Repository: mozilla/firefox-browser-architecture Branch: master Commit: f5171ada734f Files: 37 Total size: 308.2 KB Directory structure: gitextract_jxunuj8l/ ├── .gitignore ├── CODE_OF_CONDUCT.md ├── Gemfile ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── _config.yml ├── _layouts/ │ ├── default.html │ └── text.html ├── assets/ │ └── css/ │ └── style.scss ├── experiments/ │ ├── 2017-09-06-rust-on-ios.md │ └── 2017-09-21-rust-on-android.md ├── newsletter/ │ └── _posts/ │ ├── 2017-07-27-browser-architecture-update.md │ ├── 2017-08-24-browser-architecture-newsletter-2.md │ ├── 2017-09-22-browser-architecture-newsletter-3.md │ ├── 2017-10-19-browser-architecture-newsletter-4.md │ └── 2017-11-29-browser-architecture-newsletter-5.md ├── newsletters.xml └── text/ ├── 0000-template.md ├── 0001-documenting-output.md ├── 0002-extracting-necko.md ├── 0003-problems-with-xul.md ├── 0004-xbl-web-components.md ├── 0005-problems-with-xbl.md ├── 0006-architecture-review-process.md ├── 0007-xbl-design-review-packet.md ├── 0008-sync-and-storage-review-packet.md ├── 0009-type-safety-systems.md ├── 0010-firefox-data-stores.md ├── 0011-fluent-in-prefs-design-review.md ├── 0012-jsonfile.md ├── 0012-process-isolation-in-firefox.md ├── 0013-ipc-security-models-and-status.md ├── 0014-xul-overlay-removal-review-packet.md ├── 0015-rkv.md ├── 0016-xulstore-rkv-poc.md └── 0017-lmdb-vs-leveldb.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Created by https://www.gitignore.io/api/vim,node,grunt,emacs,gitbook,eclipse,jetbrains,visualstudiocode ### Eclipse ### .metadata bin/ tmp/ *.tmp *.bak *.swp *~.nib local.properties .settings/ .loadpath .recommenders # External tool builders .externalToolBuilders/ # Locally stored "Eclipse launch configurations" *.launch # PyDev specific (Python IDE for Eclipse) *.pydevproject # CDT-specific (C/C++ Development Tooling) .cproject # Java annotation processor (APT) .factorypath # PDT-specific (PHP Development Tools) .buildpath # sbteclipse plugin .target # Tern plugin .tern-project # TeXlipse plugin .texlipse # STS (Spring Tool Suite) .springBeans # Code Recommenders .recommenders/ # Scala IDE specific (Scala & Java development for Eclipse) .cache-main .scala_dependencies .worksheet ### Eclipse Patch ### # Eclipse Core .project # JDT-specific (Eclipse Java Development Tools) .classpath ### Emacs ### # -*- mode: gitignore; -*- *~ \#*\# /.emacs.desktop /.emacs.desktop.lock *.elc auto-save-list tramp .\#* # Org-mode .org-id-locations *_archive # flymake-mode *_flymake.* # eshell files /eshell/history /eshell/lastdir # elpa packages /elpa/ # reftex files *.rel # AUCTeX auto folder /auto/ # cask packages .cask/ dist/ # Flycheck flycheck_*.el # server auth directory /server/ # projectiles files .projectile # directory configuration .dir-locals.el ### GitBook ### # Node rules: ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt ## Dependency directory ## Commenting this out is preferred by some people, see ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git node_modules # Book build output _book # eBook build output *.epub *.mobi *.pdf ### grunt ### # Grunt usually compiles files inside this directory # Grunt usually preprocesses files such as coffeescript, compass... inside the .tmp directory .tmp/ ### JetBrains ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff: .idea/**/workspace.xml .idea/**/tasks.xml .idea/dictionaries # Sensitive or high-churn files: .idea/**/dataSources/ .idea/**/dataSources.ids .idea/**/dataSources.xml .idea/**/dataSources.local.xml .idea/**/sqlDataSources.xml .idea/**/dynamic.xml .idea/**/uiDesigner.xml # Gradle: .idea/**/gradle.xml .idea/**/libraries # CMake cmake-build-debug/ # Mongo Explorer plugin: .idea/**/mongoSettings.xml ## File-based project format: *.iws ## Plugin-specific files: # IntelliJ /out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Cursive Clojure plugin .idea/replstate.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties ### JetBrains Patch ### # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 # *.iml # modules.xml # .idea/misc.xml # *.ipr # Sonarlint plugin .idea/sonarlint ### Node ### # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # Typescript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env ### Vim ### # swap [._]*.s[a-v][a-z] [._]*.sw[a-p] [._]s[a-v][a-z] [._]sw[a-p] # session Session.vim # temporary .netrwhist # auto-generated tag files tags ### VisualStudioCode ### .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .history # End of https://www.gitignore.io/api/vim,node,grunt,emacs,gitbook,eclipse,jetbrains,visualstudiocode # JOE: Added manually .idea/ # Jekyll: Added manually .sass-cache _site Gemfile.lock ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Community Participation Guidelines This repository is governed by Mozilla's code of conduct and etiquette guidelines. For more details, please read the [Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). ## How to Report For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page. ================================================ FILE: Gemfile ================================================ source "https://rubygems.org" gem 'github-pages', group: :jekyll_plugins ================================================ FILE: ISSUE_TEMPLATE.md ================================================ This repository is for documentation about the Firefox Architectural Change program. It's not a place to raise bugs about Firefox itself. * If you have found a bug in Firefox please start here: https://bugzilla.mozilla.org/enter_bug.cgi * If you want to give broader feedback: https://input.mozilla.org/ * If you have a website that doesn't work properly in Firefox: https://webcompat.com/ ================================================ FILE: LICENSE ================================================ Mozilla Public License Version 2.0 ================================== 1. Definitions -------------- 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or (b) any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions -------------------------------- 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: (a) for any code that a Contributor has removed from Covered Software; or (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities ------------------- 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation --------------------------------------------------- If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination -------------- 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ************************************************************************ * * * 6. Disclaimer of Warranty * * ------------------------- * * * * Covered Software is provided under this License on an "as is" * * basis, without warranty of any kind, either expressed, implied, or * * statutory, including, without limitation, warranties that the * * Covered Software is free of defects, merchantable, fit for a * * particular purpose or non-infringing. The entire risk as to the * * quality and performance of the Covered Software is with You. * * Should any Covered Software prove defective in any respect, You * * (not any Contributor) assume the cost of any necessary servicing, * * repair, or correction. This disclaimer of warranty constitutes an * * essential part of this License. No use of any Covered Software is * * authorized under this License except under this disclaimer. * * * ************************************************************************ ************************************************************************ * * * 7. Limitation of Liability * * -------------------------- * * * * Under no circumstances and under no legal theory, whether tort * * (including negligence), contract, or otherwise, shall any * * Contributor, or anyone who distributes Covered Software as * * permitted above, be liable to You for any direct, indirect, * * special, incidental, or consequential damages of any character * * including, without limitation, damages for lost profits, loss of * * goodwill, work stoppage, computer failure or malfunction, or any * * and all other commercial damages or losses, even if such party * * shall have been informed of the possibility of such damages. This * * limitation of liability shall not apply to liability for death or * * personal injury resulting from such party's negligence to the * * extent applicable law prohibits such limitation. Some * * jurisdictions do not allow the exclusion or limitation of * * incidental or consequential damages, so this exclusion and * * limitation may not apply to You. * * * ************************************************************************ 8. Litigation ------------- Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous ---------------- This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License --------------------------- 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice ------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. ================================================ FILE: README.md ================================================ # Firefox Browser Architecture ## Mission Change Mozilla. Investigate big technical challenges and produce engineering programs to address them. ## Our Conclusions This is a list of our findings that we're reasonably happy with so far. * [Documenting our output](text/0001-documenting-output.md) looks at how we’re going to communicate with the rest of Mozilla. * [Extracting Necko](text/0002-extracting-necko.md) considers whether it's feasible or worthwhile to extract Necko — Gecko's C++ networking library — for use as a standalone component. * [Problems with XUL](text/0003-problems-with-xul.md) aims to list the different kinds of problems that exist with XUL. * [XBL and Web Components](text/0004-xbl-web-components.md) compares some old Mozilla technology (XBL) with modern Web Components. * [Problems with XBL](text/0005-problems-with-xbl.md) aims to list the different kinds of problems that exist with XBL. * [Architecture Reviews](text/0006-architecture-review-process.md) are healthy and we proposed a process for healthy reviews. * [XBL Design Review packet](text/0007-xbl-design-review-packet.md) is the packet that we prepared for the architectural design review for XBL removal. * [Roadmap Review: Sync and Storage](text/0008-sync-and-storage-review-packet.md) establishes that storage and syncing of user data is a pillar of the Firefox ecosystem, warranting holistic and long-term attention, and outlines where we’d like to end up and some ideas for how to get there. * [JavaScript Type Safety Systems](text/0009-type-safety-systems.md) are some conclusions of an investigation into the use of JavaScript type safety systems. * [Firefox Data Stores Documentation](text/0010-firefox-data-stores.md) documents the existing data stores across all current Firefox platforms. * [Fluent in Prefs Design Review](text/0011-fluent-in-prefs-design-review.md) describes the lightweight design review for Fluent in Prefs. * [A brief analysis of JSON file-backed storage](text/0012-jsonfile.md) outlines some of the pros and cons of using a flat file (particularly via `JSONFile.jsm`) to store data in Firefox. * [Process Isolation in Firefox](text/0012-process-isolation-in-firefox.md) is a WIP evaluation of how far we can push process isolation to improve security and stability. * [IPC Security Models and Status](text/0013-ipc-security-models-and-status.md) is an audit of our current IPC status. * [XUL Overlay Removal Review Packet](text/0014-xul-overlay-removal-review-packet.md) is the packet that we prepared for the architectural design review for XUL Overlay removal. * [Design Review: Key-Value Storage](text/0015-rkv.md) proposes the introduction of a fast, cross-platform key-value store for Mozilla products. * [XULStore Using rkv – Proof of Concept](text/0016-xulstore-rkv-poc.md) describes a proof-of-concept implementation of XULStore that uses [rkv](https://github.com/mozilla/rkv). * [LMDB vs. LevelDB](text/0017-lmdb-vs-leveldb.md) compares the [Lightning Memory-mapped Database](https://symas.com/lmdb/) (LMDB) key-value storage engine to the [LevelDB](https://github.com/google/leveldb) key-value storage engine. ## Posts We typically send our newsletters to [firefox-dev](https://www.mozilla.org/en-US/about/forums/#firefox-dev). * [Browser Architecture Update](newsletter/_posts/2017-07-27-browser-architecture-update.md). See also [mailing-list-post](https://groups.google.com/forum/#!topic/firefox-dev/ueRILL2ppac). * [Browser Architecture Newsletter #2](newsletter/_posts/2017-08-24-browser-architecture-newsletter-2.md). See also [mailing-list-post](https://groups.google.com/forum/#!topic/firefox-dev/Rc2w2a9e8HQ). * [Browser Architecture Newsletter #3](newsletter/_posts/2017-09-22-browser-architecture-newsletter-3.md). See also [mailing-list-post](https://groups.google.com/forum/#!topic/firefox-dev/p9rTlfFUXlQ). * [Browser Architecture Newsletter #4](newsletter/_posts/2017-10-19-browser-architecture-newsletter-4.md). See also [mailing-list-post](https://groups.google.com/forum/#!topic/firefox-dev/CLFtj8qUSv8). * [Browser Architecture Newsletter #5](newsletter/_posts/2017-11-29-browser-architecture-newsletter-5.md). See also [mailing-list-post](https://groups.google.com/forum/#!topic/firefox-dev/XKp3EthdJ60). ## Explorations and Experiments To support our conclusions we occasionally perform explorations and experiments. The first exploration is designed to support the notion that we can create a sync and storage layer in Rust that we can deploy to Desktop, Android and iOS. * [Deploying a Rust library on iOS](experiments/2017-09-06-rust-on-ios.md). A short tutorial describing how to build and deploy a Rust library for use inside an iOS app. * [Deploying a Rust library on Android](experiments/2017-09-21-rust-on-android.md). A short tutorial describing how to build and deploy a Rust library for use inside an Android app. # Community Participation Guidelines This repository is governed by Mozilla's code of conduct and etiquette guidelines. For more details, please read the [Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). ## How to Report For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page. ================================================ FILE: _config.yml ================================================ theme: jekyll-theme-minimal baseurl: /firefox-browser-architecture ================================================ FILE: _layouts/default.html ================================================ {{ page.title }}
{{ content }}
================================================ FILE: _layouts/text.html ================================================ {{ page.title }}

