summaryrefslogtreecommitdiffstats
path: root/mobile/android/docs/geckoview/contributor
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/docs/geckoview/contributor')
-rw-r--r--mobile/android/docs/geckoview/contributor/apilint.rst85
-rw-r--r--mobile/android/docs/geckoview/contributor/contributing-to-mc.rst188
-rw-r--r--mobile/android/docs/geckoview/contributor/for-gecko-engineers.rst176
-rw-r--r--mobile/android/docs/geckoview/contributor/geckoview-architecture.rst826
-rw-r--r--mobile/android/docs/geckoview/contributor/geckoview-quick-start.rst341
-rw-r--r--mobile/android/docs/geckoview/contributor/index.rst29
-rw-r--r--mobile/android/docs/geckoview/contributor/junit.rst373
-rw-r--r--mobile/android/docs/geckoview/contributor/mc-quick-start.rst184
-rw-r--r--mobile/android/docs/geckoview/contributor/native-debugging.rst262
9 files changed, 2464 insertions, 0 deletions
diff --git a/mobile/android/docs/geckoview/contributor/apilint.rst b/mobile/android/docs/geckoview/contributor/apilint.rst
new file mode 100644
index 0000000000..9d9e315896
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/apilint.rst
@@ -0,0 +1,85 @@
+apilint release process
+~~~~~~~~~~~~~~~~~~~~~~~
+
+To release a new version of `apilint <https://github.com/mozilla-mobile/gradle-apilint>`_, do the following:
+
+- Create a commit titled "Branch X.Y" and modify the files ``apilint/build.gradle`` and ``apilint/Config.java`` accordingly. See for example `Branch 0.5 <https://github.com/mozilla-mobile/gradle-apilint/commit/93a79ffddb8587ad018be67a361eb2a6ae777c63>`_. Note that it's not necessary to modify ``apilint/Config.java`` if there aren't any ``apidoc`` changes.
+
+- Create a git tag with the branch version
+
+.. code:: bash
+
+ $ git tag X.Y
+
+- Run tests locally by running
+
+.. code:: bash
+
+ $ ./gradlew build
+
+
+- Publish new version to local repository
+
+.. code:: bash
+
+ $ ./gradlew publishToMavenLocal
+
+- Modify ``mozilla-central`` locally to test ``apilint`` with the new version, add ``mavenLocal()`` to every ``repositories {}`` block inside the root ``build.gradle``, e.g.
+
+
+.. code:: diff
+
+ diff --git a/build.gradle b/build.gradle
+ index 813ba09aa3d4b..753fdb8d958a6 100644
+ --- a/build.gradle
+ +++ b/build.gradle
+ @@ -60,6 +60,7 @@ allprojects {
+ }
+
+ repositories {
+ + mavenLocal()
+ gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
+ maven {
+ url repository
+ @@ -100,6 +101,7 @@ buildDir "${topobjdir}/gradle/build"
+
+ buildscript {
+ repositories {
+ + mavenLocal()
+ gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
+ maven {
+ url repository
+ @@ -113,7 +115,7 @@ buildscript {
+ ext.kotlin_version = '1.5.31'
+
+ dependencies {
+ - classpath 'org.mozilla.apilint:apilint:0.5.2'
+ + classpath 'org.mozilla.apilint:apilint:0.X.Y'
+ classpath 'com.android.tools.build:gradle:7.0.3'
+ classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
+ classpath 'org.apache.commons:commons-exec:1.3'
+
+* Test integration running ``api-lint``, this should always pass with no ``api.txt`` modifications needed (there could be exceptions, but should be intentional).
+
+.. code:: bash
+
+ $ ./mach lint -l android-api-lint
+
+- Push the tag to the remote repository (note, the branch commit is `not` pushed to the main branch).
+
+.. code:: bash
+
+ $ git push -u origin X.Y
+
+- Wait until github automation finishes successfully.
+- (optional, if there are any ``apidoc`` changes) ask the Releng team to publish a new `apidoc` version, the bundle will be present under the github artifacts, e.g. see ``maven.zip`` in `releases/tag/0.5 <https://github.com/mozilla-mobile/gradle-apilint/releases/tag/0.5>`_. See also `Bug 1727585 <https://bugzilla.mozilla.org/show_bug.cgi?id=1727585>`_.
+
+- Add the ``plugins.gradle.org`` keys to your ``.gradle`` folder, see `publishing_gradle_plugins.html <https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html>`_.
+
+- Publish plugin by running
+
+.. code:: bash
+
+ $ ./gradlew apilint:publishPlugins
+
+- Finally, update ``mozilla-central`` to use the new version, e.g. see `this patch <https://hg.mozilla.org/mozilla-central/rev/0f746422db0e9fc6b70488bdb7114f08973191a0>`_.
diff --git a/mobile/android/docs/geckoview/contributor/contributing-to-mc.rst b/mobile/android/docs/geckoview/contributor/contributing-to-mc.rst
new file mode 100644
index 0000000000..ee4f5be877
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/contributing-to-mc.rst
@@ -0,0 +1,188 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+=================================
+Mozilla Central Contributor Guide
+=================================
+
+Table of contents
+=================
+
+.. contents:: :local:
+
+Submitting a patch to Firefox using Git.
+========================================
+
+This guide will take you through submitting and updating a patch to
+``mozilla-central`` as a git user. You need to already be `set up to use
+git to contribute to mozilla-central <mc-quick-start.html>`_.
+
+Performing a bug fix
+--------------------
+
+All of the open bugs for issues in Firefox can be found in
+`Bugzilla <https://bugzilla.mozilla.org>`_. If you know the component
+that you wish to contribute to you can use Bugzilla to search for issues
+in that project. If you are unsure which component you are interested
+in, you can search the `Good First
+Bugs <https://bugzilla.mozilla.org/buglist.cgi?quicksearch=good-first-bug>`_
+list to find something you want to work on.
+
+- Once you have your bug, assign it to yourself in Bugzilla.
+- Update your local copy of the firefox codebase to match the current
+ version on the servers to ensure you are working with the most up to
+ date code.
+
+.. code:: bash
+
+ git remote update
+
+- Create a new feature branch tracking either Central or Inbound.
+
+.. code:: bash
+
+ git checkout -b bugxxxxxxx [inbound|central]/default
+
+- Work on your bug, checking into git according to your preferred
+ workflow. *Try to ensure that each individual commit compiles and
+ passes all of the tests for your component. This will make it easier
+ to land if you use ``moz-phab`` to submit (details later in this
+ post).*
+
+It may be helpful to have Mozilla commit access, at least level 1. There
+are three levels of commit access that give increasing levels of access
+to the repositories.
+
+Level 1: Try/User access. You will need this level of access commit to
+the try server.
+
+Level 2: General access. This will give you full commit
+access to any mercurial or SVN repository not requiring level 3 access.
+
+Level 3: Core access. You will need this level to commit directly to any
+of the core repositories (Firefox/Thunderbird/Fennec).
+
+If you wish to apply for commit access, please follow the guide found in
+the `Mozilla Commit Access
+Policy <https://www.mozilla.org/en-US/about/governance/policies/commit/access-policy/>`_.
+
+Submitting a patch that touches C/C++
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If your patch makes changes to any C or C++ code and your editor does
+not have ``clang-format`` support, you should run the clang-format
+linter before submitting your patch to ensure that your code is properly
+formatted.
+
+.. code:: bash
+
+ mach clang-format -p path/to/file.cpp
+
+Note that ``./mach bootstrap`` will offer to set up a commit hook that
+will automatically do this for you.
+
+Submitting to ``try`` with Level 1 commit access.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you only have Level 1 access, you will still need to submit your
+patch through phabricator, but you can test it on the try server first.
+
+- Use ``./mach try fuzzy`` to select jobs to run and push to try.
+
+Submitting a patch via Phabricator.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To commit anything to the repository, you will need to set up moz-phab
+and Phabricator. If you are using ``git-cinnabar`` then you will need to
+use git enabled versions of these tools.
+
+Set up Phabricator
+^^^^^^^^^^^^^^^^^^
+
+- In a browser, visit Mozilla’s Phabricator instance at
+ https://phabricator.services.mozilla.com/.
+
+- Click “Log In” at the top of the page
+
+ .. figure:: ../assets/LogInPhab.png
+ :alt: Log in to Phabricator
+
+ alt text
+
+- Click the “Log In or Register” button on the next page. This will
+ take you to Bugzilla to log in or register a new account.
+
+ .. figure:: ../assets/LogInOrRegister.png
+ :alt: Log in or register a Phabiricator account
+
+ alt text
+
+- Sign in with your Bugzilla credentials, or create a new account.
+
+ .. figure:: ../assets/LogInBugzilla.png
+ :alt: Log in with Bugzilla
+
+ alt text
+
+- You will be redirected back to Phabricator, where you will have to
+ create a new Phabricator account.
+
+ .. raw:: html
+
+ <Screenshot Needed>
+
+- Fill in/amend any fields on the form and click “Register Account”.
+
+ .. raw:: html
+
+ <Screenshot Needed>
+
+- You now have a Phabricator account and can submit and review patches.
+
+Installing ``moz-phab``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: bash
+
+ pip install MozPhab [--user]
+
+Submitting a patch using ``moz-phab``.
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Ensure you are on the branch where you have commits that you want to
+ submit.
+
+.. code:: bash
+
+ git checkout your-branch
+
+- Check the revision numbers for the commits you want to submit
+
+.. code:: bash
+
+ git log
+
+- Run ``moz-phab``. Specifying a start commit will submit all commits
+ from that commit. Specifying an end commit will submit all commits up
+ to that commit. If no positional arguments are provided, the range is
+ determined to be starting with the first non-public, non-obsolete
+ changeset (for Mercurial) and ending with the currently checked-out
+ changeset.
+
+.. code:: bash
+
+ moz-phab submit [start_rev] [end_rev]
+
+- You will receive a Phabricator link for each commit in the set.
+
+Updating a patch
+~~~~~~~~~~~~~~~~
+
+- Often you will need to make amendments to a patch after it has been
+ submitted to address review comments. To do this, add your commits to
+ the base branch of your fix as normal.
+
+For ``moz-phab`` run in the same way as the initial submission with the
+same arguments, that is, specifying the full original range of commits.
+Note that, while inserting and amending commits should work fine,
+reordering commits is not yet supported, and deleting commits will leave
+the associated revisions open, which should be abandoned manually
diff --git a/mobile/android/docs/geckoview/contributor/for-gecko-engineers.rst b/mobile/android/docs/geckoview/contributor/for-gecko-engineers.rst
new file mode 100644
index 0000000000..4517d950b4
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/for-gecko-engineers.rst
@@ -0,0 +1,176 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+=============================
+GeckoView For Gecko Engineers
+=============================
+
+Table of contents
+=================
+
+.. contents:: :local:
+
+Introduction
+------------
+
+Who this guide is for: As the title suggests, the target audience of
+this guide is existing Gecko engineers who need to be able to build and
+(locally) test GeckoView. If you aren’t already familiar with building
+Firefox on a desktop platform, you’ll likely be better served by reading
+`our general introduction <geckoview-quick-start.html>`_. This guide may
+also be helpful if you find you’ve written a patch that requires
+changing GeckoView’s public API, see `Landing a Patch <#landing-a-patch>`_.
+
+Who this guide is not for: As mentioned above, if you are not already
+familiar with building Firefox for desktop, you’d likely be better
+served by our general bootstrapping guide. If you are looking to
+contribute to front-end development of one of Mozilla’s Android
+browsers, you’re likely better off starting with their codebase and
+returning here only if actual GeckoView changes are needed. See, for
+example, `Fenix’s GitHub <https://github.com/mozilla-mobile/firefox-android/tree/main/fenix>`_.
+
+What to do if this guide contains bugs or leads you astray: The quickest
+way to get a response is to ask generally on #gv on Mozilla Slack;
+#mobile on Mozilla IRC may also work for the time being, albeit likely
+with slower response times. If you believe the guide needs updating, it
+would also be good to file a ticket to request that.
+
+Configuring the build system
+----------------------------
+
+First, a quick note: This guide was written on MacOS 10.14; it should
+translate quite closely to other supported versions of MacOS and to
+Linux. Building GeckoView on Windows is not officially supported at the
+moment. To begin with, re-run ``./mach bootstrap``; it will present you
+with options for the version of Firefox/GV that you want to build.
+Currently, option ``3`` is
+``GeckoView/Firefox for Android Artifact Mode`` and ``4`` is
+``GeckoView/Firefox for Android``; if you’re here, you want one of
+these. The brief and approximately correct breakdown of ``Artifact`` vs
+regular builds for GeckoView is that ``Artifact`` builds will not allow
+you to work on native code, only on JS or Java. Once you’ve selected
+your build type, ``bootstrap`` should do its usual thing and grab
+whatever dependencies are necessary. You may need to agree to some
+licenses along the way. Once ``bootstrap`` has successfully completed,
+it will spit out a recommended ``mozconfig``.
+
+Mozconfig and Building
+----------------------
+
+If you’ve followed from the previous section, ``./mach bootstrap``
+printed out a recommended ``mozconfig`` that looks something like this:
+
+::
+
+ # Build GeckoView/Firefox for Android:
+ ac_add_options --enable-project=mobile/android
+
+ # Targeting the following architecture.
+ # For regular phones, no --target is needed.
+ # For x86 emulators (and x86 devices, which are uncommon):
+ # ac_add_options --target=i686
+ # For newer phones.
+ # ac_add_options --target=aarch64
+ # For x86_64 emulators (and x86_64 devices, which are even less common):
+ # ac_add_options --target=x86_64
+
+As written, this defaults to building for a 32-bit ARM architecture,
+which is probably not what you want. If you intend to work on an actual
+device, you almost certainly want a 64-bit ARM build, as it is supported
+by virtually all modern ARM phones/tablets and is the only ARM build we
+ship on the Google Play Store. To go this route, uncomment the
+``ac_add_options --target=aarch64`` line in the ``mozconfig``. On the
+other hand, x86-64 emulated devices are widely used by the GeckoView
+team and are used extensively on ``try``; if you intend to use an
+emulator, uncomment the ``ac_add_options --target=x86_64`` line in the
+``mozconfig``. Don’t worry about installing an emulator at the moment,
+that will be covered shortly. It’s worth noting here that other
+``mozconfig`` options will generally work as you’d expect. Additionally,
+if you plan on debugging native code on Android, you should include the
+``mozconfig`` changes mentioned `in our native debugging guide <native-debugging.html>`_. Now, using
+that ``mozconfig`` with any modifications you’ve made, simply
+``./mach build``. If all goes well, you will have successfully built
+GeckoView.
+
+Installing, Running, and Using in Fenix/AC
+------------------------------------------
+
+An (x86-64) emulator is the most common and developer-friendly way of
+contributing to GeckoView in most cases. If you’re going to go this
+route, simply run ``./mach android-emulator`` — by default, this will
+install and launch an x86-64 Android emulator running the same Android
+7.0 image that is used on ``try``. If you need a different emulator
+image you can run ``./mach android-emulator --help`` for information on
+what Android images are available via ``mach``. You can also install an
+emulator image via Android Studio. In cases where an emulator may not
+suffice (eg graphics or performance testing), or if you’d simply prefer
+not to use an emulator, you can opt to use an actual phone instead. To
+do so, you’ll need to enable ``USB Debugging`` on your phone if you
+haven’t already. On most modern Android devices, you can do this by
+opening ``Settings``, going to ``About phone``, and tapping
+``Build number`` seven times. You should get a notification informing
+you that you’ve unlocked developer options. Now return to ``Settings``,
+go to ``Developer options``, and enable USB debugging.
+
+GeckoView Example App
+~~~~~~~~~~~~~~~~~~~~~
+
+Now that you’ve connected a phone or setup an emulator, the simplest way
+to test GeckoView is to launch the GeckoView Example app by running
+``./mach run`` (or install it with ``./mach install`` and run it
+yourself). This is a simplistic GV-based browser that lives in the tree;
+in many cases, it is sufficient to test and debug Gecko changes, and is
+by far the simplest way of doing so. It supports remote debugging by
+default — simply open Remote Debugging on your desktop browser and the
+connected device/emulator should show up when the example app is open.
+You can also use the example app for native debugging, follow the
+`native debugging guide <native-debugging.html>`_.
+
+GeckoView JUnit Tests
+~~~~~~~~~~~~~~~~~~~~~
+
+Once you’ve successfully built GV, you can run tests from the GeckoView
+JUnit test suite with ``./mach geckoview-junit``. For further examples
+(eg running individual tests, repeating tests, etc.), consult the `quick
+start guide <geckoview-quick-start.html#running-tests-locally>`_.
+
+Fenix and other GV-based Apps
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you are working on something for which the GeckoView Example app is
+not sufficient for some reason, you may need to `use your local build of
+GeckoView in one of Mozilla’s GV-based apps like Fenix <geckoview-quick-start.html#include-geckoview-as-a-dependency>`_.
+
+Debugging
+---------
+
+Remote Debugging
+~~~~~~~~~~~~~~~~
+
+To recap a bit of the above, in the GeckoView Example app, remote
+debugging is enabled by default, and your device should show up in your
+desktop browser’s Remote Debugging window with no special effort. For
+Fenix, you can enable remote debugging by opening the three-dot menu and
+toggling ``Remote debugging via USB`` under ``Developer tools``; other
+Mozilla GV-based browsers have similar options.
+
+Native Debugging
+~~~~~~~~~~~~~~~~
+
+To perform native debugging on any GV app will require you to install
+Android Studio and follow instructions `here <native-debugging.html>`_.
+
+Landing a Patch
+---------------
+
+In most cases, there shouldn’t be anything out of the ordinary to deal
+with when landing a patch that affects GeckoView; make sure you include
+Android in your ``try`` runs and you should be good. However, if you
+need to alter the GeckoView public API in any way — essentially anything
+that’s exposed as ``public`` in GeckoView Java files — then you’ll find
+that you need to run the API linter and update the change log. To do
+this, first run ``./mach lint --linter android-api-lint`` — if you have
+indeed changed the public API, this will give you a ``gradle`` command
+to run that will give further instructions. GeckoView API changes
+require two reviews from GeckoView team members; you can open it up to
+the team in general by adding ``#geckoview-reviewers`` as a reviewer on
+Phabricator.
diff --git a/mobile/android/docs/geckoview/contributor/geckoview-architecture.rst b/mobile/android/docs/geckoview/contributor/geckoview-architecture.rst
new file mode 100644
index 0000000000..7ef34e11d5
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/geckoview-architecture.rst
@@ -0,0 +1,826 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+=====================
+Architecture overview
+=====================
+
+.. contents:: Table of Contents
+ :depth: 2
+ :local:
+
+Introduction
+============
+
+*Gecko* is a Web engine developed by Mozilla and used to power Firefox on
+various platforms. A Web engine is roughly comprised of a JavaScript engine, a
+Rendering engine, HTML parser, a Network stack, various media encoders, a
+Graphics engine, a Layout engine and more.
+
+Code that is part of a browser itself is usually referred to as "chrome" code
+(from which the popular Chrome browser takes its name) as opposed to code part
+of a Web site, which is usually referred to "content" code or content Web page.
+
+*GeckoView* is an Android library that can be used to embed Gecko into Android
+apps. Android apps that embed Gecko this way are usually referred to by
+"embedders" or simply "apps".
+
+GeckoView powers all currently active Mozilla browsers on Android, like Firefox
+for Android and Firefox Focus.
+
+API
+===
+
+The following sections describe parts of the GeckoView API that are public and
+exposed to embedders.
+
+ |api-diagram|
+
+Overall tenets
+--------------
+
+GeckoView is an opinionated library that contains a minimal UI and makes no
+assumption about the type of app that is being used by. Its main consumers
+inside Mozilla are browsers, so a lot of features of GeckoView are geared
+towards browsers, but there is no assumption that the embedder is actually a
+browser (e.g. there is no concept of "tab" in GeckoView).
+
+The GeckoView API tries to retain as little data as possible, delegating most
+data storage to apps. Notable exceptions to this rule are: permissions,
+extensions and cookies.
+
+View, Runtime and Session
+-------------------------
+
+ |view-runtime-session|
+
+There are three main classes in the GeckoView API:
+
+- ``GeckoRuntime`` represents an instance of Gecko running in an app. Normally,
+ apps have only one instance of the runtime which lives for as long as the app
+ is alive. Any object in the API that is not specific to a *session*
+ (more to this later) is usually reachable from the runtime.
+- ``GeckoSession`` represents a web site *instance*. You can think of it as a
+ *tab* in a browser or a Web view in an app. Any object related to the
+ specific session will be reachable from this object. Normally, embedders
+ would have many instances of ``GeckoSession`` representing each tab that is
+ currently open. Internally, a session is represented as a "window" with one
+ single tab in it.
+- ``GeckoView`` is an Android ``View`` that embedders can use to paint a
+ ``GeckoSession`` in the app. Normally, only ``GeckoSession`` s associated to
+ a ``GeckoView`` are actually *alive*, i.e. can receive events, fire timers,
+ etc.
+
+Delegates
+---------
+
+Because GeckoView has no UI elements and doesn't store a lot of data, it needs
+a way to *delegate* behavior when Web sites need functionality that requires
+these features.
+
+To do that, GeckoView exposes Java interfaces to the embedders, called
+Delegates. Delegates are normally associated to either the runtime, when they
+don't refer to a specific session, or a session, when they are
+session-specific.
+
+The most important delegates are:
+
+- ``Autocomplete.StorageDelegate`` Which is used by embedders to implement
+ autocomplete functionality for logins, addresses and credit cards.
+- ``ContentDelegate`` Which receives events from the content Web page like
+ "open a new window", "on fullscreen request", "this tab crashed" etc.
+- ``HistoryDelegate`` Which receives events about new or modified history
+ entries. GeckoView itself does not store history so the app is required to
+ listen to history events and store them permanently.
+- ``NavigationDelegate`` Informs the embedder about navigation events and
+ requests.
+- ``PermissionDelegate`` Used to prompt the user for permissions like
+ geolocation, notifications, etc.
+- ``PromptDelegate`` Implements content-side prompts like alert(), confirm(),
+ basic HTTP auth, etc.
+- ``MediaSession.Delegate`` Informs the embedder about media elements currently
+ active on the page and allows the embedder to pause, resume, receive playback
+ state etc.
+- ``WebExtension.MessageDelegate`` Used by the embedder to exchange messages
+ with built-in extensions. See also `Interacting with Web Content <../consumer/web-extensions.html>`_.
+
+
+.. _GeckoDisplay:
+
+GeckoDisplay
+------------
+
+GeckoView can paint to either a ``SurfaceView`` or a ``TextureView``.
+
+- ``SufaceView`` is what most apps will use and it's the default, it provides a
+ barebone wrapper around a GL surface where GeckoView can paint on.
+ SurfaceView is not part of normal Android compositing, which means that
+ Android is not able to paint (partially) on top of a SurfaceView or apply
+ transformations and animations to it.
+- ``TextureView`` offers a surface which can be transformed and animated but
+ it's slower and requires more memory because it's `triple-buffered
+ <https://en.wikipedia.org/wiki/Multiple_buffering#Triple_buffering>`_
+ (which is necessary to offer animations).
+
+Most apps will use the ``GeckoView`` class to paint the web page. The
+``GeckoView`` class is an Android ``View`` which takes part in the Android view
+hierarchy.
+
+Android recycles the ``GeckoView`` whenever the app is not visible, releasing
+the associated ``SurfaceView`` or ``TextureView``. This triggers a few actions
+on the Gecko side:
+
+- The GL Surface is released, and Gecko is notified in
+ `SyncPauseCompositor <https://searchfox.org/mozilla-central/rev/ead7da2d9c5400bc7034ff3f06a030531bd7e5b9/widget/android/nsWindow.cpp#1114>`_.
+- The ``<browser>`` associated to the ``GeckoSession`` is `set to inactive <https://searchfox.org/mozilla-central/rev/ead7da2d9c5400bc7034ff3f06a030531bd7e5b9/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java#553>`_,
+ which essentially freezes the JavaScript engine.
+
+Apps that do not use ``GeckoView``, because e.g. they cannot use
+``SurfaceView``, need to manage the active state manually and call
+``GeckoSession.setActive`` whenever the session is not being painted on the
+screen.
+
+Thread safety
+-------------
+
+Apps will inevitably have to deal with the Android UI in a significant way.
+Most of the Android UI toolkit operates on the UI thread, and requires
+consumers to execute method calls on it. The Android UI thread runs an event
+loop that can be used to schedule tasks on it from other threads.
+
+Gecko, on the other hand, has its own main thread where a lot of the front-end
+interactions happen, and many methods inside Gecko expect to be called on the
+main thread.
+
+To not overburden the App with unnecessary multi-threaded code, GeckoView will
+always bridge the two "main threads" and redirect method calls as appropriate.
+Most GeckoView delegate calls will thus happen on the Android UI thread and
+most APIs are expected to be called on the UI thread as well.
+
+This can sometimes create unexpected performance considerations, as illustrated
+in later sections.
+
+GeckoResult
+-----------
+
+An ubiquitous tool in the GeckoView API is ``GeckoResult``. GeckoResult is a
+promise-like class that can be used by apps and by Gecko to return values
+asynchronously in a thread-safe way. Internally, ``GeckoResult`` will keep
+track of what thread it was created on, and will execute callbacks on the same
+thread using the thread's ``Handler``.
+
+When used in Gecko, ``GeckoResult`` can be converted to ``MozPromise`` using
+``MozPromise::FromGeckoResult``.
+
+Page load
+---------
+
+ |pageload-diagram|
+
+GeckoView offers several entry points that can be used to react to the various
+stages of a page load. The interactions can be tricky and surprising so we will
+go over them in details in this section.
+
+For each page load, the following delegate calls will be issued:
+``onLoadRequest``, ``onPageStart``, ``onLocationChange``,
+``onProgressChange``, ``onSecurityChange``, ``onSessionStateChange``,
+``onCanGoBack``, ``onCanGoForward``, ``onLoadError``, ``onPageStop``.
+
+Most of the method calls are self-explanatory and offer the App a chance to
+update the UI in response to a change in the page load state. The more
+interesting delegate calls will be described below.
+
+onPageStart and onPageStop
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``onPageStart`` and ``onPageStop`` are guaranteed to appear in pairs and in
+order, and denote the beginning and the end of a page load. In between a start
+and stop event, multiple ``onLoadRequest`` and ``onLocationChange`` call can be
+executed, denoting redirects.
+
+onLoadRequest
+~~~~~~~~~~~~~
+
+``onLoadRequest``, which is perhaps the most important, can be used by the App
+to intercept page loads. The App can either *deny* the load, which will stop
+the page from loading, and handle it internally, or *allow* the
+load, which will load the page in Gecko. ``onLoadRequest`` is called for all
+page loads, regardless of whether they were initiated by the app itself, by Web
+content, or as a result of a redirect.
+
+When the page load originates in Web content, Gecko has to synchronously
+wait for the Android UI thread to schedule the call to ``onLoadRequest`` and
+for the App to respond. This normally takes a negligible amount of time, but
+when the Android UI thread is busy, e.g. because the App is being painted for
+the first time, the delay can be substantial. This is an area of GeckoView that
+we are actively trying to improve.
+
+onLoadError
+~~~~~~~~~~~
+
+``onLoadError`` is called whenever the page does not load correctly, e.g.
+because of a network error or a misconfigured HTTPS server. The App can return
+a URL to a local HTML file that will be used as error page internally by Gecko.
+
+onLocationChange
+~~~~~~~~~~~~~~~~
+
+``onLocationChange`` is called whenever Gecko commits to a navigation and the
+URL can safely displayed in the URL bar.
+
+onSessionStateChange
+~~~~~~~~~~~~~~~~~~~~
+
+``onSessionStateChange`` is called whenever any piece of the session state
+changes, e.g. form content, scrolling position, zoom value, etc. Changes are
+batched to avoid calling this API too frequently.
+
+Apps can use ``onSessionStateChange`` to store the serialized state to
+disk to support restoring the session at a later time.
+
+Third-party root certificates
+-----------------------------
+
+Gecko maintains its own Certificate Authority store and does not use the
+platform's CA store. GeckoView follows the same policy and will not, by
+default, read Android's CA store to determine root certificates.
+
+However, GeckoView provides a way to import all third-party CA roots added to
+the Android CA store by setting the `enterpriseRootsEnabled
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#enterpriseRootsEnabled(boolean)>`_
+runtime setting to ``true``, this feature is implemented in `EnterpriseRoots
+<https://searchfox.org/mozilla-central/rev/26a6a38fb515dbab0bb459c40ec4b877477eefef/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EnterpriseRoots.java>`_
+
+There is not currently any API for an app to manually specify additional CA
+roots, although this might change with `Bug 1522162
+<https://bugzilla.mozilla.org/show_bug.cgi?id=1522162>`_.
+
+Lite and Omni builds
+---------------------
+
+A variation of the default GeckoView build, dubbed `Omni` in the codebase,
+provides additional libraries that can be helpful when building a browser app.
+Currently, the `Glean
+<https://docs.telemetry.mozilla.org/concepts/glean/glean.html>`_ library is
+included in the ``geckoview-omni`` package. The default build ``geckoview``,
+which does not contain such libraries, is similarly dubbed `Lite` in the
+codebase.
+
+The additional libraries in the Omni package are directly built into Gecko's
+main ``.so`` file, ``libxul.so``. These libraries are then declared in the
+``.module`` package inside the ``maven`` repository, e.g. see the ``.module``
+file for `geckoview-omni
+<https://maven.mozilla.org/maven2/org/mozilla/geckoview/geckoview-omni/102.0.20220623063721/geckoview-omni-102.0.20220623063721.module>`_:
+
+.. code-block:: json
+
+ "capabilities": [
+ {
+ "group": "org.mozilla.geckoview",
+ "name": "geckoview-omni",
+ "version": "102.0.20220623063721"
+ },
+ {
+ "group": "org.mozilla.telemetry",
+ "name": "glean-native",
+ "version": "44.1.1"
+ }
+ ]
+
+Notice the ``org.mozilla.telemetry:glean-native`` capability is declared
+alongside ``org.mozilla.geckoview``.
+
+The main Glean library then depends on ``glean-native`` which is either
+provided in a standalone package (for apps that do not include GeckoView) or by
+the GeckoView capability above.
+
+In Treeherder, the Lite build is denoted with ``Lite``, while the Omni builds
+don't have extra denominations as they are the default build, so e.g. for
+``x86_64`` the platorm names would be:
+
+- ``Android 7.0 x86-64`` for the Omni build
+- ``Android 7.0 x86-64 Lite`` for the Lite build
+
+Extensions
+----------
+
+Extensions can be installed using ``WebExtensionController::install`` and
+``WebExtensionController::installBuiltIn``, which asynchronously returns a
+``WebExtension`` object that can be used to set delegates for
+extension-specific behavior.
+
+The ``WebExtension`` object is immutable, and will be replaced every time a
+property changes. For instance, to disable an extension, apps can use the
+``disable`` method, which will return an updated version of the
+``WebExtension`` object.
+
+Internally, all ``WebExtension`` objects representing one extension share the
+same delegates, which are stored in ``WebExtensionController``.
+
+Given the extensive sprawling amount of data associated to extensions,
+extension installation persists across restarts. Existing extensions can be
+listed using ``WebExtensionController::list``.
+
+In addition to ordinary WebExtension APIs, GeckoView allows ``builtIn``
+extensions to communicate to the app via native messaging. Apps can register
+themselves as native apps and extensions will be able to communicate to the app
+using ``connectNative`` and ``sendNativeMessage``. Further information can be
+found `here <../consumer/web-extensions.html>`__.
+
+Internals
+=========
+
+The following sections describe how Gecko and GeckoView are implemented. These
+parts of GeckoView are not normally exposed to embedders.
+
+Process Model
+-------------
+
+Internally, Gecko uses a multi-process architecture, most of the chrome code
+runs in the *main* process, while content code runs in *child* processes also
+called *content* processes. There are additional types of specialized processes
+like the *socket* process, which runs parts of the networking code, the *gpu*
+process which executes GPU commands, the *extension* process which runs most
+extension content code, etc.
+
+We intentionally do not expose our process model to embedders.
+
+To learn more about the multi-process architecture see `Fission for GeckoView
+engineers <https://gist.github.com/agi/c900f3e473ff681158c0c907e34780e4>`_.
+
+The majority of the GeckoView Java code runs on the main process, with a thin
+glue layer on the child processes, mostly contained in ``GeckoThread``.
+
+Process priority on Android
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On Android, each process is assigned a given priority. When the device is
+running low on memory, or when the system wants to conserve resources, e.g.
+when the screen has been off for a long period of time, or the battery is low,
+Android will sort all processes in reverse priority order and kill, using a
+``SIGKILL`` event, enough processes until the given free memory and resource
+threshold is reached.
+
+Processes that are necessary to the function of the device get the highest
+priority, followed by apps that are currently visible and focused on the
+screen, then apps that are visible (but not on focus), background processes and
+so on.
+
+Processes that do not have a UI associated to it, e.g. background services,
+will normally have the lowest priority, and thus will be killed most
+frequently.
+
+To increase the priority of a service, an app can ``bind`` to it. There are
+three possible ``bind`` priority values
+
+- ``BIND_IMPORTANT``: The process will be *as important* as the process binding
+ to it
+- default priority: The process will have lower priority than the process
+ binding to it, but still higher priority than a background service
+- ``BIND_WAIVE_PRIORITY``: The bind will be ignored for priority
+ considerations.
+
+It's important to note that the priority of each service is only relative to
+the priority of the app binding to it. If the app is not visible, the app
+itself and all services attached to it, regardless of binding, will get
+background priority (i.e. the lowest possible priority).
+
+Process management
+~~~~~~~~~~~~~~~~~~
+
+Each Gecko process corresponds to an Android ``service`` instance, which has to
+be declared in GeckoView's ``AndroidManifest.xml``.
+
+For example, this is the definition of the ``media`` process:
+
+.. code-block:: xml
+
+ <service
+ android:name="org.mozilla.gecko.media.MediaManager"
+ android:enabled="true"
+ android:exported="false"
+ android:isolatedProcess="false"
+ android:process=":media">
+
+Process creation is controlled by Gecko which interfaces to Android using
+``GeckoProcessManager``, which translates Gecko's priority to Android's
+``bind`` values.
+
+Because all priorities are waived when the app is in the background, it's not
+infrequent that Android kills some of GeckoView's services, while still leaving
+the main process alive.
+
+It is therefore very important that Gecko is able to recover from process
+disappearing at any moment at runtime.
+
+Priority Hint
+~~~~~~~~~~~~~
+
+Internally, GeckoView ties the lifetime of the ``Surface`` associated to a
+``GeckoSession`` and the process priority of the process where the session
+lives.
+
+The underlying assumption is that a session that is not visible doesn't have a
+surface associated to it and it's not being used by the user so it shouldn't
+receive high priority status.
+
+The way this is implemented is `by setting
+<https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java#114,123>`_
+the ``active`` property on the ``browser`` object to ``false``, which causes
+Gecko to de-prioritize the process, assuming that no other windows in the same
+process have ``active=true``. See also `GeckoDisplay`_.
+
+However, there are use cases where just looking at the surface is not enough.
+For instance, when the user opens the settings menu, the currently selected tab
+becomes invisible, but the user will still expect the browser to retain that
+tab state with a higher priority than all the other tabs. Similarly, when the
+browser is put in the background, the surface associated to the current tab
+gets destroyed, but the current tab is still more important than the other
+tabs, but because it doesn't have a surface associated to it, we have no way to
+differentiate it from all the other tabs.
+
+To solve the above problem, we expose an API for consumers to *boost* a session
+priority, `setPriorityHint
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html#setPriorityHint(int)>`_.
+The priority hint is taken into consideration when calculating the
+priority of a process. Any process that contains either an active session or a
+session with the priority hint `is boosted
+<https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/dom/ipc/BrowserParent.cpp#3593>`_
+to the highest priority.
+
+Shutdown
+--------
+
+Android does not provide apps with a notification whenever the app is shutting
+down. As explained in the section above, apps will simply be killed whenever
+the system needs to reclaim resources. This means that Gecko on Android will
+never shutdown cleanly, and that shutdown actions will never execute.
+
+.. _principals:
+
+Principals
+----------
+
+In Gecko, a *website* loaded in a session is represented by an abstraction
+called `principal
+<https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/caps/nsIPrincipal.idl>`_.
+Principals contain information that is used to determine what permissions have
+been granted to the website instance, what APIs are available to it, which
+container the page is loaded in, is the page in private browsing or not, etc.
+
+Principals are used throughout the Gecko codebase, GeckoView, however, does not
+expose the concept to the API. This is intentional, as exposing it would
+potentially expose the app to various security sensitive concepts, which would
+violate the "secure" requirement for the GeckoView API.
+
+The absence of principals from the API is, e.g., why GeckoView does not offer a
+way to set permissions given a URL string, as permissions are internally stored
+by principal. See also `Setting Permissions`_.
+
+To learn more about principals see `this talk by Bobby Holley
+<https://www.youtube.com/watch?v=28FPetl5Fl4>`_.
+
+Window model
+------------
+
+Internally, Gecko has the concept of *window* and *tab*. Given that GeckoView
+doesn't have the concept of tab (since it might be used to build something that
+is *not* a browser) we hide Gecko tabs from the GeckoView API.
+
+Each ``GeckoSession`` corresponds to a Gecko ``window`` object with exactly one
+``tab`` in it. Because of this you might see ``window`` and ``session`` used
+interchangeably in the code.
+
+Internally, Gecko uses ``window`` s for other things other than
+``GeckoSession``, so we have to sometime be careful about knowing which windows
+belong to GeckoView and which don't. For example, the background extension page
+is implemented as a ``window`` object that doesn't paint to a surface.
+
+EventDispatcher
+---------------
+
+The GeckoView codebase is written in C++, JavaScript and Java, it runs across
+processes and often deals with asynchronous and garbage-collected code with
+complex lifetime dependencies. To make all of this work together, GeckoView
+uses a cross-language event-driven architecture.
+
+The main orchestrator of this event-driven architecture is ``EventDispatcher``.
+Each language has an implementation of ``EventDispatcher`` that can be used to
+fire events that are reachable from any language.
+
+Each window (i.e. each session) has its own ``EventDispatcher`` instance, which
+is also present on the content process. There is also a global
+``EventDispatcher`` that is used to send and receive events that are not
+related to a specific session.
+
+Events can have data associated to it, which is represented as a
+``GeckoBundle`` (essentially a ``String``-keyed variant map) on the Java and
+C++ side, and a plain object on the JavaScript side. Data is automatically
+converted back and forth by ``EventDispatcher``.
+
+In Java, events are fired in the same thread where the listener was registered,
+which allows us to ensure that events are received in a consistent order and
+data is kept consistent, so that we by and large don't have to worry about
+multi-threaded issues.
+
+JNI
+---
+
+GeckoView code uses the Java Native Interface or JNI to communicate between
+Java and C++ directly. Our JNI exports are generated from the Java source code
+whenever the ``@WrapForJNI`` annotation is present. For non-GeckoView code, the
+list of classes for which we generate imports is defined at
+``widget/android/bindings``.
+
+The lifetime of JNI objects depends on their native implementation:
+
+- If the class implements ``mozilla::SupportsWeakPtr``, the Java object will
+ store a ``WeakPtr`` to the native object and will not own the lifetime of the
+ object.
+- If the class implements ``AddRef`` and ``Release`` from ``nsISupports``, the
+ Java object will store a ``RefPtr`` to the native object and will hold a
+ strong reference until the Java object releases the object using
+ ``DisposeNative``.
+- If neither cases apply, the Java object will store a C++ pointer to the
+ native object.
+
+Calling Runtime delegates from native code
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Runtime delegates can be reached directly using the ``GeckoRuntime`` singleton.
+A common pattern is to expose a ``@WrapForJNI`` method on ``GeckoRuntime`` that
+will call the delegate, that than can be used on the native side. E.g.
+
+.. code:: java
+
+ @WrapForJNI
+ private void featureCall() {
+ ThreadUtils.runOnUiThread(() -> {
+ if (mFeatureDelegate != null) {
+ mFeatureDelegate.feature();
+ }
+ });
+ }
+
+And then, on the native side:
+
+.. code:: cpp
+
+ java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
+ if (runtime != nullptr) {
+ runtime->FeatureCall();
+ }
+
+Session delegates
+~~~~~~~~~~~~~~~~~
+
+``GeckoSession`` delegates require a little more care, as there's a copy of a
+delegate for each ``window``. Normally, a method on ``android::nsWindow`` is
+added which allows Gecko code to call it. A reference to ``nsWindow`` can be
+obtained from a ``nsIWidget`` using ``nsWindow::From``:
+
+.. code:: cpp
+
+ RefPtr<nsWindow> window = nsWindow::From(widget);
+ window->SessionDelegateFeature();
+
+The ``nsWindow`` implementation can then forward the call to
+``GeckoViewSupport``, which is the JNI native side of ``GeckoSession.Window``.
+
+.. code:: cpp
+
+ void nsWindow::SessionDelegateFeature() {
+ auto acc(mGeckoViewSupport.Access());
+ if (!acc) {
+ return;
+ }
+ acc->SessionDelegateFeature(aResponse);
+ }
+
+Which can in turn forward the call to the Java side using the JNI stubs.
+
+.. code:: cpp
+
+ auto GeckoViewSupport::SessionDelegateFeature() {
+ GeckoSession::Window::LocalRef window(mGeckoViewWindow);
+ if (!window) {
+ return;
+ }
+ window->SessionDelegateFeature();
+ }
+
+And finally, the Java implementation calls the session delegate.
+
+.. code:: java
+
+ @WrapForJNI
+ private void sessionDelegateFeature() {
+ final GeckoSession session = mOwner.get();
+ if (session == null) {
+ return;
+ }
+ ThreadUtils.postToUiThread(() -> {
+ final FeatureDelegate delegate = session.getFeatureDelegate();
+ if (delegate == null) {
+ return;
+ }
+ delegate.feature();
+ });
+ }
+
+.. _permissions:
+
+Permissions
+-----------
+
+There are two separate but related permission concepts in GeckoView: `Content`
+permissions and `Android` permissions. See also the related `consumer doc
+<../consumer/permissions.html>`_ on permissions.
+
+Content permissions
+~~~~~~~~~~~~~~~~~~~
+
+Content permissions are granted to individual web sites (more precisely,
+`principals`_) and are managed internally using ``nsIPermissionManager``.
+Content permissions are used by Gecko to keep track which website is allowed to
+access a group of Web APIs or functionality. The Web has the concept of
+permissions, but not all Gecko permissions map to Web-exposed permissions.
+
+For instance, the ``Notification`` permission, which allows websites to fire
+notifications to the user, is exposed to the Web through
+`Notification.requestPermission
+<https://developer.mozilla.org/en-US/docs/Web/API/Notification/requestPermission>`_,
+while the `autoplay` permission, which allows websites to play video and audio
+without user interaction, is not exposed to the Web and websites have no way to
+set or request this permission.
+
+GeckoView retains content permission data, which is an explicit violation of
+the design principle of not storing data. This is done because storing
+permissions is very complex, making a mistake when dealing with permissions
+often ends up being a security vulnerability, and because permissions depend on
+concepts that are not exposed to the GeckoView API like `principals`_.
+
+Android permissions
+~~~~~~~~~~~~~~~~~~~
+
+Consumers of GeckoView are Android apps and therefore they have to receive
+permission to use certain features on behalf of websites.
+
+For instance, when a website requests Geolocation permission for the first
+time, the app needs to request the corresponding Geolocation Android permission
+in order to receive position data.
+
+You can read more about Android permissions on `this doc
+<https://developer.android.com/guide/topics/permissions/overview>`_.
+
+
+Implementation
+~~~~~~~~~~~~~~
+
+The main entry point from Gecko is ``nsIContentPermissionPrompt.prompt``, which
+is handled in the `Permission module
+<https://searchfox.org/mozilla-central/rev/256f84391cf5d4e3a4d66afbbcd744a5bec48956/mobile/android/components/geckoview/GeckoViewPermission.jsm#21>`_
+in the same process where the request is originated.
+
+The permission module calls the child actor `GeckoViewPermission
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionChild.jsm#47>`_
+which issues a `GeckoView:ContentPermission
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionChild.jsm#75>`_
+request to the Java front-end as needed.
+
+Media permissions are requested using a global observer, and therefore are
+handled in a `Process actor
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionProcessChild.jsm#41>`_,
+media permissions requests have enough information to redirect the request to
+the corresponding window child actor, with the exception of requests that are
+not associated with a window, which are redirected to the `current active
+window
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewPermissionProcessParent.jsm#28-35>`_.
+
+Setting permissions
+~~~~~~~~~~~~~~~~~~~
+
+Permissions are stored in a map between a `principal <#principals>`_ and a list
+of permission (key, value) pairs. To prevent security vulnerabilities, GeckoView
+does not provide a way to set permissions given an arbitrary URL and requires
+consumers to get hold of the `ContentPermission
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.ContentPermission.html>`_
+object. The ContentPermission object is returned in `onLocationChange
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.NavigationDelegate.html#onLocationChange(org.mozilla.geckoview.GeckoSession,java.lang.String,java.util.List)>`_
+upon navigation, making it unlikely to have confusion bugs whereby the
+permission is given to the wrong website.
+
+Internally, some permissions are only present when a certain override is set,
+e.g. Tracking Protection override permissions are only present when the page
+has been given a TP override. Because the only way to set the value of a
+permission is to get hold of the ``ContentPermission`` object, `we manually insert
+<https://searchfox.org/mozilla-central/rev/5b2d2863bd315f232a3f769f76e0eb16cdca7cb0/mobile/android/modules/geckoview/GeckoViewNavigation.jsm#605-625>`_
+a `trackingprotection` permission on every page load.
+
+Autofill Support
+----------------
+
+GeckoView supports third-party autofill providers through Android's `autofill framework <https://developer.android.com/guide/topics/text/autofill>`_. Internally, this support is referred to as `autofill`.
+
+Document tree
+~~~~~~~~~~~~~
+
+The autofill Java front-end is located in the `Autofill class
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#37>`_.
+GeckoView maintains a virtual tree structure of the current document for each
+``GeckoSession``.
+
+The virtual tree structure is composed of `Node
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#593>`_
+objects which are immutable. Data associated to a node, including mutable data
+like the current value, is stored in a separate `NodeData
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#171>`_
+class. Only HTML nodes that are relevant to autofilling are referenced in the
+virtual structure and each node is associated to a root node, e.g. the root
+``<form>`` element. All root nodes are children of the autofill `mRoot
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java#210>`_
+node, hence making the overall structure a tree rather than a collection of
+trees. Note that the root node is the only node in the virtual structure that
+does not correspond to an actual element on the page.
+
+Internally, nodes are assigned a unique ``UUID`` string, which is used to match
+nodes between the Java front-end and the data stored in GeckoView's chrome
+Javascript. The autofill framework itself requires integer IDs for nodes, so we
+store a mapping between UUIDs and integer IDs in the associated ``NodeData``
+object. The integer IDs are used only externally, while internally only the
+UUIDs are used. The reason why we use a separate ID structure from the autofill
+framework is that this allows us to `generate UUIDs
+<https://searchfox.org/mozilla-central/rev/7e34cb7a0094a2f325a0c9db720cec0a2f2aca4f/mobile/android/actors/GeckoViewAutoFillChild.jsm#217-220>`_
+directly in the isolated content processes avoiding an IPC roundtrip to the
+main process.
+
+Each ``Node`` object is associated to an ``EventCallback`` object which is
+invoked whenever the node is autofilled by the autofill framework.
+
+Detecting autofillable nodes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+GeckoView scans every web page for password ``<input>`` elements whenever the
+``pageshow`` event `fires
+<https://searchfox.org/mozilla-central/rev/9dc5ffe42635b602d4ddfc9a4b8ea0befc94975a/mobile/android/actors/GeckoViewAutoFillChild.jsm#74-78>`_.
+
+It also uses ``DOMFormHasPassword`` and ``DOMInputPasswordAdded`` to detect
+whenever a password element is added to the DOM after the ``pageshow`` event.
+
+Prefs
+-----
+
+`Preferences </modules/libpref/index.html>`_ (or prefs) are used throughout
+Gecko to configure the browser, enable custom features, etc.
+
+GeckoView does not directly expose prefs to Apps. A limited set configuration
+options is exposed through ``GeckoRuntimeSettings``.
+
+``GeckoRuntimeSettings`` can be easily mapped to a Gecko ``pref`` using
+``Pref``, e.g.
+
+.. code:: java
+
+ /* package */ final Pref<Boolean> mPrefExample =
+ new Pref<Boolean>("example.pref", false);
+
+The value of the pref can then be read internally using ``mPrefExample.get``
+and written to using ``mPrefExample.commit``.
+
+Front-end and back-end
+----------------------
+
+ |code-layers|
+
+Gecko and GeckoView code can be divided in five layers:
+
+- **Java API** the outermost code layer that is publicly accessible to
+ GeckoView embedders.
+- **Java Front-End** All the Java code that supports the API and talks directly
+ to the Android APIs and to the JavaScript and C++ front-ends.
+- **JavaScript Front-End** The main interface to the Gecko back-end (or Gecko
+ proper) in GeckoView is JavaScript, we use this layer to call into Gecko and
+ other utilities provided by Gecko, code lives in ``mobile/android``
+- **C++ Front-End** A smaller part of GeckoView is written in C++ and interacts
+ with Gecko directly, most of this code is lives in ``widget/android``.
+- **C++/Rust Back-End** This is often referred to as "platform", includes all
+ core parts of Gecko and is usually accessed to in GeckoView from the C++
+ front-end or the JavaScript front-end.
+
+Modules and Actors
+------------------
+
+GeckoView's JavaScript Front-End is largely divided into units called modules
+and actors. For each feature, each window will have an instance of a Module, a
+parent-side Actor and (potentially many) content-side Actor instances. For a
+detailed description of this see `here <https://gist.github.com/agi/c900f3e473ff681158c0c907e34780e4#actors>`__.
+
+Testing infrastructure
+----------------------
+
+For a detailed description of our testing infrastructure see `GeckoView junit
+Test Framework <junit.html>`_.
+
+.. |api-diagram| image:: ../assets/api-diagram.png
+.. |view-runtime-session| image:: ../assets/view-runtime-session.png
+.. |pageload-diagram| image:: ../assets/pageload-diagram.png
+.. |code-layers| image:: ../assets/code-layers.png
diff --git a/mobile/android/docs/geckoview/contributor/geckoview-quick-start.rst b/mobile/android/docs/geckoview/contributor/geckoview-quick-start.rst
new file mode 100644
index 0000000000..140dd62784
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/geckoview-quick-start.rst
@@ -0,0 +1,341 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+.. _geckoview-contributor-guide:
+
+=================
+Contributor Guide
+=================
+
+Table of contents
+=================
+
+.. contents:: :local:
+
+GeckoView Contributor Quick Start Guide
+=======================================
+
+This is a guide for developers who want to contribute to the GeckoView
+project. If you want to get started using GeckoView in your app then you
+should refer to the
+`wiki <https://wiki.mozilla.org/Mobile/GeckoView#Get_Started>`_.
+
+Get set up with Mozilla Central
+-------------------------------
+
+The GeckoView codebase is part of the main Firefox tree and can be found
+in ``mozilla-central``. You will need to get set up as a contributor to
+Firefox in order to contribute to GeckoView. To get set up with
+``mozilla-central``, follow the `Quick Start Guide for Git
+Users <mc-quick-start.html>`_, or the `Contributing to the Mozilla code
+base <https://firefox-source-docs.mozilla.org/setup/contributing_code.html>`_
+guide and `Firefox Contributors’ Quick Reference
+<https://firefox-source-docs.mozilla.org/contributing/contribution_quickref.html>`_
+for Mercurial users.
+
+Once you have a copy of ``mozilla-central``, you will need to build
+GeckoView.
+
+Bootstrap Gecko
+---------------
+
+Bootstrap configures everything for GeckoView and Fennec (Firefox for Android) development.
+
+- Ensure you have ``mozilla-central`` checked out. If this is the first
+ time you are doing this, it may take some time.
+
+.. code:: bash
+
+ git checkout central/default
+
+If you are on a mac, you will need to have the Xcode build tools
+installed. You can do this by either `installing
+Xcode <https://developer.apple.com/xcode/>`__ or installing only the
+tools from the command line by running ``xcode-select --install`` and
+following the on screen instructions.
+
+You will need to ``bootstrap`` for GeckoView/Firefox for Android. The easiest way is to run the following command:
+
+.. code:: bash
+
+ ./mach --no-interactive bootstrap --application-choice="GeckoView/Firefox for Android"
+
+.. note::
+
+ - The ``--no-interactive`` argument will make ``bootstrap`` run start to finish without requiring any input from you. It will automatically accept any license agreements.
+ - The ``--application-choice="GeckoView/Firefox for Android"`` argument is needed when using ``--no-interactive`` so that "bootstrapping" is done for the correct application (instead of the default).
+
+ If you want to make all the selections yourself and/or read through the license agreements, you can simply run:
+
+ .. code:: bash
+
+ ./mach bootstrap
+
+ Select ``4. GeckoView/Firefox for Android`` when prompted and respond to any subsequent prompts as they appear.
+
+Once ``./mach bootstrap`` is complete, it will automatically write
+the configuration into a new ``mozconfig`` file. If you already
+have a ``mozconfig``, ``mach`` will instead output new configuration
+that you should append to your existing file.
+
+Build from the command line
+---------------------------
+
+In order to pick up the configuration changes we just made we need to
+build from the command line. This will update generated sources, compile
+native code, and produce GeckoView AARs and example and test APKs.
+
+.. code:: bash
+
+ ./mach build
+
+Build Using Android Studio
+--------------------------
+
+- Install `Android
+ Studio <https://developer.android.com/studio/install>`_.
+- Choose File->Open from the toolbar
+- Navigate to the root of your ``mozilla-central`` source directory and
+ click “Open”
+- Click yes if it asks if you want to use the gradle wrapper.
+
+ - If the gradle sync does not automatically start, select File >
+ Sync Project with Gradle Files.
+
+- Wait for the project to index and gradle to sync. Once synced, the
+ workspace will reconfigure to display the different projects.
+
+ - annotations contains custom Java annotations used inside GeckoView
+ - app contains geckoview build settings and omnijar. omnijar contains
+ the parts of Gecko and GeckoView that are not written in Java or Kotlin
+ - geckoview is the GeckoView project. Here is all the Java files
+ related to GeckoView
+ - geckoview_example is an example browser built using GeckoView.
+
+ |alt text 1|
+
+Now you’re set up and ready to go.
+
+**Important: at this time, building from Android Studio or directly from
+Gradle does not (re-)compile native code, including C++ and Rust.** This
+means you will need to run ``mach build`` yourself to pick up changes to
+native code. `Bug
+1509539 <https://bugzilla.mozilla.org/show_bug.cgi?id=1509539>`_ tracks
+making Android Studio and Gradle do this automatically.
+
+If you want set up code formatting for Kotlin, please reference
+`IntelliJ IDEA configuration
+<https://pinterest.github.io/ktlint/rules/configuration-intellij-idea/>`_.
+
+Custom mozconfig with Android Studio
+------------------------------------
+
+Out of the box, Android Studio will use the default mozconfig file, normally
+located at ``mozconfig`` in the root directory of your ``mozilla-central``
+checkout.
+
+To make Android Studio use a mozconfig in a custom location, you can add the
+following to your ``local.properties``:
+
+::
+
+ mozilla-central.mozconfig=relative/path/to/mozconfig
+
+Note that, when running mach from the command line, this value will be ignored,
+and the mozconfig from the mach environment will be used instead.
+
+To override the mozconfig used by mach, you can use the `MOZCONFIG` environment
+variable, for example:
+
+::
+
+ MOZCONFIG=debug.mozconfig ./mach build
+
+Performing a bug fix
+--------------------
+
+One you have got GeckoView building and running, you will want to start
+contributing. There is a general guide to `Performing a Bug Fix for Git
+Developers <contributing-to-mc.html>`_ for you to follow. To contribute to
+GeckoView specifically, you will need the following additional
+information.
+
+Running tests and linter locally
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To ensure that your patch does not break existing functionality in
+GeckoView, you can run the junit test suite with the following command
+
+::
+
+ ./mach geckoview-junit
+
+This command also allows you to run individual tests or test classes,
+e.g.
+
+::
+
+ ./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
+ ./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
+
+If your patch makes a GeckoView JavaScript module, you should run ESLint
+as well:
+
+::
+
+ ./mach lint -l eslint mobile/android/modules/geckoview/
+
+To see information on other options, simply run
+``./mach geckoview-junit --help``; of particular note for dealing with
+intermittent test failures are ``--repeat N`` and
+``--run-until-failure``, both of which do exactly what you’d expect.
+
+Updating the changelog and API documentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the patch that you want to submit changes the public API for
+GeckoView, you must ensure that the API documentation is kept up to
+date. To check whether your patch has altered the API, run the following
+command.
+
+.. code:: bash
+
+ ./mach lint --linter android-api-lint
+
+The output of this command will inform you if any changes you have made
+break the existing API. Review the changes and follow the instructions
+it provides.
+
+If the linter asks you to update the changelog, please ensure that you
+follow the correct format for changelog entries. Under the heading for
+the next release version, add a new entry for the changes that you are
+making to the API, along with links to any relevant files, and bug
+number e.g.
+
+::
+
+ - Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
+ not `about:config` should be available.
+ ([bug 1540065]({{bugzilla}}1540065))
+
+ [71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled(boolean)
+
+Submitting to the ``try`` server
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is advisable to run your tests before submitting your patch. You can
+do this using Mozilla’s ``try`` server. To submit a GeckoView patch to
+``try`` before submitting it for review, type:
+
+.. code:: bash
+
+ ./mach try auto
+
+This will automatically select tests to run from our suite. If your patch
+passes on ``try`` you can be (fairly) confident that it will land successfully
+after review.
+
+Tagging a reviewer
+~~~~~~~~~~~~~~~~~~
+
+When submitting a patch to Phabricator, if you know who you want to
+review your patch, put their Phabricator handle against the
+``reviewers`` field.
+
+If you don’t know who to tag for a review in the Phabricator submission
+message, leave the field blank and, after submission, follow the link to
+the patch in Phabricator and scroll to the bottom of the screen until
+you see the comment box.
+
+- Select the ``Add Action`` drop down and pick the ``Change Reviewers`` option.
+- In the presented box, add ``geckoview-reviewers``. Selecting this group as the reviewer will notify all the members of the GeckoView team there is a patch to review.
+- Click ``Submit`` to submit the reviewer change request.
+
+Include GeckoView as a dependency
+---------------------------------
+
+If you want to include a development version of GeckoView as a
+dependency inside another app, you must link to a local copy. There are
+several ways to achieve this, but the preferred way is to use Gradle’s
+*dependency substitution* mechanism, for which there is first-class
+support in ``mozilla-central`` and a pattern throughout Mozilla’s
+GeckoView-consuming ecosystem.
+
+The good news is that ``mach build`` produces everything you need, so
+that after the configuration below, you should find that the following
+commands rebuild your local GeckoView and then consume your local
+version in the downstream project.
+
+.. code:: sh
+
+ cd /path/to/mozilla-central && ./mach build
+ cd /path/to/project && ./gradlew assembleDebug
+
+**Be sure that your ``mozconfig`` specifies the correct ``--target``
+argument for your target device.** Many projects use “ABI splitting” to
+include only the target device’s native code libraries in APKs deployed
+to the device. On x86-64 and aarch64 devices, this can result in
+GeckoView failing to find any libraries, because valid x86 and ARM
+libraries were not included in a deployed APK. Avoid this by setting
+``--target`` to the exact ABI that your device supports.
+
+Dependency substiting your local GeckoView into a Mozilla project
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Most GeckoView-consuming projects produced by Mozilla support dependency
+substitution via ``local.properties``. These projects include:
+
+- `Fenix <https://github.com/mozilla-mobile/firefox-android/tree/main/fenix>`_
+- `reference-browser <https://github.com/mozilla-mobile/reference-browser>`_
+- `android-components <https://github.com/mozilla-mobile/firefox-android/tree/main/android-components>`_
+- `Firefox Reality <https://github.com/MozillaReality/FirefoxReality>`_
+
+Simply edit (or create) the file ``local.properties`` in the project
+root and include a line like:
+
+.. code:: properties
+
+ dependencySubstitutions.geckoviewTopsrcdir=/path/to/mozilla-central
+
+The default object directory – the one that a plain ``mach build``
+discovers – will be used. You can optionally specify a particular object
+directory with an additional line like:
+
+.. code:: properties
+
+ dependencySubstitutions.geckoviewTopobjdir=/path/to/object-directory
+
+With these lines, the GeckoView-consuming project should use the
+GeckoView AAR produced by ``mach build`` in your local
+``mozilla-central``.
+
+**Remember to remove the lines in ``local.properties`` when you want to
+return to using the published GeckoView builds!**
+
+Dependency substituting your local GeckoView into a non-Mozilla project
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In projects that don’t have first-class support for dependency
+substitution already, you can do the substitution yourself. See the
+documentation in
+`substitue-local-geckoview.gradle <https://hg.mozilla.org/mozilla-central/file/tip/substitute-local-geckoview.gradle>`_,
+but roughly: in each Gradle project that consumes GeckoView, i.e., in
+each ``build.gradle`` with a
+``dependencies { ... 'org.mozilla.geckoview:geckoview-...' }`` block,
+include lines like:
+
+.. code:: groovy
+
+ ext.topsrcdir = "/path/to/mozilla-central"
+ ext.topobjdir = "/path/to/object-directory" // Optional.
+ apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
+
+**Remember to remove the lines from all ``build.gradle`` files when you
+want to return to using the published GeckoView builds!**
+
+Next Steps
+----------
+
+- Get started with `Native Debugging <native-debugging.html>`_
+
+.. |alt text| image:: ../assets/DisableInstantRun.png
+.. |alt text 1| image:: ../assets/GeckoViewStructure.png
diff --git a/mobile/android/docs/geckoview/contributor/index.rst b/mobile/android/docs/geckoview/contributor/index.rst
new file mode 100644
index 0000000000..f38b1c5677
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/index.rst
@@ -0,0 +1,29 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+=========================
+Contributing to GeckoView
+=========================
+
+.. toctree::
+ :maxdepth: 1
+ :glob:
+ :hidden:
+
+ *
+
+- `Contributor Quick Start Guide <geckoview-quick-start.html>`_:
+ Get GeckoView set up for development.
+- `GeckoView for Gecko Engineers <for-gecko-engineers.html>`_: A
+ quick-start guide for those already familiar with contributing to
+ Firefox development.
+- `Mozilla Central Quick Start Guide <mc-quick-start.html>`_: Get Mozilla
+ Central set up for development.
+- `Mozilla Central Contributor Guide <contributing-to-mc.html>`_: Get
+ started as a contributor to Mozilla Central.
+- `Guide to Native Debugging in Android Studio <native-debugging.html>`_:
+ Set up Android Studio for debugging native code.
+- `Architecture overview <geckoview-architecture.html>`_: An overview of
+ GeckoView's architecture.
+- `Junit Test Framework <junit.html>`_: An overview of GeckoView's custom
+ Junit code.
+- `apilint <apilint.html>`_: GeckoView's linter for the API.
diff --git a/mobile/android/docs/geckoview/contributor/junit.rst b/mobile/android/docs/geckoview/contributor/junit.rst
new file mode 100644
index 0000000000..bf8cfd4615
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/junit.rst
@@ -0,0 +1,373 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+====================
+Junit Test Framework
+====================
+
+GeckoView has `a lot
+<https://searchfox.org/mozilla-central/rev/36904ac58d2528fc59f640db57cc9429103368d3/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java>`_
+of `custom
+<https://searchfox.org/mozilla-central/source/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support>`_
+code that is used to run junit tests. This document is an overview of what this
+code does and how it works.
+
+.. contents:: Table of Contents
+ :depth: 2
+ :local:
+
+Introduction
+============
+
+`GeckoView <https://geckoview.dev>`_ is an Android Library that can be used to
+embed Gecko, the Web Engine behind Firefox, in applications. It is the
+foundation for Firefox on Android, and it is intended to be used to build Web
+Browsers, but can also be used to build other types of apps that need to
+display Web content.
+
+GeckoView itself has no UI elements besides the Web View and uses Java
+interfaces called "delegates" to let embedders (i.e. apps that use GeckoView)
+implement UI behavior.
+
+For example, when a Web page's JavaScript code calls ``alert('Hello')`` the
+embedder will receive a call to the `onAlertPrompt
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PromptDelegate.html#onAlertPrompt-org.mozilla.geckoview.GeckoSession-org.mozilla.geckoview.GeckoSession.PromptDelegate.AlertPrompt->`_
+method of the `PromptDelegate
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PromptDelegate.html>`_
+interface with all the information needed to display the prompt.
+
+As most delegate methods deal with UI elements, GeckoView will execute them on
+the UI thread for the embedder's convenience.
+
+GeckoResult
+-----------
+
+One thing that is important to understand for what follows is `GeckoResult
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/GeckoResult.html>`_.
+``GeckoResult`` is a promise-like object that is used throughout the GeckoView
+API, it allows embedders to asynchronously respond to delegate calls and
+GeckoView to return results asynchronously. This is especially important for
+GeckoView as it never provides synchronous access to Gecko as a design
+principle.
+
+For example, when installing a WebExtension in GeckoView, the resulting
+`WebExtension
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html>`_
+object is returned in a ``GeckoResult``, which is completed when the extension
+is fully installed:
+
+.. code:: java
+
+ public GeckoResult<WebExtension> install(...)
+
+To simplify memory safety, ``GeckoResult`` will always `execute callbacks
+<https://searchfox.org/mozilla-central/rev/36904ac58d2528fc59f640db57cc9429103368d3/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResult.java#740-744>`_
+in the same thread where it was created, turning asynchronous code into
+single-threaded javascript-style code. This is currently `implemented
+<https://searchfox.org/mozilla-central/rev/36904ac58d2528fc59f640db57cc9429103368d3/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResult.java#285>`_
+using the Android Looper for the thread, which restricts ``GeckoResult`` to
+threads that have a looper, like the Android UI thread.
+
+Testing overview
+----------------
+
+Given that GeckoView is effectively a translation layer between Gecko and the
+embedder, it's mostly tested through integration tests. The vast majority of
+the GeckoView tests are of the form:
+
+- Load simple test web page
+- Interact with the web page through a privileged JavaScript test API
+- Verify that the right delegates are called with the right inputs
+
+and most of the test framework is built around making sure that these
+interactions are easy to write and verify.
+
+Tests in GeckoView can be run using the ``mach`` interface, which is used by
+most Gecko tests. E.g. to run the `loadUnknownHost
+<https://searchfox.org/mozilla-central/rev/36904ac58d2528fc59f640db57cc9429103368d3/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt#186-196>`_
+test in ``NavigationDelegateTest`` you would type on your terminal:
+
+.. code:: shell
+
+ ./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
+
+Another way to run GeckoView tests is through the `Android Studio IDE
+<https://developer.android.com/studio>`_. By running tests this way, however,
+some parts of the test framework are not initialized, and thus some tests
+behave differently or fail, as will be explained later.
+
+Testing envelope
+----------------
+
+Being a library, GeckoView has a natural, stable, testing envelope, namely the
+GeckoView API. The vast majority of GeckoView tests only use
+publicly-accessible APIs to verify the behavior of the API.
+
+Whenever the API is not enough to properly test behavior, the testing framework
+offers targeted "privileged" testing APIs.
+
+Using a restricted, stable testing envelope has proven over the years to be an
+effective way of writing consistent tests that don't break upon refactoring.
+
+Testing Environment
+-------------------
+
+When run through ``mach``, the GeckoView junit tests run in a similar
+environment as mochitests (a type of Web regression tests used in Gecko). They
+have access to the mochitest web server at `example.com`, and inherit most of
+the testing prefs and profile.
+
+Note the environment will not be the same as mochitests when the test is run
+through Android Studio, the prefs will be inherited from the default GeckoView
+prefs (i.e. the same prefs that would be enabled in a consumer's build of
+GeckoView) and the mochitest web server will not be available.
+
+Tests account for this using the `isAutomation
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Environment.java#36-38>`_
+check, which essentially checks whether the test is running under ``mach`` or
+via Android Studio.
+
+Unlike most other junit tests in the wild, GeckoView tests run in the UI
+thread. This is done so that the GeckoResult objects are created on the right
+thread. Without this, every test would most likely include a lot of blocks that
+run code in the UI thread, adding significant boilerplate.
+
+Running tests on the UI thread is achieved by registering a custom ``TestRule``
+called `GeckoSessionTestRule
+<https://searchfox.org/mozilla-central/rev/36904ac58d2528fc59f640db57cc9429103368d3/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt#186-196>`_,
+which, among other things, `overrides the evaluate
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1307,1312>`_
+method and wraps everything into a ``instrumentation.runOnMainSync`` call.
+
+Verifying delegates
+===================
+
+As mentioned earlier, verifying that a delegate call happens is one of the most
+common assertions that a GeckoView test makes. To facilitate that,
+``GeckoSessionTestRule`` offers several ``delegate*`` utilities like:
+
+.. code:: java
+
+ sessionRule.delegateUntilTestEnd(...)
+ sessionRule.delegateDuringNextWait(...)
+ sessionRule.waitUntilCalled(...)
+ sessionRule.forCallbacksDuringWait(...)
+
+These all take an arbitrary delegate object (which may include multiple
+delegate implementations) and handle installing and cleaning up the delegate as
+needed.
+
+Another set of facilities that ``GeckoSessionTestRule`` offers allow tests to
+synchronously ``wait*`` for events, e.g.
+
+.. code:: java
+
+ sessionRule.waitForJS(...)
+ sessionRule.waitForResult(...)
+ sessionRule.waitForPageStop(...)
+
+These facilities work together with the ``delegate*`` facilities by marking the
+``NextWait`` or the ``DuringWait`` events.
+
+As an example, a test could load a page using ``session.loadUri``, wait until
+the page has finished loading using ``waitForPageStop`` and then verify that
+the expected delegate was called using ``forCallbacksDuringWait``.
+
+Note that the ``DuringWait`` here always refers to the last time a ``wait*``
+method was called and finished executing.
+
+The next sections will go into how this works and how it's implemented.
+
+Tracking delegate calls
+-----------------------
+
+One thing you might have noticed in the above section is that
+``forCallbacksDuringWait`` moves "backward" in time by replaying the delegates
+called that happened while the wait was being executed.
+``GeckoSessionTestRule`` achieves this by `injecting a proxy object
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1137>`_
+into every delegate, and `proxying every call
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1091-1092>`_
+to the current delegate according to the ``delegate`` test calls.
+
+The proxy delegate `is built
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1105-1106>`_
+using the Java reflection's ``Proxy.newProxyInstance`` method and receives `a
+callback
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1030-1031>`_
+every time a method on the delegate is being executed.
+
+``GeckoSessionTestRule`` maintains a list of `"default" delegates
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#743-752>`_
+used in GeckoView, and will `use reflection
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#585>`_
+to match the object passed into the ``delegate*`` calls to the proxy delegates.
+
+For example, when calling
+
+.. code:: java
+
+ sessionRule.delegateUntilTestEnd(object : NavigationDelegate, ProgressDelegate {})
+
+``GeckoSessionTestRule`` will know to redirect all ``NavigationDelegate`` and
+``ProgressDelegate`` calls to the object passed in ``delegateUntilTestEnd``.
+
+Replaying delegate calls
+------------------------
+
+Some delegate methods require output data to be passed in by the embedder, and
+this requires extra care when going "backward in time" by replaying the
+delegate's call.
+
+For example, whenever a page loads, GeckoView will call
+``GeckoResult<AllowOrDeny> onLoadRequest(...)`` to know if the load can
+continue or not. When replaying delegates, however, we don't know what the
+value of ``onLoadRequest`` will be (or if the test is going to install a
+delegate for it, either!).
+
+What ``GeckoSessionTestRule`` does, instead, is to `return the default value
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1092>`_
+for the delegate method, and ignore the replayed delegate method return value.
+This can be a little confusing for test writers, for example this code `will
+not` stop the page from loading:
+
+.. code:: java
+
+ session.loadUri("https://www.mozilla.org")
+ sessionRule.waitForPageStop()
+ sessionRule.forCallbacksDuringWait(object : NavigationDelegate {
+ override fun onLoadRequest(session: GeckoSession, request: LoadRequest) :
+ GeckoResult<AllowOrDeny>? {
+ // this value is ignored
+ return GeckoResult.deny()
+ }
+ })
+
+as the page has already loaded by the time the ``forCallbacksDuringWait`` call is
+executed.
+
+Tracking Waits
+--------------
+
+To track when a ``wait`` occurs and to know when to replay delegate calls,
+``GeckoSessionTestRule`` `stores
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1075>`_
+the list of delegate calls in a ``List<CallRecord>`` object, where
+``CallRecord`` is a class that has enough information to replay a delegate
+call. The test rule will track the `start and end index
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1619>`_
+of the last wait's delegate calls and `replay it
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1697-1724>`_
+when ``forCallbacksDuringWait`` is called.
+
+To wait until a delegate call happens, the test rule will first `examine
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1585>`_
+the already executed delegate calls using the call record list described above.
+If none of the calls match, then it will `wait for new calls
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1589>`_
+to happen, using ``UiThreadUtils.waitForCondition``.
+
+``waitForCondition`` is also used to implement other type of ``wait*`` methods
+like ``waitForResult``, which waits until a ``GeckoResult`` is executed.
+
+``waitForCondition`` runs on the UI thread, and it synchronously waits for an
+event to occur. The events it waits for normally execute on the UI thread as
+well, so it `injects itself
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/UiThreadUtils.java#145,153>`_
+in the Android event loop, checking for the condition after every event has
+executed. If no more events remain in the queue, `it posts a delayed 100ms
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/UiThreadUtils.java#136-141>`_
+task to avoid clogging the event loop.
+
+Executing Javascript
+====================
+
+As you might have noticed from an earlier section, the test rule allows tests
+to run arbitrary JavaScript code using ``waitForJS``. The GeckoView API,
+however, doesn't offer such an API.
+
+The way ``waitForJS`` and ``evaluateJS`` are implemented will be the focus of
+this section.
+
+How embedders run javascript
+----------------------------
+
+The only supported way of accessing a web page for embedders is to `write a
+built-in WebExtension
+<https://firefox-source-docs.mozilla.org/mobile/android/geckoview/consumer/web-extensions.html>`_
+and install it. This was done intentionally to avoid having to rewrite a lot of
+the Web-Content-related APIs that the WebExtension API offers.
+
+GeckoView extends the WebExtension API to allow embedders to communicate to the
+extension by `overloading
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/modules/geckoview/GeckoViewWebExtension.jsm#221>`_
+the native messaging API (which is not normally implemented on mobile).
+Embedders can register themselves as a `native app
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html>`_
+and the built-in extension will be able to `exchange messages
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Port.html#postMessage-org.json.JSONObject->`_
+and `open ports
+<https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html#onConnect-org.mozilla.geckoview.WebExtension.Port->`_
+with the embedder.
+
+This is still a controversial topic among smaller embedders, especially solo
+developers, and we have discussed internally the possibility to expose a
+simpler API to run one-off javascript snippets, similar to what Chromium's
+WebView offers, but nothing has been developed so far.
+
+The test runner extension
+-------------------------
+
+To run arbitrary javascript in GeckoView, the test runner installs a `support
+extension
+<https://searchfox.org/mozilla-central/source/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support>`_.
+
+The test framework then `establishes
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1827>`_
+a port for the background script, used to run code in the main process, and a
+port for every window, to be able to run javascript on test web pages.
+
+When ``evaluateJS`` is called, the test framework will send `a message
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1912>`_
+to the extension which then `calls eval
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-support.js#21>`_
+on it and returns the `JSON`-stringified version of the result `back
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1952-1956>`_
+to the test framework.
+
+The test framework also supports promises with `evaluatePromiseJS
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1888>`_.
+It works similarly to ``evaluateJS`` but instead of returning the stringified
+value, it `sets
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1879>`_
+the return value of the ``eval`` call into the ``this`` object, keyed by a
+randomly-generated UUID.
+
+.. code:: java
+
+ this[uuid] = eval(...)
+
+``evaluatePromiseJS`` then returns an ``ExtensionPromise`` Java object which
+has a ``getValue`` method on it, which will essentially execute `await
+this[uuid]
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#1883-1885>`_
+to get the value from the promise when needed.
+
+Beyond executing javascript
+---------------------------
+
+A natural way of breaking the boundaries of the GeckoView API is to run a
+so-called "experiment extension". Experiment extensions have access to the full
+Gecko front-end, which is written in JavaScript, and don't have limits on what
+they can do. Experiment extensions are essentially what old add-ons used to be
+in Firefox, very powerful and very dangerous.
+
+The test runner uses experiments to offer `privileged APIs
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-api.js>`_
+to tests like ``setPref`` or ``getLinkColor`` (which is not normally available
+to websites for privacy concerns).
+
+Each privileged API is exposed as an `ordinary Java API
+<https://searchfox.org/mozilla-central/rev/95d8478112eecdd0ee249a941788e03f47df240b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java#2101>`_
+and the test framework doesn't offer a way to run arbitrary chrome code to
+discourage developers from relying too much on implementation-dependent
+privileged code.
diff --git a/mobile/android/docs/geckoview/contributor/mc-quick-start.rst b/mobile/android/docs/geckoview/contributor/mc-quick-start.rst
new file mode 100644
index 0000000000..bac9dc3ce5
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/mc-quick-start.rst
@@ -0,0 +1,184 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+===========================
+Mozilla Central Quick Start
+===========================
+
+Table of contents
+=================
+
+.. contents:: :local:
+
+Firefox Developer Git Quick Start Guide
+=======================================
+
+Getting setup to as a first time Mozilla contributor is hard. There are
+plenty of guides out there to help you get started as a contributor, but
+many of the new contributor guides out of date often more current ones
+are aimed at more experienced contributors. If you want to review these
+guides, you can find several linked to from
+:ref:`Working on Firefox <Working on Firefox>`.
+
+This guide will take you through setting up as a contributor to
+``mozilla-central``, the Firefox main repository, as a git user.
+
+Setup
+-----
+
+The first thing you will need is to install Mercurial as this is the VCS
+that ``mozilla-central`` uses.
+
+.. _mac-0:
+
+Mac
+~~~
+
+.. _homebrew-0:
+
+Homebrew
+^^^^^^^^
+
+.. code:: bash
+
+ brew install mercurial
+
+macports
+^^^^^^^^
+
+.. code:: bash
+
+ sudo port install mercurial
+
+Linux
+~~~~~
+
+apt
+^^^
+
+.. code:: bash
+
+ sudo apt-get install mercurial
+
+Alternatively you can install `Mercurial directly <https://www.mercurial-scm.org/wiki/Download>`_.
+
+Check that you have successfully installed Mercurial by running:
+
+.. code:: bash
+
+ hg --version
+
+If you are an experienced git user and are unfamiliar with Mercurial,
+you may want to install ``git-cinnabar``. Cinnabar is a git remote
+helper that allows you to interact with Mercurial repos using git
+semantics.
+
+git-cinnabar
+------------
+
+There is a Homebrew install option for ``git-cinnabar``, but this did
+not work for me, nor did the installer option. Using these tools, when I
+tried to clone the Mercurial repo it hung and did not complete. I had to
+do a manual install before I could use ``git-cinnabar`` successfully to
+download a Mercurial repo. If you would like to try either of these
+option, however, here they are:
+
+.. _mac-1:
+
+Mac
+~~~~~
+
+.. _homebrew-1:
+
+Homebrew
+^^^^^^^^
+
+.. code:: bash
+
+ brew install git-cinnabar
+
+All Platforms
+~~~~~~~~~~~~~
+
+Installer
+^^^^^^^^^
+
+.. code:: bash
+
+ git cinnabar download
+
+Manual installation
+^^^^^^^^^^^^^^^^^^^
+
+.. code:: bash
+
+ git clone https://github.com/glandium/git-cinnabar.git && cd git-cinnabar
+ make
+ export PATH="$PATH:/somewhere/git-cinnabar"
+ echo 'export PATH="$PATH:/somewhere/git-cinnabar"' >> ~/.bash_profile
+ git cinnabar download
+
+``git-cinnabar``\ ’s creator, `glandium <https://glandium.org/>`_, has
+written a number of posts about setting up for Firefox Development with
+git. This `post <https://glandium.org/blog/?page_id=3438>`_ is the one
+that has formed the basis for this walkthrough.
+
+In synopsis:
+
+- initialize an empty git repository
+
+.. code:: bash
+
+ git init gecko && cd gecko
+
+- Configure git:
+
+.. code:: bash
+
+ git config fetch.prune true
+ git config push.default upstream
+
+- Add remotes for your repositories. There are several to choose from,
+ ``central``, ``inbound``, ``beta``, ``release`` etc. but in reality,
+ if you plan on using Phabricator, which is Firefox’s preferred patch
+ submission system, you only need to set up ``central``. It might be
+ advisable to have access to ``inbound`` however, if you want to work
+ on a version of Firefox that is queued for release. This guide will
+ be focused on Phabricator.
+
+.. code:: bash
+
+ git remote add central hg::https://hg.mozilla.org/mozilla-central -t branches/default/tip
+ git remote add inbound hg::https://hg.mozilla.org/integration/mozilla-inbound -t branches/default/tip
+ git remote set-url --push central hg::ssh://hg.mozilla.org/mozilla-central
+ git remote set-url --push inbound hg::ssh://hg.mozilla.org/integration/mozilla-inbound
+
+- Expose the branch tip to get quick access with some easy names.
+
+.. code:: bash
+
+ git config remote.central.fetch +refs/heads/branches/default/tip:refs/remotes/central/default
+ git config remote.inbound.fetch +refs/heads/branches/default/tip:refs/remotes/inbound/default
+
+- Setup a remote for the try server. The try server is an easy way to
+ test a patch without actually checking the patch into the core
+ repository. Your code will go through the same tests as a
+ ``mozilla-central`` push, and you’ll be able to download builds if
+ you wish.
+
+.. code:: bash
+
+ git remote add try hg::https://hg.mozilla.org/try
+ git config remote.try.skipDefaultUpdate true
+ git remote set-url --push try hg::ssh://hg.mozilla.org/try
+ git config remote.try.push +HEAD:refs/heads/branches/default/tip
+
+- Now update all the remotes. This performs a ``git fetch`` on all the
+ remotes. Mozilla Central is a *large* repository. Be prepared for
+ this to take a very long time.
+
+.. code:: bash
+
+ git remote update
+
+All that’s left to do now is pick a bug to fix and `submit a
+patch <contributing-to-mc.html>`__.
diff --git a/mobile/android/docs/geckoview/contributor/native-debugging.rst b/mobile/android/docs/geckoview/contributor/native-debugging.rst
new file mode 100644
index 0000000000..774fe35cce
--- /dev/null
+++ b/mobile/android/docs/geckoview/contributor/native-debugging.rst
@@ -0,0 +1,262 @@
+.. -*- Mode: rst; fill-column: 80; -*-
+
+=====================
+Debugging Native Code
+=====================
+
+Table of contents
+=================
+
+.. contents:: :local:
+
+Debugging Native Code in Android Studio.
+========================================
+
+If you want to work on the C++ code that powers GeckoView, you will need
+to be able to perform native debugging inside Android Studio. This
+article will guide you through how to do that.
+
+If you need to get set up with GeckoView for the first time, follow the
+`Quick Start Guide <geckoview-quick-start.html>`_.
+
+Perform a debug build of Gecko.
+-------------------------------
+
+1. Edit your ``mozconfig`` file and add the following lines. These will
+ ensure that the build includes debug checks and symbols.
+
+.. code:: text
+
+ ac_add_options --enable-debug
+
+2. Ensure that the following lines are commented out in your
+ ``mozconfig`` if present. ``./mach configure`` will not allow
+ artifact builds to be enabled when generating a debug build.
+
+.. code:: text
+
+ # ac_add_options --enable-artifact-builds
+
+3. To be absolutely sure that Android Studio will pick up your debug
+ symbols, the first time you perform a debug build it is best to
+ clobber your ``MOZ_OBJDIR``. Subsequent builds should not need this
+ step.
+
+.. code:: bash
+
+ ./mach clobber
+
+4. Build as usual. Because this is a debug build, and because you have
+ clobbered your ``MOZ_OBJDIR``, this will take a long time. Subsequent
+ builds will be incremental and take less time, so go make yourself a
+ cup of your favourite beverage.
+
+.. code:: bash
+
+ ./mach build
+
+Set up lldb to find your symbols
+--------------------------------
+
+Edit your ``~/.lldbinit`` file (or create one if one does not already
+exist) and add the following lines.
+
+The first line tells LLDB to enable inline breakpoints - Android Studio
+will need this if you want to use visual breakpoints.
+
+The remaining lines tell LLDB where to go to find the symbols for
+debugging.
+
+.. code:: bash
+
+ settings set target.inline-breakpoint-strategy always
+ settings append target.exec-search-paths <PATH>/objdir-android-opt/toolkit/library/build
+ settings append target.exec-search-paths <PATH>/objdir-android-opt/mozglue/build
+ settings append target.exec-search-paths <PATH>/objdir-android-opt/security
+
+Set up Android Studio to perform native debugging.
+==================================================
+
+1. Edit the configuration that you want to debug by clicking
+ ``Run -> Edit Configurations...`` and selecting the correct
+ configuration from the options on the left hand side of the resulting
+ window.
+2. Select the ``Debugger`` tab.
+3. Select ``Dual`` from the ``Debug type`` select box. Dual will allow
+ debugging of both native and Java code in the same session. It is
+ possible to use ``Native``, but it will only allow for debugging
+ native code, and it’s frequently necessary to break in the Java code
+ that configures Gecko and child processes in order to attach
+ debuggers at the correct times.
+4. Under ``Symbol Directories``, add a new path pointing to
+ ``<PATH>/objdir-android-opt/toolkit/library/build``, the same path
+ that you entered into your ``.lldbinit`` file.
+5. Select ``Apply`` and ``OK`` to close the window.
+
+Debug Native code in Android Studio
+===================================
+
+1. The first time you are running a debug session for your app, it’s
+ best to start from a completely clean build. Click
+ ``Build -> Rebuild Project`` to clean and rebuild. You can also
+ choose to remove any existing builds from your emulator to be
+ completely sure, but this may not be necessary.
+2. If using Android Studio visual breakpoints, set your breakpoints in
+ your native code.
+3. Run the app in debug mode as usual.
+4. When debugging Fennec or geckoview_example, you will almost
+ immediately hit a breakpoint in ``ElfLoader.cpp``. This is expected.
+ If you are not using Android Studio visual breakpoints, you can set
+ your breakpoints here using the lldb console that is available now
+ this breakpoint has been hit. To set a breakpoint, select the app tab
+ (if running Dual, there will also be an ``<app> java`` tab) from the
+ debug window, and then select the ``lldb`` console tab. Type the
+ following into the console:
+
+.. code:: text
+
+ b <file>.cpp:<line number>
+
+5. Once your breakpoints have been set, click the continue execution
+ button to move beyond the ``ElfLoader`` breakpoint and your newly set
+ native breakpoints should be hit. Debug as usual.
+
+Attaching debuggers to content and other child processes
+--------------------------------------------------------
+
+Internally, GeckoView has a multi-process architecture. The main Gecko
+process lives in the main Android process, but content rendering and
+some other functions live in child processes. This balances load,
+ensures certain critical security properties, and allows GeckoView to
+recover if content processes become unresponsive or crash. However, it’s
+generally delicate to debug child processes because they come and go.
+
+The general approach is to make the Java code in the child process that
+you want to debug wait for a Java debugger at startup, and then to
+connect such a Java debugger manually from the Android Studio UI.
+
+`Bug 1522318 <https://bugzilla.mozilla.org/show_bug.cgi?id=1522318>`__
+added environment variables that makes GeckoView wait for Java debuggers
+to attach, making this debug process more developer-friendly. See
+`Configuring GeckoView for Automation <../consumer/automation.html>`__
+for instructions on how to set environment variables that configure
+GeckoView’s runtime environment.
+
+Making processes wait for a Java debugger
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``set-debug-app`` command will make Android wait for a debugger before
+running an app or service. e.g., to make GeckoViewExample wait, run the
+following:
+
+.. code:: shell
+
+ adb shell am set-debug-app -w --persistent org.mozilla.geckoview_example
+
+The above command works with child processes too, e.g. to make the GPU
+process wait for a debugger, run:
+
+.. code:: shell
+
+ adb shell am set-debug-app -w --persistent org.mozilla.geckoview_example:gpu
+
+
+Attaching a Java debugger to a waiting child process
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is standard: follow the `Android Studio instructions <https://developer.android.com/studio/debug/index.html#attach-debugger>`_.
+You must attach a Java debugger, so you almost certainly want to attach
+a ``Dual`` debugger and you definitely can’t attach only a ``Native``
+debugger.
+
+Determining the correct process to attach to is a little tricky because
+the mapping from process ID (pid) to process name is not always clear.
+Gecko content child processes are suffixed ``:tab`` at this time.
+
+If you attach ``Dual`` debuggers to both the main process and a content
+child process, you will have four (4!) debug tabs to manage in Android
+Studio, which is awkward. Android Studio doesn’t appear to configure
+attached debuggers in the same way that it configures debuggers
+connecting to launched Run Configurations, so you may need to manually
+configure search paths – i.e., you may need to invoke the contents of
+your ``lldbinit`` file in the appropriate ``lldb`` console by hand,
+using an invocation like
+``command source /absolute/path/to/topobjdir/lldbinit``.
+
+Android Studio also doesn’t appear to support targeting breakpoints from
+the UI (say, from clicking in a gutter) to specific debug tabs, so you
+may also need to set breakpoints in the appropriate ``lldb`` console by
+hand.
+
+Managing more debug tabs may require different approaches.
+
+Debug Native Memory Allocations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Android Studio includes a `Native Memory Profiler
+<https://developer.android.com/studio/profile/memory-profiler#native-memory-profiler>`_
+which works for physical devices running Android 10 and later. In order to
+track allocations correctly Gecko must be built with ``jemalloc`` disabled.
+Additionally, the native memory profiler appears to only work with ``aarch64``
+builds. The following must therefore be present in your ``mozconfig`` file:
+
+.. code:: text
+
+ ac_add_options --target=aarch64
+ ac_add_options --disable-jemalloc
+
+The resulting profiles are symbolicated correctly in debug builds, however, you
+may prefer to use a release build when profiling. Unfortunately a method to
+symbolicate using local symbols from the development machine has not yet been
+found, therefore in order for the profile to be symbolicated you must prevent
+symbols being stripped during the build process. To do so, add the following to
+your ``mozconfig``:
+
+.. code:: text
+
+ ac_add_options STRIP_FLAGS=--strip-debug
+
+And the following to ``mobile/android/geckoview/build.gradle``, and additionally
+to ``mobile/android/geckoview_example/build.gradle`` if profiling GeckoView
+Example, or ``app/build.gradle`` if profiling Fenix, for example.
+
+.. code:: groovy
+
+ android {
+ packagingOptions {
+ doNotStrip "**/*.so"
+ }
+ }
+
+Using Android Studio on Windows
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can now use :ref:`artifact builds <Understanding Artifact Builds>`
+mode on `MozillaBuild environment <https://wiki.mozilla.org/MozillaBuild>`_ even if you are
+not using WSL. If you want to debug GeckoView using Android Studio on
+Windows, you have to set an additional environment variable via the
+Control Panel to run the gradle script. The ``mach`` command sets these
+variables automatically, but Android Studio cannot.
+
+If you install MozillaBuild tools to ``C:\mozilla-build`` (default
+installation path), you have to set the ``MOZILLABUILD`` environment
+variable to recognize MozillaBuild installation path.
+
+To set environment variable on Windows 10, open the ``Control Panel``
+from ``Windows System``, then select ``System and Security`` -
+``System`` - ``Advanced system settings`` -
+``Environment Variables ...``.
+
+To set the ``MOZILLABUILD`` variable, click ``New...`` in
+``User variables for``, then ``Variable name:`` is ``MOZILLABUILD`` and
+``Variable value:`` is ``C:\mozilla-build``.
+
+You also have to append some tool paths to the ``Path`` environment
+variable.
+
+To append the variables to PATH, double click ``Path`` in
+``User Variables for``, then click ``New``. And append the following
+variables to ``Path``.
+
+- ``%MOZILLABUILD%\msys\bin``
+- ``%MOZILLABUILD%\bin``