[Back to top]

{{ content }}

[Back to top]

================================================ FILE: assets/css/style.scss ================================================ --- --- @import "{{ site.theme }}"; @import url('https://fonts.googleapis.com/css?family=Zilla+Slab|Zilla+Slab+Highlight'); // Convert pixel units to rems, assuming a 16px base size // Usage: remify(24px) @function remify($pixels) { $rems: $pixels / 16px; @return #{$rems}rem; } @mixin font-size($size) { // When unit is pixels, pass it through and convert to rem @if (unit($size) == 'px') { font-size: $size; font-size: remify($size); } // When unit is not pixels, show an error @else { @error 'This mixin only accepts sizes in pixels. You declared `font-size(#{$size})`.'; } } @mixin font-size-huge { // For especially huge titles @include font-size(50px); @media screen and (min-width: 760px) { @include font-size(90px); } } @mixin font-size-level1 { @include font-size(28px); @media screen and (min-width: 760px) { @include font-size(50px); } } @mixin font-size-level2 { @include font-size(21px); @media screen and (min-width: 760px) { @include font-size(38px); } } @mixin font-size-level3 { @include font-size(18px); @media screen and (min-width: 760px) { @include font-size(28px); } } @mixin font-size-level4 { @include font-size(16px); @media screen and (min-width: 760px) { @include font-size(21px); } } body { background: #fff; font-size: 20px; font-family: "Zilla Slab", "Open Sans", X-LocaleSpecific, sans-serif; line-height: 1.5; } h1, h2, h3, h4, h5, h6, legend { color: #000; font-weight: bold; line-height: 1.1; margin: 0 0 .25em; } h1 { @include font-size-level1; } h2 { @include font-size-level2; } h3 { @include font-size-level3; } h4 { @include font-size-level4; } h5, h6 { @include font-size(16px); } p, ul, ol, dl, table { margin-bottom: 1.25em; } a { color: #006688; } a:hover, a:focus, a:active, a:visited:hover, a:visited:focus, a:visited:active { color: #0088aa; font-weight: normal; } a:visited { color: #004455; } .wrapper > section { float: none; width: 100%; } ================================================ FILE: experiments/2017-09-06-rust-on-ios.md ================================================ --- title: Building and Deploying a Rust library on iOS layout: text --- # Building and Deploying a Rust library on iOS First, we have to [install Xcode](https://itunes.apple.com/us/app/xcode/id497799835?ls=1&mt=12) and then set up Xcode build tools. If you already have the build tools installed and they are up to date, you can skip this step. ``` xcode-select --install ``` Next, we need to ensure that Rust is installed and that we can cross compile to the iOS architectures. For this we will be using [rustup](https://www.rustup.rs/). If you already have rustup installed, you can skip this step. Rustup installs Rust from the official release channels and enables you to easily switch between different release versions. It will be useful to you for all your future Rust development, not just here. ``` curl https://sh.rustup.rs -sSf | sh ``` Add the iOS architectures to rustup so we can use them during cross compilation. ``` rustup target add aarch64-apple-ios armv7-apple-ios armv7s-apple-ios x86_64-apple-ios i386-apple-ios ``` When you installed Rust, it also installed cargo, which is a package manager similar to pip, gems etc. Now we will use cargo to install `cargo-lipo`. This is a cargo subcommand which automatically creates a universal library for use with iOS. Without this crate, cross compiling Rust to work on iOS is infinitely harder. ``` cargo install cargo-lipo ``` Now we're all setup and we're ready to start. Let's create the project directory. ``` mkdir greetings cd greetings cargo new cargo mkdir ios ``` `cargo new cargo` sets up a brand new Rust project with its default files and directories in a directory called `cargo`. In this directory is a file called `Cargo.toml`, which is the package manager descriptor file, and there is be a subdirectory, `src`, which contains a file called `lib.rs`. This will contain the Rust code that we will be executing. Our Rust project here is a super simple Hello World library. It contains a function `rust_greeting` that takes a string argument and return a string greeting that argument. Therefore, if the argument is "world", the returned string is "Hello world". Open `cargo/src/lib.rs` and enter the following code. ```rust use std::os::raw::{c_char}; use std::ffi::{CString, CStr}; #[no_mangle] pub extern fn rust_greeting(to: *const c_char) -> *mut c_char { let c_str = unsafe { CStr::from_ptr(to) }; let recipient = match c_str.to_str() { Err(_) => "there", Ok(string) => string, }; CString::new("Hello ".to_owned() + recipient).unwrap().into_raw() } #[no_mangle] pub extern fn rust_greeting_free(s: *mut c_char) { unsafe { if s.is_null() { return } CString::from_raw(s) }; } ``` Let's take a look at what is going on here. As we will be calling this library from non-Rust code, we will actually be calling it through a C bridge.`#[no_mangle]` tells the compiler not to mangle the function name as it usually does by default, ensuring our function name is exported as if it had been written in C. `extern` tells the Rust compiler that this function will be called from outside of Rust and to therefore ensure that it is compiled using C calling conventions. The string that `rust_greeting` accepts is a pointer to a C char array. We have to then convert the string from a C string to a Rust `str`. First we create a `CStr` object from the pointer. We then convert it to a `str` and check the result. If an error has occurred, then no arg was provided and we substitute `there`, otherwise we use the value of the provided string. We then append the provided string on the end of our greeting string to create our return string. The return string is then converted into a `CString` and passed back into C code. Using `CString` and returning the raw representation keeps the string in memory and prevents it from being released at the end of the function. If the memory were to be released, the pointer provided back to the caller would now be pointing to empty memory - or possibly something else entirely. But, by ensuring that the string sticks around after the function has finished executing, we have memory allocated and no longer any handle to it. That is a recipe for a memory leak, so we have to provide a second function `rust_greeting_free` that takes a pointer to a C string and frees that memory. We will have to remember to call `rust_greeting_free` from our iOS code to ensure we don't run into problems. We also need to create our C bridge. Create a new file in `cargo/src` called `greetings.h`. Inside that file, let's define what our C interface will look like. We need to ensure that every rust function that we want to call from iOS is defined here. ```C #include const char* rust_greeting(const char* to); void rust_greeting_free(char *); ``` Let's build our code to make sure it works. In order to do this we have to complete our `Cargo.toml` file. This will tell cargo to create a static library and C dynamic library for our code. ```toml [package] name = "greetings" version = "0.1.1" authors = ["fluffyemily "] description = "Example static library project built for iOS" publish = false [lib] name = "greetings" crate-type = ["staticlib", "cdylib"] ``` We need to build our library against the iOS architectures using `cargo-lipo`. The built artifacts of will be placed in `cargo/target/`. The universal iOS library that we are interested in can be found in `cargo/target/universal/release/libgreetings.a`. ``` cd cargo cargo lipo --release ``` And that's it for our Rust library. Let's get it linked with an iOS project. Open Xcode and create a new project. Go to `File\New\Project…` and select the `iOS\Application\Single View Application` template. This template is as close to a default iOS app as it gets. Click `Next`. ![Create new Swift project](assets/2017-09-06-rust-on-ios/new-project.png) Call the project `Greetings`, make it a Swift project. Click `Next` to choose the location. We are using the ios directory that we created earlier. If you choose another location you will have to amend some of the paths that we set later. Click `Create`. ![Name project](assets/2017-09-06-rust-on-ios/name-project.png) Select the Greetings project from the project navigator, and then ensure the Greetings target is selected. Open the `General` tab. Scroll down to the `Linked Frameworks and Libraries` section. ![Link rust library](assets/2017-09-06-rust-on-ios/link-libs.png) Import your `libgreetings.a` library by either dragging it in from finder, or clicking the + at the bottom of the list, clicking 'Add other...' and navigating to `cargo/target/universal/release/`. Select `libgreetings.a` and then click `Open`. Link `libresolv.tbd`. Click the + at the bottom of the Linked Frameworks list and type libresolv into the search box. Select `libresolv.tbd` and then "Add". ![Link libresolv](assets/2017-09-06-rust-on-ios/link-libresolv.png) iOS will need a bridging header to access the C header we created. First, let's import `greetings.h` into our Xcode project so we can link to it. Go to `File\Add files to "Greetings"...` Navigate to `greetings.h` and select `Add`. To create our bridging header, go to `File\New\File...`. Select `iOS\Source\Header File` from the provided options and select `Next`. Name the file `Greetings-Bridging-Header.h` and select `Create`. ![Create bridging header](assets/2017-09-06-rust-on-ios/bridging-header.png) Open the bridging header and amend it to look like the following: ```C #ifndef Greetings_Bridging_Header_h #define Greetings_Bridging_Header_h #import "greetings.h" #endif ``` We need to tell Xcode about the bridging header. Select the Greetings project from the project navigator, and then ensure the Greetings target is selected and open the Build Settings tab. Set the `Objective-C Bridging Header` option value to `$(PROJECT_DIR)/Greetings/Greetings-Bridging-Header.h` ![Set bridging header location](assets/2017-09-06-rust-on-ios/build-settings-header.png) We also need to tell Xcode where to look for our libraries for linking. In the same Build Settings pane, amend the `Library Search Paths` option value to `$(PROJECT_DIR)/../../cargo/target/universal/release` ![Link Library Search Paths](assets/2017-09-06-rust-on-ios/build-settings-search-paths.png) Build your xcode project and everything should compile. So, now we have imported our Rust library into our iOS project and successfully linked to it. But we still need to call it. go to `File\New\File...`. Select `iOS\Source\Swift File` from the provided options and select `Next`. Name name it `RustGreetings`. ![Create new Swift file](assets/2017-09-06-rust-on-ios/new-swift.png) Add the following code: ```swift class RustGreetings { func sayHello(to: String) -> String { let result = rust_greeting(to) let swift_result = String(cString: result!) rust_greeting_free(UnsafeMutablePointer(mutating: result)) return swift_result } } ``` This creates a new class that we will use as an interface to call into our Rust library. This will allow us to abstract the nuance away from the main code of the app, including conversion from a C String to a Swift String and ensures that we won't forget to call our free function and inadvertently introduce a memory leak! Open `ViewController.swift`. Inside the `viewDidLoad` function add the following code: ```swift let rustGreetings = RustGreetings() print("\(rustGreetings.sayHello(to: "world"))") ``` Now build your project and run. The simulator will open and start running your app. When the view loads, "Hello world" will be output in the console window inside Xcode. You can find the code for this on [Github](https://github.com/fluffyemily/cross-platform-rust) ================================================ FILE: experiments/2017-09-21-rust-on-android.md ================================================ --- title: Building and Deploying a Rust library on Android layout: text --- # Building and Deploying a Rust library on Android Following on from the last post on getting a Rust library [building on iOS](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html), we're now going to deploy the same library on Android. In order to do Android development, we'll need to set up our Android environment. First we need to install [Android Studio](https://developer.android.com/studio/index.html). Once Android Studio is installed, we'll need to install the NDK (Native Development Kit). Open Android Studio. From the toolbar, go to `Android Studio > Preferences > Appearance & Behaviour > Android SDK > SDK Tools`. Check the following options for installation and click `OK`. * Android SDK Tools * NDK * CMake * LLDB Once the NDK and associated tools have been installed, we need to set a few environment variables, first for the SDK path and the second for the NDK path. Set the following envvars: ``` export ANDROID_HOME=/Users/$USER/Library/Android/sdk export NDK_HOME=$ANDROID_HOME/ndk-bundle ``` If you do not already have Rust installed, we need to do this now. For this we will be using [rustup](https://www.rustup.rs/). `rustup` installs Rust from the official release channels and enables you to easily switch between different release versions. It will be useful to you for all your future Rust development, not just here. `rustup` can also be used in conjunction with `HomeBrew`. ``` curl https://sh.rustup.rs -sSf | sh ``` The next step is to create standalone versions of the NDK for us to compile against. We need to do this for each of the architectures we want to compile against. We will be using the `make_standalone_toolchain.py` script inside the main Android NDK in order to do this. First create a directory for our project. ``` mkdir greetings cd greetings ``` Now let's create our standalone NDKs. There is no need to be inside the `NDK` directory once you have created it to do this. ``` mkdir NDK ${NDK_HOME}/build/tools/make_standalone_toolchain.py --api 26 --arch arm64 --install-dir NDK/arm64 ${NDK_HOME}/build/tools/make_standalone_toolchain.py --api 26 --arch arm --install-dir NDK/arm ${NDK_HOME}/build/tools/make_standalone_toolchain.py --api 26 --arch x86 --install-dir NDK/x86 ``` Create a new file, `cargo-config.toml`. This file will tell cargo where to look for the NDKs during cross compilation. Add the following content to the file, remembering to replace instances of `` with the path to your project directory. ``` [target.aarch64-linux-android] ar = "/greetings/NDK/arm64/bin/aarch64-linux-android-ar" linker = "/greetings/NDK/arm64/bin/aarch64-linux-android-clang" [target.armv7-linux-androideabi] ar = "/greetings/NDK/arm/bin/arm-linux-androideabi-ar" linker = "/greetings/NDK/arm/bin/arm-linux-androideabi-clang" [target.i686-linux-android] ar = "/greetings/NDK/x86/bin/i686-linux-android-ar" linker = "/greetings/NDK/x86/bin/i686-linux-android-clang" ``` In order for `cargo` to see our new SDK's we need to copy this config file to our `.cargo` directory like this: ``` cp cargo-config.toml ~/.cargo/config ``` Let's go ahead and add our newly created Android architectures to `rustup` so we can use them during cross compilation: ``` rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android ``` Now we're all set up and we're ready to start. Let's create the `lib` directory. If you've already created a Rust project from following the iOS post, you don't need to do it again. ``` cargo new cargo mkdir android ``` `cargo new cargo` sets up a brand new Rust project with its default files and directories in a directory called `rust`. The name of the directory is not important. In this directory is a file called `Cargo.toml`, which is the package manager descriptor file, and there is be a subdirectory, `src`, which contains a file called `lib.rs`. This will contain the Rust code that we will be executing. Our Rust project here is a super simple Hello World library. It contains a function `rust_greeting` that takes a string argument and return a greeting including that argument. Therefore, if the argument is "world", the returned string is "Hello world". Open `cargo/src/lib.rs` and enter the following code. ```rust use std::os::raw::{c_char}; use std::ffi::{CString, CStr}; #[no_mangle] pub extern fn rust_greeting(to: *const c_char) -> *mut c_char { let c_str = unsafe { CStr::from_ptr(to) }; let recipient = match c_str.to_str() { Err(_) => "there", Ok(string) => string, }; CString::new("Hello ".to_owned() + recipient).unwrap().into_raw() } ``` Let's take a look at what is going on here. As we will be calling this library from non-Rust code, we will actually be calling it through a C bridge. `#[no_mangle]` tells the compiler not to mangle the function name as it usually does by default, ensuring our function name is exported as if it had been written in C. `extern` tells the Rust compiler that this function will be called from outside of Rust and to therefore ensure that it is compiled using C calling conventions. The string that `rust_greeting` accepts is a pointer to a C char array. We have to then convert the string from a C string to a Rust `str`. First we create a `CStr` object from the pointer. We then convert it to a `str` and check the result. If an error has occurred, then no arg was provided and we substitute `there`, otherwise we use the value of the provided string. We then append the provided string on the end of our greeting string to create our return string. The return string is then converted into a `CString` and passed back into C code. Now let's create our Android project. Open Android Studio and select `Start a New Android Project` from the options. ![Create new Android project](assets/2017-09-21-rust-on-android/new-project.png) On the next screen, type a project name of `Greetings` into the `Application name` field, choose your `Company domain` and select the `android` directory we created earlier as the `Project location`. This will create your Android project inside `greetings/android/Greetings`. Click `Next`. ![Name project](assets/2017-09-21-rust-on-android/name-project.png) On the next screen, make sure the `Phone and Tablet` option is selected. Click `Next`. ![Choose form factor](assets/2017-09-21-rust-on-android/form-factors.png) Now we will be asked to choose a starting activity. Select the `Empty Activity` option and click `Next`. ![Choose starting activity](assets/2017-09-21-rust-on-android/add-activity.png) Name your Activity and layout on the following screen, calling the activity `GreetingsActivity` and the layout `activity_greetings`. Click `Finish`. ![Name activity](assets/2017-09-21-rust-on-android/customize-activity.png) As with iOS, we're going to create a wrapper class to wrap the C API and JNI bindings. In the project explorer on the left hand side of the studio window, ensure that `app > java > .greetings` is highlighted then go to `File > New > Java Class`. Name your class `RustGreetings` and click `OK`. ![Create new class](assets/2017-09-21-rust-on-android/new-class.png) In your new class file, add the following code. Here we are defining the native interface to our Rust library and calling it `greeting`, with the same signature. The `sayHello` method simply makes a call to that native function. ```java public class RustGreetings { private static native String greeting(final String pattern); public String sayHello(String to) { return greeting(to); } } ``` Instead of creating C header that will be used as a bridge as we did when we wanted to integrate with Swift, for Android we want to expose our functions through JNI. The way that JNI constructs the name of the function that it will call is `Java___`. In the case of the method, `greeting` that we have declared here, the function in our Rust library that JNI will attempt to call will be `Java_com_mozilla_greetings_RustGreetings_greeting`. This is the reason why we created our Android project and Java wrapper class before adding any JNI code to the Rust library. We needed to know what the domain, class and function name were before we could construct the right JNI function name in Rust. Let's head back over to our Rust project and create the partner code. Open `cargo/src/lib.rs`. At the bottom of the file add the following code: ```rust /// Expose the JNI interface for android below #[cfg(target_os="android")] #[allow(non_snake_case)] pub mod android { extern crate jni; use super::*; use self::jni::JNIEnv; use self::jni::objects::{JClass, JString}; use self::jni::sys::{jstring}; #[no_mangle] pub unsafe extern fn Java_com_mozilla_greetings_RustGreetings_greeting(env: JNIEnv, _: JClass, java_pattern: JString) -> jstring { // Our Java companion code might pass-in "world" as a string, hence the name. let world = rust_greeting(env.get_string(java_pattern).expect("invalid pattern string").as_ptr()); // Retake pointer so that we can use it below and allow memory to be freed when it goes out of scope. let world_ptr = CString::from_raw(world); let output = env.new_string(world_ptr.to_str().unwrap()).expect("Couldn't create java string!"); output.into_inner() } } ``` The first line here `#[cfg(target_os="android")]` is telling the compiler to target Android when compiling this module. `#[cfg]` is a special attribute that allows you to compile code based on a flag passed to the compiler. The second line, `#[allow(non_snake_case)]`, tells the compiler not to warn if we are not using `snake_case` for a variable or function name. The Rust compiler is very strict — this is one of the things that makes Rust great — and it enforces the use of `snake_case` throughout. However, we defined our class name and native method in our Android project using Java coding conventions which is `camelCase` and `UpperCamelCase` and we don't want to change this or our Java code will look wrong. Given the way that JNI constructs native function names, we need to tell the Rust compiler to go easy on us in this instance. This flag will apply to all functions and variables created inside this module that we are creating, called `android`. After declaring that we need the `jni` crate, and importing some useful objects from it, we can declare our function. This function needs to be marked `unsafe` because we will be dealing with pointers from a language that allows null pointers, but our code doesn't check for `NULL`. This situation would never happen in Rust only code as the Rust compiler enforces memory safety. By marking the function as not memory safe, we are alerting other Rust functions that it may not be able to deal with a null pointer. `extern` defines the function as one that will be exposed to other languages. As arguments, along with the `JString` that our Java function declaration said that we will be providing, we also need to take an instance of the `JNIEnv` and a class reference (which is unused in this example). The `JNIEnv` will be the object we will use to read values associated with the pointers that we are taking as argument. Next, we read the string in from the `JNIEnv` and convert it into a C pointer to pass to `rust_greeting`. The result of that function is another C pointer, which we then need to convert to a back into a String. Using the `JNIEnv` transfers the ownership of the object to Java, but there is still a reference hanging around held by our Rust code. That memory will be freed as `world_ptr` goes out of scope. Then we return our String. We declared that we needed the `jni` crate, that means we need to include the crate in the `Cargo.toml` file. Open it up and add the following between the `[package]` and `[lib]` declarations. ``` [target.'cfg(target_os="android")'.dependencies] jni = { version = "0.5", default-features = false } ``` We also need to tell the compiler what type of a library it should produce. You can specify this in the `Cargo.toml` file's `[lib]` section: ``` [lib] crate-type = ["dylib"] ``` We are now ready to build our libraries. Unlike with iOS, there is no handy universal Android library that we can make so we have to create one for each of our target architectures. We can then create symlinks to them from the Android project. You will need to use absolute paths to your libraries here, not relative ones, otherwise Android Studio will not be able to follow the link. Navigate to your `cargo` directory and run the following commands: ``` cargo build --target aarch64-linux-android --release cargo build --target armv7-linux-androideabi --release cargo build --target i686-linux-android --release cd ../android/Greetings/app/src/main mkdir jniLibs mkdir jniLibs/arm64 mkdir jniLibs/armeabi mkdir jniLibs/x86 ln -s /greetings/cargo/target/aarch64-linux-android/release/libgreetings.so jniLibs/arm64/libgreetings.so ln -s /greetings/cargo/target/armv7-linux-androideabi/release/libgreetings.so jniLibs/armeabi/libgreetings.so ln -s /greetings/cargo/target/i686-linux-android/release/libgreetings.so jniLibs/x86/libgreetings.so ``` Now, head back to Android Studio and open `GreetingsActivity.java`. We need to load our Rust library when the app starts, so add the following lines below the class declaration and before the `onCreate` method. ```java static { System.loadLibrary("greetings"); } ``` This looks for a library called `greetings.so` inside the jniLibs directory and picks the correct one for the current architecture. Open `res/layout/activity-greetings.xml`. In the `Component Tree` panel, highlight the `TextField` and open the `Properties` panel. Change the `ID` in the `Properties` panel to `greetingField`. This is how we are going to refer to it from our Activity. ![Amend activity xml](assets/2017-09-21-rust-on-android/activity-greetings.png) Reopen `GreetingsActivity.java` and amend the `onCreate` method to call our greetings function and set the text on the `greetingField` `TextField` to the response value. ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_greetings); RustGreetings g = new RustGreetings(); String r = g.sayHello("world"); ((TextView)findViewById(R.id.greetingField)).setText(r); } ``` Build and run the app. If this is your first time in Android Studio, you may need to set up a simulator. When choosing/creating your simulator pick one with API 26. When the app starts, `Hello world` will be printed on your screen. You can find the code for this on [Github](https://github.com/fluffyemily/cross-platform-rust). ================================================ FILE: newsletter/_posts/2017-07-27-browser-architecture-update.md ================================================ --- title: Browser Architecture Update layout: text description: The first of our newsletters introducing our work mailinglist: https://groups.google.com/d/msg/firefox-dev/ueRILL2ppac/RxR9lLPkAwAJ --- # Browser Architecture Update [Link to mailing-list archive]({{ page.mailinglist }}) In the spirit of the Quantum Flow and Photon Newsletters - an update on what the Browser Architecture team is doing: The Browser Architecture Team is new-ish - it’s existed since the re-org earlier this year, and its goal is to look ahead and make plans for our architecture. We want to build the world’s best web browsers. Which is easy to say, but much harder to actually do. mozilla-central is a big complex software project. Its size and complexity slows us down, and it’s daunting to think about making it easier to reason about. We’ve often put off making life easy for ourselves because our users come first. We generally prioritize fixing bugs for users over internal work. But sometimes you can go faster for users by focusing on going faster yourself. Part of what the Browser Architecture team would like is to tackle some of the hard problems of our own development velocity. We also need to look at some problems that will take several years to address. Problems that don’t fit into any project area roadmap. We have a mandate to help build the world’s best web browsers, but how? Our strategy is twofold: 1. Kickstart a streamlined developer experience by removing roadblocks to immediate progress. 2. Consciously plan our software architecture at an organization-wide level. So what are the specific problems we are looking at? ## Workflow UI development in mozilla-central somewhat mirrors the web development ecosystem, however one way we’ve fallen behind is in unit tests for frontend code. In mozilla-central we usually rely on integration tests rather than unit tests. Integration tests end up being slower and are more likely to fail randomly. In addition they steal focus and don’t allow for integration with code editors, to see test results as you type. We’d like to figure out how to write more unit tests in our codebase. We’re looking at turning headless mode into a way to continue work whilst running tests, rather than needing to run a VM or turning to sword-fighting. We’ve also spent some time looking at ways to make developing the Firefox frontend more like web development, with features like CSS hot reload and refreshing the UI without rebuilding and restarting the process. In parallel, we’re also looking at ways that we can improve Gecko development efficiency, especially on build times and debugging (Rust, rr, gdb on Mac). ## XUL and XBL Our user interface language has problems. It’s uncared for, so it’s buggy and sometimes we don’t land fixes that we know about. It’s largely undocumented or worse, documented wrongly, so it’s hard to fix. Also it behaves almost like the web, which can lead web developers to think they understand it better than they really do. We care about HTML, so that’s documented and optimized. XUL? Not so much. The first talk I heard about Servo was in 2013. At the Q&A at the end someone asked about XUL and Servo — the answer was "There is no XUL in the product at all". Applause from audience. So the tide has been against XUL for at least 4 years, but so far we’ve not made headway in tackling it. The Browser Architecture team is approaching it from various angles: Can we remove XUL and XBL piece by piece? We are experimenting with a couple of approaches with the preferences UI. Could we convert the XBL to JS modules and Web Components ‘in place’? Alternatively, how much work is it to rewrite it in HTML, using something like React? Or more dramatically, how far up the stack should our use of Rust go? Maybe we should consider a UI generated by Rust? Alternatively, what’s the minimum we could do to just fix and document what we’ve got. Perhaps we should just focus on removing XBL? Maybe the plans above are too much work and we need to invest elsewhere entirely? ## User Data Storage and Sync We don’t have a good story for storage of user data. We wouldn’t sit down to design the profile directory and come up with what we have today, and we need a better story to be able to sync more readily to Firefox for Android and iOS and to adapt to unanticipated and evolving product needs. Recently we've been exploring Project Mentat, which promised some advances in helping us rapidly evolve data storage, and making syncing of data less troublesome. We decided that porting all of Firefox’s storage to Mentat was too much work right now, but the problem of improving user data storage and sync remains. So we’re looking at the big picture of storage and sync and how we can share data not just between desktop and mobile, but also to help us develop and test new products in the market. ## A Monolithic Platform We’re considering what it would look like to turn Gecko inside out so it’s more modular, can be reused in smaller parts and is easier to test, as with Rust crates in Servo. Changing that is hard — really hard — but the potential value is also significant. We're looking at existing Firefox components and wondering if we can extract them (or rewrite them) as separate components that we could reuse in situations where we can't rely on the Gecko runtime environment, and we’re looking at the work on GeckoView to see how it can help us reuse Gecko outside Firefox. ---- There are a lot of ideas there. Maybe some sound cool, maybe some sound crazy. We’re planning on writing up our findings on each of the areas so look out for future posts where we drill down into some of these ideas. Thanks Joe Walker (on behalf of the Browser Architecture Team) Feedback is welcome. Either reply here or find Nick Alexander, Brendan Dahl, Brian Grinstead, Rob Helmer, Randell Jesup, Myk Melez, Richard Newman, Victor Porof, Emily Toop, Dave Townsend, Peter Van Der Beken, or Joe Walker near some watercooler (like #browser-arch). ================================================ FILE: newsletter/_posts/2017-08-24-browser-architecture-newsletter-2.md ================================================ --- title: Browser Architecture Newsletter 2 layout: text description: A follow-up with updates on XBL Conversion, Storage and Sync and Workflow Improvements mailinglist: https://groups.google.com/d/msg/firefox-dev/ueRILL2ppac/RxR9lLPkAwAJ --- # Browser Architecture Newsletter 2 [Link to mailing-list archive]({{ page.mailinglist }}) Welcome to the second Browser Architecture Newsletter! Since our [last update](https://groups.google.com/forum/#!msg/firefox-dev/ueRILL2ppac/RxR9lLPkAwAJ;context-place=forum/firefox-dev), we have a [new website](https://mozilla.github.io/firefox-browser-architecture/) which includes posts about some of the [problems with XUL](https://mozilla.github.io/firefox-browser-architecture/text/0003-problems-with-xul.html), [extracting Necko](https://mozilla.github.io/firefox-browser-architecture/text/0002-extracting-necko.html) as a standalone component, and [comparing](https://mozilla.github.io/firefox-browser-architecture/text/0004-xbl-web-components.html) XBL with Web Components. The website is built from [this GitHub repository](https://github.com/mozilla/firefox-browser-architecture) of Markdown files, and we’re using pull requests to review and revise our research proposals and analyses. Do you have ideas for improvements? File an issue on the repo or contact us in #browser-arch! ## XBL Conversion We'd like to reduce or even remove XBL and XUL from the tree. It's becoming clear that replacing XBL is more important and easier than replacing XUL, so there are a few projects ongoing to learn more about it. A conversion of the behavioral `` binding is in progress at [Bug 1379338](https://bugzilla.mozilla.org/show_bug.cgi?id=1379338). Although this work started as a prototype, it resulted in a more straightforward implementation than we currently have, so is on the path to being landed. As mentioned above, there’s some new [documentation](https://mozilla.github.io/firefox-browser-architecture/text/0004-xbl-web-components.html) comparing XBL with Web Components. There’s also a [visual tree](https://bgrins.github.io/xbl-analysis) of the bindings we use in Firefox and what features each uses. A prototype of replacing some XBL UI components in about:preferences with Custom Elements is attached to [Bug 1392367](https://bugzilla.mozilla.org/show_bug.cgi?id=1392367). This relies on a [forked version](https://github.com/webcomponents/custom-elements/compare/master...bgrins:firefox-browser-chrome?expand=1) of the [custom elements polyfill](https://github.com/webcomponents/custom-elements) made to work in XUL documents. A prototype of converting `` to a JS class is in progress at [Bug 1392352](https://bugzilla.mozilla.org/show_bug.cgi?id=1392352). This would cause gBrowser to become a JS object instead of a DOM Node. This conversion is semi-automated [by a script converting the binding to a JS class](https://github.com/bgrins/xbl-analysis/blob/ad87d682b937620b1c129e49c4081483c7074540/scripts/build-custom-elements.js). ## Storage and Sync We're in the process of cataloging and analyzing some of Firefox's sprawling storage technologies (45+ different data stores and dozens of formats on desktop alone), and how they relate to Sync and across platforms. We're hoping to find ways to make this situation simpler, more reliable, and easier to extend. You can see the beginnings of our knowledge capture [here](https://github.com/mozilla/firefox-data-store-docs) (PRs welcome!), and a [spreadsheet](http://bit.ly/2vpZI9e) showing how data types interact with Sync and mobile platforms. Huge thanks to the Sync team and data and product folks across the org for helping with our research. ## Workflow Improvements Lately I've been paying extra attention to development papercuts when working on bugs, especially issues when using ./mach run without passing a profile. Here’s a list of recent changes on that front: * You can [open the Browser Toolbox](https://groups.google.com/d/msg/firefox-dev/678mrnS6120/KXcP18ZUCAAJ) in a local build without flipping prefs. * The default browser prompt and about:config warning screen [no longer show up](https://groups.google.com/d/msg/firefox-dev/kPwA1y-7BpI/gX6rvhEjBQAJ) for the scratch_user (the profile used when you do ./mach run without a profile). * You can flip any pref for the scratch_user with the --setpref option, or by adding them in your [machrc file](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/mach#Does_mach_have_its_own_configuration_file). For example, to make sure I always see dump output I added this to my ~/.mozbuild/machrc file: `[runprefs] browser.dom.window.dump.enabled=true` * There’s a [new keyboard shortcut](https://groups.google.com/d/msg/firefox-dev/Tme95bp3EHY/ow-l077FAAAJ) to do a restart + session restore in local builds. * The Browser Console is [now part of session store](https://bugzilla.mozilla.org/show_bug.cgi?id=1388552), so it will reopen after using the above keyboard shortcut. ================================================ FILE: newsletter/_posts/2017-09-22-browser-architecture-newsletter-3.md ================================================ --- title: Browser Architecture Newsletter 3 layout: text description: A newsletter on architecture review, XBL Conversion, Storage and Sync, Workflow Improvements and a developer survey mailinglist: https://groups.google.com/forum/#!topic/firefox-dev/p9rTlfFUXlQ --- # Browser Architecture Newsletter 3 [Link to mailing-list archive]({{ page.mailinglist }}) Welcome to the third Browser Architecture Newsletter! Since our [last update](https://mozilla.github.io/firefox-browser-architecture/posts/2017-08-24-browser-architecture-newsletter-2.html), we've continued to investigate moving away from XBL and started to document what we're talking about when we talk about XUL problems. We're also working with members of the Sync, AS, and Lockbox teams to figure out what the future of storage and syncing looks like for Mozilla. A lot of the issues that the Browser Architecture team are digging into are larger than our team. Our goal is to discuss and review entire product level architecture issues and build consensus around solutions. We're interested in engaging with engineers around the organization. We're actively reaching out to folks but if you want to talk to us we'd sure love to hear from you. You can find us in \#browser-arch on IRC or Slack. ## Architecture Review We are asking for comments on our [proposed process](https://mozilla.github.io/firefox-browser-architecture/text/0006-architecture-review-process.html) for when our team performs architecture reviews. The process is in draft right now so if you have suggestions for how to improve it please let us know. If you've got ideas, questions, or concerns, talk to [jwalker](https://mozillians.org/en-US/u/jwalker/). ## XBL Removal We've filed a [meta bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1397874) for our de-XBL work, which includes a variety of prototypes and other investigations, including: moving XBL bindings to Custom Elements, moving XBL bindings to JS modules, and performance comparisons of XBL bindings to a custom elements polyfill. You can view all the prototypes and investigations we're working on by viewing the meta bug's dependencies. We're getting ready to run through a design review for our XBL replacement plans. The review will be chaired by Dave Townsend and include a panel of experts on both Gecko and Firefox. The review process itself is a work in progress, and our XBL Removal review is a trial run to help us refine it. Look for more information on the review itself soon when we get further along in the process. If you've got ideas, questions, or concerns, talk to [bgrins](https://mozillians.org/en-US/u/bgrinstead/). ## Storage and Sync We've [captured](https://github.com/mozilla/firefox-data-store-docs) a bunch of knowledge about Firefox's data stores. That effort is feeding into some roadmapping work with the Sync and Activity Stream teams. We hope to have some concrete roadmap documentation underway by our next newsletter, as well as some stage-setting blog posts. We expect that the future will include some cross-platform Rust storage services, so we've been researching how this looks in practice. [Deploying an Rust library on iOS](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html) is a short tutorial describing how to build and deploy a Rust library for use inside an iOS app. If you've got ideas, questions, or concerns, talk to [rnewman](https://mozillians.org/en-US/u/rnewman/) or [fluffyemily](https://mozillians.org/en-US/u/etoop/). ## Workflow Improvements * [You can now](https://groups.google.com/d/msg/firefox-dev/L5D3YSBxqh8/pjonQLutCwAJ) open Browser Toolboxes on more than one instance of Firefox at the same time * The ‘no popup autohide' mode that can be toggled in the Browser Toolbox to inspect popups [now automatically resets](https://bugzilla.mozilla.org/show_bug.cgi?id=1251658) when the toolbox closes if you clicked the button to enable it. You can also flip this pref yourself with \`ui.popup.disable\_autohide\` * dump() is [now enabled by default](https://bugzilla.mozilla.org/show_bug.cgi?id=1395711) in local builds - kudos to :kmag for doing this If you've got ideas, questions, or concerns, talk to [bgrins](https://mozillians.org/en-US/u/bgrinstead/) or [nalexander](https://mozillians.org/en-US/u/nalexander/). If you have suggestions or pain points about doing Gecko development (non-front-end), please contact [jesup](https://mozillians.org/en-US/u/jesup/). ## Front-end Developer Survey We've sent out a survey to front-end developers asking them about their workflow and productivity issues. The results of this survey will help us target future workflow and development improvements. If you're an employee working on front-end Firefox code and you haven't received the survey, please let [mossop](https://mozillians.org/en-US/u/Mossop/) or [nalexander](https://mozillians.org/en-US/u/nalexander/) know so we can get it to you! We're still discussing if we should open this survey up to contributors at this time. If you've got other ideas, questions, or concerns, [mossop](https://mozillians.org/en-US/u/Mossop/) and [nalexander](https://mozillians.org/en-US/u/nalexander/) are also the right people to contact. ================================================ FILE: newsletter/_posts/2017-10-19-browser-architecture-newsletter-4.md ================================================ --- title: Browser Architecture Newsletter 4 layout: text description: A newsletter on architecture review, XBL Conversion, Storage and Sync, Workflow Improvements and a developer survey mailinglist: https://groups.google.com/forum/#!topic/firefox-dev/CLFtj8qUSv8 --- # Browser Architecture Newsletter 4 [Link to mailing-list archive]({{ page.mailinglist }}) Welcome to the fourth Browser Architecture Newsletter! A lot of the issues that the Browser Architecture team are digging into are larger than our team. Our goal is to discuss and review entire product level architecture issues and build consensus around solutions. We’re interested in engaging with engineers around the organization. We’re actively reaching out to folks but if you want to talk to us we’d sure love to hear from you. You can find us in `#browser-arch` on IRC or Slack. ## XBL Removal Since our last update, we've completed the design review for [a plan to move away from XBL in Firefox](https://mozilla.github.io/firefox-browser-architecture/text/0007-xbl-design-review-packet.html). Thanks to the long list of people who guided the creation of that plan, and the chair and panel for putting it through its paces. We're working through some follow-up investigations; expect a separate email with more details soon. ## Storage and Sync We've been doing lots of writing on this topic. Emily has [documented](https://github.com/fluffyemily/cross-platform-rust) and blogged about getting Rust libraries up and running on multiple platforms ([iOS](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html), [Android](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html)), which will pave the way for shared storage implementations across mobile and desktop products. Richard has published the [first in a series of blog posts about sync](https://medium.com/@rnewman/thinking-about-syncing-part-1-timelines-7f758e2bd676). A [roadmap review](https://mozilla.github.io/firefox-browser-architecture/text/0006-architecture-review-process.html) is planned for this quarter; thanks to everyone — a dizzying array of engineers, managers, product folks, and Deep Syncers — who've been contributing to that process. Let rnewman know if you're not involved and would like to be. ## Front-end Developer Survey We sent out a survey for front-end developers to try to understand how to target our architecture and workflow improvements. The results will be published soon, but one thing we found was that a lack of documentation is holding developers back. We'll be digging into this more in the future. ================================================ FILE: newsletter/_posts/2017-11-29-browser-architecture-newsletter-5.md ================================================ --- title: Browser Architecture Newsletter 5 layout: text description: A newsletter on Storage and Sync, XBL Removal and Workflow Improvements mailinglist: https://groups.google.com/forum/#!topic/firefox-dev/XKp3EthdJ60 --- # Browser Architecture Newsletter 5 [Link to mailing-list archive]({{ page.mailinglist }}) Welcome to the exciting fifth installment in our series of Browser Architecture Newsletters! ## Storage and Sync We are pleased to report that the Sync and Storage roadmap proposal successfully passed review by dcamp. Thanks to the 20+ people from around the organization who helped us build consensus. The roadmap establishes that storage and syncing of user data is a pillar of the Firefox ecosystem, warranting holistic and long-term attention, and outlines both where we’d like to end up and some ideas for how to get there. We expect this roadmap to lead to a number of subsequent concrete design reviews, as we begin with prototyping, further competitive analysis, and more coordination across Mozilla. The roadmap doc itself has been lightly cleaned up and [published](https://mozilla.github.io/firefox-browser-architecture/text/0008-sync-and-storage-review-packet.html) alongside [our other docs](https://mozilla.github.io/firefox-browser-architecture/). If you’re working on improving storage or syncing of data in any of our products or projects, on any platform, or if you’re currently struggling to work with what currently exists, then we’d like to hear from you and align our efforts. You can find us in Slack or IRC (#browser-arch), or come find rnewman, etoop, rfkelly, markh, or adavis. We’ll be meeting to talk in more detail about the roadmap, the present, and the future [at the All Hands](https://austinyallhands2017.sched.com/event/CyOK/sync-and-storage). We would welcome your participation. ## XBL Removal Our work to remove XBL is proceeding apace. We’ve started by removing bindings that are never or only rarely used. Work to convert XBL bindings to custom elements is currently stalled while we get custom elements working in XUL. You can track how this project is progressing with some [lovely graphs](https://bgrins.github.io/xbl-analysis/graph/). If you’d like to help with the effort, you can grab a bug tagged with [[xbl-available]](https://mzl.la/2AyTxCG). ## Workflow Improvements Running mochitest-plain in headless mode is now supported on Windows, MacOS, and Linux. Use the “--headless” flag with “./mach test” to try it out. ## Austin All Hands We have two meetings planned for the All Hands. You can see these in Sched here: * [Austin Y'all Hands 2017: Sync and Storage](https://austinyallhands2017.sched.com/event/CyOK/sync-and-storage) * [Austin Y'all Hands 2017: XBL and XUL Removal](https://austinyallhands2017.sched.com/event/CyLC/xbl-and-xul-removal) ================================================ FILE: newsletters.xml ================================================ --- layout: null --- Mozilla Browser Architecture Newsletters The published newsletters from the Mozilla Browser Architecture team. {{ site.url }}{{ site.baseurl }} {% for post in site.categories.newsletter %} {{ post.title }} {{ post.description }} {{ site.url }}{{ site.baseurl }}{{ post.url }} {{ site.url }}{{ site.baseurl }}{{ post.url }} {{ post.date }} {% endfor %} ================================================ FILE: text/0000-template.md ================================================ --- title: Documentation Template layout: text --- # Documentation Template ## Problem A short lay summary of the problem space and the stakeholders. Our documents should have a front matter containing a title, which should be the same as the first heading (using `#`). Other headings will generally be at the `##` or `###` levels. ## Proposal Explanation of the solution to the problem. ## Drawbacks / Unresolved Questions It's a rare proposal that perfectly meets the problem, so we'll probably need to document the drawbacks. ## Alternatives Competitive analysis suggesting alternatives, costs, and opportunities. ## Links to discussion * Mailing list discussion? * Original GDocs document ================================================ FILE: text/0001-documenting-output.md ================================================ --- title: Documenting our Output layout: text --- # Documenting our Output ## Problem The Browser Architecture team needs to publish its findings clearly. We would like anyone in Mozilla to be able to: * Find what we’ve learned so far * Find what we’re working on * Leave feedback The solution should: * Be low friction for contribution * Be flexible in how the result is published * Ensure that documents can be found easily ## Proposal Browser Architecture team will document its output like this: 1. The discussion phase involves conversations in the browser-arch [Google Group](https://groups.google.com/a/mozilla.com/forum/#!forum/browser-arch), [IRC channel](https://www.irccloud.com/#!/ircs://irc.mozilla.org:6697/%23browser-arch), [Slack channel](https://mozilla.slack.com/messages/C5F80LV0C/), etc - when a semi-permanent record of current thinking is needed, we use GDocs, stored in [the Browser Architecture folder](https://drive.google.com/drive/u/1/folders/0BzQINYlY78CtbGVqVDVlZlNJX0k). 2. When we've come to some internal consensus (note this doesn't mean that the proposal is final) we convert our GDocs to Markdown/Git to create an 'RFC' and get feedback from management and the wider Mozilla developer community as appropriate. * Use [this template](0000-template.md) 3. As there are updates we keep the Markdown up to date 4. We may publish to a wider audience using a blog post or GitBook as required ## Drawbacks / Unresolved Questions It is possible that GDocs has such a low update friction that people will resent the PR process imposed by Github. If this turns out to be true then we will need to update this process. This process is somewhat modelled on the [Rust RFC](https://github.com/rust-lang/rfcs) process. It isn't certain that we need the numeric prefix. ## Alternatives * Create an index to our documentation using Google Docs, and stay in that world. * Use Medium and or RSS to publish output. ## Links to discussion * [Mailing list discussion](https://groups.google.com/a/mozilla.com/forum/#!topic/browser-arch/FOtfYVHbgfo) ================================================ FILE: text/0002-extracting-necko.md ================================================ --- title: Extracting Necko layout: text --- # Extracting Necko ## Proposal We should extract Necko for reuse in background services and on mobile platforms. ### Motivation We expect that Mozilla will need to build consistent native applications and background services across platforms, including services and applications that don't run Gecko atop a profile directory. To do this it would be beneficial (in theory) to leverage our existing investment in our network layer, avoiding the confusing situation of having multiple ways to configure network settings, and avoiding the possibility of different behaviors in different parts of an application. Furthermore, we expect the question of reuse to recur. Necko is sometimes characterized as being a relatively self-contained piece of mozilla-central's compiled code, so it should be one of the easiest to reuse. Also, its interdependencies are probably applicable to other components, so it's a good opportunity to learn. Breaking out a component for reuse is, for our purposes, equivalent to embedding: it's taking the component and driving it in a different context. Specifically, we are interested in those contexts being (a) Rust, (b) not necessarily desktop. An alternative approach is to build a new Gecko application on top of a slimmed-down libxul. In the case of Necko, that might be something like a cURL clone. This kind of reuse is a known quantity, so we won't discuss it here. ## References * Lots of very old documents: * * *   * Discussions with rhelmer and jduell * Examination of `/netwerk` ## Analysis: obstacles to embedding * In its early days, 15+ years ago, Necko was intended to be embeddable; in recent years that has not been an aim of the component leads. Meeting the needs of Gecko and Firefox is more important. (The definition of 'embeddable' here still carries the obligations of Gecko-style initialization.) * As noted in the "Embedding Necko" document, Necko depends on Gecko features: - XPCOM and NSPR. - mDNS, `NetUtil.jsm`, and some HTTP functionality requires a JS runtime. This is feasible to eliminate if needed. - Docshell. - If cookies are desired, they must be provided via the nsICookieService interface, which is baked into Necko. One can build Necko without, via `--disable-cookies`, but this is a build-time decision. One could conceivably provide one's own implementation of the cookie service, but the interface requires a stateful synchronous global singleton. - Necko depends on the Mozilla preferences service (libpref) for configuration, which is a privileged singleton that itself depends on the observer service (for startup and profile events) and the directory service (for profile directory and app locations). * Because of its dependency on the profile (both for reading state and as a key for the disk cache) and flushing files to disk for prefs, it's not safe to use Necko from two distinct processes simultaneously for the same application. * Because of its extensive use of XPCOM singleton patterns, it's not possible to have two independent Neckos in the same process; they need separate processes and separate profile directories. Some independence can be achieved by carefully configuring channels, but it's not isolation. * It's not possible to use Necko without a profile service (*e.g.*, to make a network request without touching disk). * Parts of Necko are still single-threaded, requiring new channels to be created on the main thread, and dispatching callbacks to the main thread. * Necko's init and deinit are managed by observer notifications, which is not ideal for embedding outside of Gecko. # Proposal ## Proposal # Conclusion Necko is a very feature-rich C++ networking library that is directly targeted at meeting the needs of single-user, single-main-process, single-profile, interactive applications built on a persistent profile directory in the traditional Mozilla model. It is not well-suited for use outside of the Gecko lifecycle — indeed, almost every aspect is designed for the Gecko world — and would require substantial effort in decoupling to be suited for embedded use. Even if so decoupled, it would still mandate the use of XPCOM and the NSPR. To extract Necko for reuse outside of Gecko, by non-XPCOM-based applications, would — almost by definition — require coming up with a plan to deal with XPCOM. That plan might look a lot like continuing historical efforts on deCOMtamination. Necko's data structures, interface definitions, error codes, macros, etc. *are* XPCOM's, and so eliminating XPCOM dependency from the module is likely to involve touching almost every line of code. [Automated tools to do so have been proposed](https://brendaneich.com/2006/10/mozilla-2/). (Going further to eliminate NSPR and mfbt data structures, yielding a more standard C++ library, would be further work still.) This is particularly relevant when we consider oxidation — the replacement of C++ and JS components of Firefox with Rust — and even more so when we consider the use of such components both outside and inside Firefox *from* Rust (rather than from existing non-Rust callers). There is ongoing work on landing Rust components in Firefox; most obstacles there are around XPCOM integration for Rust code, which currently requires writing lots of routine boilerplate by hand. There is also some initial scoping of work to extract and use Gecko C++ components from Servo, which is a similar problem to using Gecko C++ components from Rust background services or mobile applications. Those estimates are large (but not yet published), on the order of 3-5 engineer years for non-trivial components. Extracting such a module is not routine work: delicate balances need to be found between maintaining useful integration with Gecko (*e.g.*, Necko's `nsIChannel` permeates the codebase) versus designing for embedding, and between reimplementing Gecko dependencies in Rust for reuse versus reworking the component to avoid them. Our position is that extracting Necko from Gecko for reuse would be a significant amount of work. Doing so in a way that allows its use from ordinary Rust consumers, without shipping XPCOM/NSPR/*etc*., would be even more so. That amount of work is certainly much more than simply using the existing well-tested and idiomatic networking libraries available to Rust code. Given that the benefits of using Necko in its entirety (instead of *e.g.*, just using Hyper for HTTP) are relatively small, our conclusion is that we **should not attempt to reuse Necko outside of Gecko**. Standalone Rust components should use Rust networking libraries of equivalent functionality, *e.g.*, Tokio/Hyper (already vendored for Servo) or libpnet. Useful Necko functionality should be ported to Rust as needed. Those Rust reimplementations can be imported back into Necko like any other piece of oxidized code. ## Alternatives Alternatives are, variously: * Do the work to extract Necko. Some significant benefit would need to be articulated in order for this to be worthwhile. * Use Gecko for all network-related background services. We already know that this is not feasible, both for application size reasons (Gecko is large), and for technical lifecycle reasons as articulated above. Furthermore, this argument ends up as "use Gecko for everything everywhere", which is not useful. ## Links This document was originally drafted in the ["Answered questions" Google Doc](https://docs.google.com/document/d/1RIMbe0yJGNywFTf1n5ka35JpLtrkE3lHz8iip6jH_VE/edit#). ## Colophon This document was written by Richard Newman (rnewman), reviewed by Jason Duell (jduell), Rob Helmer (rhelmer), Joe Walker, and Myk Melez. ================================================ FILE: text/0003-problems-with-xul.md ================================================ --- title: Problems with XUL layout: text --- # Problems with XUL XUL is often mentioned as a source of problems for developers. This document aims to list the different kinds of problems that exist. ## XUL ownership XUL is largely unowned. While there are developers who know and understand the XUL code they are few and mostly dedicated to other projects at present. ## XUL bugs XUL contains bugs. This isn’t due to anything particularly special about XUL but when we encounter bugs we frequently choose to not fix them, instead trying to find workarounds in the UI instead. See [bug 354527](https://bugzilla.mozilla.org/show_bug.cgi?id=354527) for example. ## No new features There is no new feature implementation going on in XUL compared to HTML which receives constant improvements to meet the demands of the web. ## Performance issues It is thought that XUL’s performance is worse than that of HTML where we have spent large amounts of time optimising for the web but little amount of time optimising for XUL. ## Availability of example code and help XUL is a proprietary technology developed by Mozilla and only used by Mozilla. When developers want to find solutions to problems or implement new features the only example code and documentation they have available is our code and our documentation. ## Learning curve Related, when new developers join Mozilla it is almost certain they will not have heard of or used XUL before and so there is a learning curve to understanding and becoming proficient in the language. ## Recruiting challenge Even if the learning curve is small relative to the productive output of an engineer who has learned the technology, recruiting for a role that involves using a proprietary language is more difficult than recruiting for a role that involves using (and learning, if needed) a popular language. This applies to both new contributors as well as employees. Besides the cost of learning the language and the uncertainty about whether the work will be enjoyable, which may dissuade some candidates, the more important factor is the opportunity cost for career development relative to developing expertise in a popular language: engineers with “XUL experience” don’t benefit from it when looking for their next job (or even position within the company). ## Frameworks Often developers want to use popular JS frameworks like jQuery and React to develop new features. Commonly these frameworks are built for HTML and don’t work correctly in XUL documents. ## SVG and HTML in XUL Because XUL is missing certain features often developers want to embed HTML or SVG elements inside of XUL. Because of differences in the box model this sometimes leads to layout not working correctly. ## Gecko Complexity XUL increases the complexity of Gecko generally, which imposes costs on Gecko development and maintenance (such as the Stylo work). ================================================ FILE: text/0004-xbl-web-components.md ================================================ --- title: XBL and Web Components layout: text --- # XBL and Web Components XBL is a technology used to implement reusable widgets in XUL. Web Components are a set of specifications that provide modern and standards-based alternatives for doing the same thing with HTML. For the purposes of this document, "Web Components" refers to the [Custom Elements](https://w3c.github.io/webcomponents/spec/custom/) and [Shadow DOM](https://w3c.github.io/webcomponents/spec/shadow/) specs, which map relatively closely to how the Firefox frontend is using XBL. What follows is an initial analysis of what a migration away from XBL and to Web Components may look like. We will need to spend more time prototyping this within the Firefox UI to get a clearer picture about the viability of a migration. ## What bindings are we talking about? Most of the relevant bindings are declared in [toolkit/content/widgets](https://github.com/mozilla/gecko-dev/tree/master/toolkit/content/widgets). This analysis is focused on widely used and relatively small XBL components that could potentially be swapped out more-or-less in place with corresponding Web Components. For instance: buttons, labels, input fields, etc. Components that are only used once or are implemented mostly in C++ are ignored in this analysis. For instance: tabbrowser, trees, etc. Most of the same principles that apply to smaller components should also apply to them, but we may also consider different options for moving them away from XBL. ## Auditing the XBL feature set From the [Introduction to XBL](https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/Introduction_to_XBL), a binding has five types of things that it declares: Content, properties, methods, events, and style. But it's helpful to look at specific features used in Firefox and comparing how they map back to Web Components. Which bindings use which features is visualized at https://bgrins.github.io/xbl-analysis/. The scripts to generate that tree and also to semi-automate translation of bindings can be found at https://github.com/bgrins/xbl-analysis. ### XBL features that map to Web Components features 1. ``: These map to JS getters and setters on the Custom Element class (‘val’ name is magic in xbl, would need to keep same name to translate directly) 2. ``: These map to functions on the Custom Element class 3. `` This maps to connectedCallback on the Custom Element class (which is called when the element is inserted into a document). In XBL, the constructor fires after the element is inserted into the document (since the binding is attached through a CSS property). However, the constructor will wait some additional time to fire, unless if the element is accessed via JS in which case it will run immediately 4. ``: These map to `disconnectedCallback` on the Custom Element class 5. `[extends]`: A way to extend the functionality of another binding, i.e. `extends="chrome://global/content/bindings/general.xml#basetext"`. On a surface level this appears to map directly to how the ‘extends’ keyword in ES6 classes behavior with Custom Elements, but more investigation is needed. There’s a small set of tags where you can do `extends="xul:button"` but that’s aliasing the same thing. 6. ``: Can be implemented with addEventListener or possibly a helper on the base element i.e: ``` helpers: { "click": () => { /* bubble by default*/ } "focus|capturing": () => { /* copy in xbl implementation */ } } ``` 7. `[inherits]`: Is a way to declaratively copy attributes from a binding parent to content and keep them in sync, similar to the `` element. For example, this copies the feedURL from the parent into the 'value' field of the label and also observes future changes: ``. The same thing could be built on top of Custom Elements using a MutationObserver and some glue code to set it up in the `connectedCallback`. 8. Scoped CSS Styling: this can be done with Shadow DOM 9. Insertion Points: XBL and Shadow DOM appear to use similar models but different keywords. Further investigation is needed. ### XBL features that don't map Web Components features 1. `[implements]`: This is a way for elements with XBL bindings to implement an XPCOM interface. XBL also auto generates the Qi bits for you. One example usage is that labels implement complex cropping behavior via `implements="nsIDOMXULLabelElement"`, but there are many others (panels, menus, scrollbars). There are around 39 instances of this feature, and this will need to be handled on a case-by-case basis. But we have some options: * Write chrome-only webidl bindings for each of the individual nsiDOMXULFoo classes * Replace things like `implements="nsIObserver"` with just a separate object that in fact implements it * For some input elements like checkboxes, we could get rid of the xul interface since the corresponding HTML element has the same behavior already 2. Extension Compat: For instance, the Tab Center test pilot addon causes tab browser to become vertical via inheritance with some changes. This allows us to use the same tag name / markup so that it doesn’t need to re-write CSS. However, with the migration to Web Extensions this won’t be necessary in the general case. 3. Binding via CSS: `-moz-binding` allows a XBL binding to be attached or detached to any element through CSS. Web Components would be tied to HTML (based on the particular tag being created). This feature is used in [at least one place to swap an element to a different binding when setting a property](http://searchfox.org/mozilla-central/rev/7cc377ce3f0a569c5c9b362d589705cd4fecc0ac/toolkit/content/widgets/text.xml#47), but we can work around it. ## XBL Usage in Firefox How many times are individual bindings used? We've written a module to track how often XBL (and XUL) are used, and a modified version of the test runner that keeps a count throughout the mochitest-browser suite. [A sorted list of used bindings is attached on the bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1376546), but here are the top few bindings: url("chrome://global/content/bindings/text.xml#text-label") url("chrome://global/content/bindings/general.xml#image") url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton") url("chrome://global/content/bindings/menu.xml#menuitem") url("chrome://global/content/bindings/scrollbox.xml#autorepeatbutton") url("chrome://global/content/bindings/button.xml#button") ## Performance Considerations XUL and XBL both use fastload and they both have prototype cache, so loading them and opening new windows should be quite fast. Custom Elements (and Shadow DOM) don't have anything like that right now. If we want to use them in browser chrome, we may need to figure out how to support things like this. The first step is getting some measurements to compare things like element creation time, memory usage, etc. This work is being tracked in [Bug 1387125](https://bugzilla.mozilla.org/show_bug.cgi?id=1387125). ## Notes * Custom Elements don't currently work in XHTML documents, but are specified to. * Custom Elements don't currently work in XUL documents and additional work is required to support them. In particular: * Elements can be created from the XUL prototype cache, bypassing the XML parser * XUL elements are subtly different from HTML elements in how they handle their parenting and prototype chains * The [Custom Elements polyfill](https://github.com/webcomponents/custom-elements) doesn't work in XUL documents, but a [fork designed to use deepTreeWalker](https://github.com/webcomponents/custom-elements/compare/master...bgrins:firefox-browser-chrome?expand=1) does. Using this would allow us to prototype swapping out components without switching the top level document away from XUL. If this turns out to be a good way to migrate away from XBL, we'd have to do work to make the native Web Components implementation work in XUL documents. * The relevant Web Components implementations are still off by default and missing features in Firefox: * Custom Elements is in progress, with plans to complete the work by end Q3 2017 * Shadow DOM is backlogged, with plans to start the work in H2 2017. ================================================ FILE: text/0005-problems-with-xbl.md ================================================ --- title: Problems with XBL layout: text --- # Problems with XBL ## Unmaintained XBL is a proprietary technology developed by Mozilla. We are solely responsible for the maintenance and improvement of XBL. Any time spent on doing this doesn’t contribute to the evolution of the Web so effectively we don’t spend anytime improving XBL except for plugging serious holes. ## Poorly Documented The XBL wiki page says: > "XBL 1.0 is specified in XBL 1.0 Reference. Unfortunately, the actual implementation in Mozilla is different from the specification, and there's no known document available describing the differences. Hopefully, the Reference will be updated to describe those differences." That was written in 2005. It’s still true. Except for the "hope" part. Unlike other technologies like web components where there is plenty of documentation available on the internet, documentation for XBL is almost entirely written by Mozilla and so there is very little of it. The only reference for what is "correct" is what the frontend expects, and what the frontend expects is largely based around a hodgepodge of workarounds for bizarre behavior in the XBL implementation ## Verbose and Brittle (Because XML) Writing code in XML requires extensive use of CDATA sections making the syntax more verbose than it needs to be. ## Dynamic Binding Changes via CSS An XBL binding can set an attribute on itself that causes it to change to a different binding, e.g. [the add-on binding](https://dxr.mozilla.org/mozilla-central/rev/3ecda4678c49ca255c38b1697142b9118cdd27e7/toolkit/mozapps/extensions/content/extensions.xml#1245). These cases are difficult to find and debug and it is very unclear what is happening unless the code is well documented. ## Complicates Stylo We have a ton of code in stylo to handle XBL ``, and XBL scoped stylesheets are sufficiently different from shadow DOM scoped stylesheets that the code isn't really reusable ## Complicates Gecko The fact that XBL is driven off of frame construction is awful. It causes so much weird stuff to happen at very inopportune moments and creates an enormous amount of complexity in what is arguably the most complex and touchy part of the platform (the frame constructor). Anonymous subtrees cause lots of complication in general, and we currently have to deal with three kinds (shadow DOM, NAC, and XBLAC). Dropping this down to 2 would be a huge improvement. There is lots of complexity and security weirdness that required us to build and maintain the content XBL scope stuff in XPConnect. Eliminating the in-content XBL bindings (video, marquee, pluginProblem, and scrollbar) would be a lower-hanging fruit to eliminate this. nsBindingManager is a mutation observer, and its existence means some additional overhead for our DOM mutations, especially [ContentAppended, ContentInserted and ContentRemoved](https://searchfox.org/mozilla-central/rev/51b3d67a5ec1758bd2fe7d7b6e75ad6b6b5da223/dom/xbl/nsBindingManager.h#43). The way we do XBL binding (via CSS) means that often when you touch a node from script we have to go resolve styles for it to see whether there's XBL involved. We optimize this out on the web in various ways, but in XUL it's a pain. ## Not Used Elsewhere This presents a recruiting challenge, there aren’t developers with knowledge of XBL available for hire so everyone we hire has to be trained in this unique technology and there is a steep learning curve. ================================================ FILE: text/0006-architecture-review-process.md ================================================ --- title: Architecture Review Process layout: text --- # Architecture Review Process ## Introduction This process targets Architectural Reviews in two categories: “Roadmap” and “Design”. It doesn't tackle how to review in-progress projects to see if they should continue. The function of a **Roadmap Review** is to decide if a thing should be done. The goal is to bring together a packet of data to inform a management decision to provide resources to make the thing happen. A Roadmap Review should happen early in the process so that build time isn’t wasted on a “No” decision, but so that enough information is available to management. A **Design Review** is to decide if the thing should be done in a particular way. The goal is to ensure that the problem space is understood well enough that a realistic bug breakdown can be made, that those working on the problem all agree on the challenge, and that work can be prioritized to hit the hardest parts of the problem first (in order to get early warning if the hard parts prove impossible or to inform schedule projections early). ## Timetable For both a Roadmap Review and a Design Review the **timetable** is as follows: 1. The team should set the stage: * Summarize in one or two sentences the proposal to be reviewed. This should be agreed between the team asking for review and the reviewer. * Find a **reviewer** (See “Outputs and Audience” below for the rationale): - For a Roadmap Review this will be the least senior manager with the ability to address the problem in its entirety. - For a Design Review this will be an experienced engineer in the problem domain outside of the team willing to put time into the problem. As engineers don’t review their own code they shouldn’t review their own designs. The principle is to get the most informed and least biased feedback possible. * Optionally, for larger reviews, find someone to **chair** the review. This can facilitate the process (i.e. scheduling the meeting, managing the clock, ensuring minutes are taken, etc.) and enables the reviewer to concentrate on the review itself. The rest of this document uses 'chair' for the administrative role. For smaller reviews the reviewer also does the tasks of the chair. 2. The team produces a **Review Packet** designed to document the proposal identified in step 1. The Review Packet includes: * A lay summary of the problem space that defines a shared language and identifies the key forces behind the problem. * A list of the groups directly affected by the proposal to ensure that the review meeting includes representatives from those groups. * A vision of what the project will achieve on completion. * A brief that explains what the team is proposing. This should read more like an encyclopedia entry than a marketing document. The audience is the people in the review; i.e. this should attempt to plug organizational documentation holes. The documentation process should not be more onerous than is required for the review. The brief should identify: - the architecture being proposed - the non-functional requirements, like accessibility, performance, security, and stability - relevant business goals, such as improving user satisfaction and retention - scenarios that exercise the requirements/goals against the proposed architecture - how the proposal handles these scenarios - what review and discussion of the proposed architecture has already happened (and with whom) * A competitive analysis suggesting alternatives, costs, and opportunities * Input by representatives from the affected groups. The team may update the review packet based on this input but is not required to answer all questions and address all comments before the review. 3. The reviewer creates a list of questions to be discussed during the review, possibly from the comments made in step 2. These questions should be: * Designed to foster productive analysis and discussion * Made available to the the team prior to the review so they can prepare answers 4. The chair convenes a review meeting. The discussions of this meeting should be carefully minuted. * The meeting should have a limited attendance to avoid a sprawling unfocussed meeting, but it should include: - The team making the proposal - Representatives from the affected groups, taking care to: + Select a full range of perspectives + Avoid “stacking the deck” with too many people that think the same way * A suggested agenda for the review meeting: - Short opening statement by the team on the current state of play - Discussion of Questions and Answers (see 3. above) - A step back to discuss if the proposal is right in the wider context * A lightweight review might not need the input of others, and ultimately, might not even need a specific review meeting. The review meeting should be a discussion of the issues. Reviewers don't need to make a decision at the meeting. The goal is to understand the issues raised by the question(s) and the background from the review packet, and to add to it wisdom from the people at the review. A generally positive review is likely to have a number of action items which the team should respond to before the review is complete. The reviewer is responsible for enumerating the action items, validating the answers and ultimately deciding the outcome of the review. A more negative review may decide to alter the questions, undergo a subsequent review or drop the subject entirely. It is a goal of the process that we discover fatal flaws as early on in the process as possible. The results of the review (including review packet and reviewer summary) should be published and communicated widely, with the review packet and results archived. Some version of the decision should be publicly linkable, so that it can be the decision of record, to which blog posts, mailing list posts, can refer. ## Review Scaling: Large and Small Reviews The ideal review process scales well. The same basic system should work for a quick 2 person decision over the best way to design a certain feature, and for a critical organization-wide decision about a path to take. The term “team” is used above although we strongly recommend design reviews for smaller questions. If you feel yourself wondering if some design is best, it should be easy to perform a review. For particularly small reviews it is possible to merge a roadmap review and design review into a single review, in which case the question is both 'should we do this', and 'should we do it this way'. It is possible to conduct combined reviews where the total time for the review for all participants is 1 working day. ## Rationale: Outputs and Audience The first two considerations define the goals of the review process and are two sides of the same coin. The audience of a Roadmap Review is those “up the chain” of decision makers and the audience of a Design Review is those running “down the chain” of implementors. A Roadmap Review should focus on: * The problem space * Large forces impacting Mozilla’s choices in the space * Competitive analysis * Opportunity cost The key outcome is firstly, senior management investing in the problem space and building consensus around a shared reality. Secondly, to provide documentation of both the goals and assumptions of the project to aid later evaluation. A Design Review should focus on: * The solution space * Technical roadmaps * Milestones and timelines * Resource allocation The key outcome for middle management is to understand the value proposition and the path to success. The key outcome for engineers is firstly to understand the design constraints and the tradeoffs between them, which is important to avoid unnecessary re-work when implementation reality causes a re-think. Secondly, to provide a proposal detailed enough to begin an initial breakdown of engineering work for the proposal (although the work implied by the proposal should not be filed prior to the completion of the review). ## Examples A number of reviews have been completed and can be used as a template for a successful architectural review. [XBL Removal](0007-xbl-design-review-packet.md) was the first example of a design review, [Sync and Storage](0008-sync-and-storage-review-packet.md) was the first roadmap review, however any of the documents on this website with a title that includes "review" could be used. ## Additional Reading ### Multiple Perspectives On Technical Problems and Solutions - John Allspaw - 2017 Describes how Etsy's architecture review process evolved. A solid write-up of the social side of an Architecture Review process in an environment that is likely closer to Mozilla's than many of the other write-ups. > Fundamental: engineering decision-making is a socially constructed activity > We called these “something new” things departures. ... the basic idea is that there are costs ... for making departures that attempt to solve a local problem without thinking about the global effects it can have on an organization. * https://www.kitchensoap.com/2017/08/12/multiple-perspectives-on-technical-problems-and-solutions/ ### Architecture Reviews - Grady Booch - 2010 A formal write-up from someone who spends a significant time in Architecture Reviews. I've not found the paper online, but the MP3 is an audio version of the paper (with bonus guitar-riff intro). This IBM process suffers from lack of attention to the social aspects, but is helpful in digging into the mechanics of the review itself. * https://www.researchgate.net/publication/224132839_Architecture_Reviews * http://media.computer.org/sponsored/podcast/onarchitecture/onarch-025-v.mp3 ### A Toolbox of Software Architecture Review Techniques - Jason Baragry - 2014, 2015 Jason Baragry reviews approaches to architecture review and notes some potential pitfalls. > Architecturally significant requirements are often hard to identify, the architecturally significant decisions are often not documented, and the way the decisions interrelate is often not easily understood. A significant part of the review process is often teasing these out. * https://swarchitectonics.blogspot.co.uk/2014/12/a-toolbox-of-software-architecture.html * https://swarchitectonics.blogspot.co.uk/2015/02/a-toolbox-pt2.html * https://swarchitectonics.blogspot.co.uk/2015/09/a-toolbox-pt3.html ### Software Architecture Review and Assessment (SARA) Report - Kruchten et al. - 2002 Formal process with input from a number of companies which targets a more enterprise environment than exists at Mozilla, however the process is clearly defined. > A software architecture is a set of concepts and design decisions about structure and texture of software that must be made prior to concurrent engineering (i.e., implementation) to enable effective satisfaction of architecturally significant, explicit functional and quality requirements, along with implicit requirements of the problem and the solution domains. * https://pkruchten.files.wordpress.com/2011/09/sarav1.pdf ================================================ FILE: text/0007-xbl-design-review-packet.md ================================================ --- title: Design Review Packet - XBL Removal layout: text --- # Design Review Packet - XBL Removal This is the packet prepared for the [browser architecture ‘design review’ process](https://mozilla.github.io/firefox-browser-architecture/text/0006-architecture-review-process.html). Some of the sources used to prepare this are the [XBL and Web Components](https://mozilla.github.io/firefox-browser-architecture/text/0004-xbl-web-components.html) analysis and these [scripts and visualizations](https://github.com/bgrins/xbl-analysis), including [graphs of the amount of XBL in tree](https://bgrins.github.io/xbl-analysis). Prototyping and investigations that have been done to create this packet are tracked in the [de-XBL meta bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1397874). **Review Chair**: Mossop **Question to be resolved:** What is the best strategy for removing XBL usage in the Firefox frontend, and the platform implementation of XBL? ## Summary **Problem Space**: XBL suffers from most of the same [problems as XUL](https://mozilla.github.io/firefox-browser-architecture/text/0003-problems-with-xul.html) and [more](https://mozilla.github.io/firefox-browser-architecture/text/0005-problems-with-xbl). Primarily, XBL is unmaintained, poorly documented, verbose and brittle, adds [extra development cost](https://groups.google.com/d/msg/mozilla.dev.platform/iBoROFkR9V8/1ndvU9QIAgAJ) to new code like Stylo, and creates a learning curve and training cost for new engineers. In interviews with senior platform and frontend engineers, XBL is consistently listed as a problem. XBL is deeply ingrained into the Firefox codebase. Based on an instrumented run of the mochitest-browser integration test, Firefox creates approximately 11000 elements with XBL bindings and 6000 elements without a binding [[source]](https://bugzilla.mozilla.org/show_bug.cgi?id=1376546). Inside of mozilla-central there are more than 200 unique binding implementations and 40K LOC in those files [[source]](https://bgrins.github.io/xbl-analysis/). Further, before legacy addon support was removed XBL removal was considered a non-starter, since many popular addons relied on extending or modifying existing bindings. This has also led to extra cost when deprecating features or doing refactorings on individual bindings. **End State:** This would allow us to remove around 14-20K lines of C++ code from dom/xbl (not including tests). It also would move the frontend codebase onto a more standardized tech stack, which will benefit from ongoing platform work and allow for integration with existing tooling. More importantly, the resulting codebase would be simpler and easier to modify, debug and maintain. Performance impacts are expected to be small. **Stakeholders**: Firefox management, Firefox frontend development team, Firefox platform development team, other apps that use XUL such as Thunderbird and SeaMonkey. ## Brief We propose a multi-prong strategy for incremental XBL replacement in the Firefox frontend: * Convert some bindings to JS modules * Convert many others to Web Components * Convert a few into unrefactored XUL/JS/CSS * Flatten the inheritance hierarchy to remove unused bindings * Handle special cases ### JS modules There are some bindings that are not actually widgets - bindings that are only used once, or don’t render any DOM. These can be converted to plain JS objects (either inside a JSM or in a script scoped to the browser window) through a semi-automated process. This will also require manual changes to calling code, so they don’t access the objects as DOM Nodes, and adjust to any API changes that were done in the conversion. Here are a few examples of bindings that fit into this category: * [` / / `](https://hg.mozilla.org/mozilla-central/file/tip/toolkit/content/widgets/preferences.xml): Bindings used in about:preferences to control changing preferences from form controls. An outline for how this can be achieved (and a patch that is on its way to being landable) can be found in [Bug 1379338](https://bugzilla.mozilla.org/show_bug.cgi?id=1379338#c6) * [``](https://hg.mozilla.org/mozilla-central/file/tip/toolkit/content/widgets/stringbundle.xml): A wrapper for string bundle objects with a trivially different API (i.e. `getFormattedString` instead of `formatStringFromName`). We could either build a new object that wraps Services.strings.createBundle and exposes the same API, or change all callers to use `Services.strings.createBundle` directly. Note that the l20n project already has Web Component support. * [``](https://hg.mozilla.org/mozilla-central/file/tip/browser/components/customizableui/content/panelUI.xml#l44): Prior art - Mike de Boer’s work on the PanelMultiView included moving the majority of the implementation out of XBL and into a JSM. More details can be found in [this doc](https://docs.google.com/document/d/1D8WSxgyLA13pidT0umTNEmyrBN5njSPGNLsGkyr0oZM/edit). * [``](https://hg.mozilla.org/mozilla-central/file/tip/browser/base/content/tabbrowser.xml): Much of the Firefox frontend is driven by this binding. It’s also referenced as gBrowser throughout the frontend codebase. It does render some UI below it, but the majority of its ~6000 lines are behavioral, making more than double the size of the next largest binding in Firefox. * This is currently being investigated as a prototype in [bug 1392352](https://bugzilla.mozilla.org/show_bug.cgi?id=1392352) * This could be done as a pure JS module, or following the `PanelMultiView` strategy of keeping XBL for construction and destruction but moving the implementation into a JS module ### Web Components Most of the bindings in Firefox are in [toolkit/content/widgets](https://github.com/mozilla/gecko-dev/tree/master/toolkit/content/widgets), and many of these are self-contained UI widgets that exist at the XUL tag level. For instance, ``, `