tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

geckoview-quick-start.rst (19569B)


      1 .. -*- Mode: rst; fill-column: 80; -*-
      2 
      3 .. _geckoview-contributor-guide:
      4 
      5 =================
      6 Contributor Guide
      7 =================
      8 
      9 Table of contents
     10 =================
     11 
     12 .. contents:: :local:
     13 
     14 GeckoView Contributor Quick Start Guide
     15 =======================================
     16 
     17 This is a guide for developers who want to contribute to the GeckoView
     18 project. If you want to get started using GeckoView in your app then you
     19 should refer to the
     20 `wiki <https://wiki.mozilla.org/Mobile/GeckoView#Get_Started>`_.
     21 
     22 Background
     23 -----------
     24 GeckoView is a public API that exposes core Gecko functionality to GeckoView consumers.
     25 Several Mozilla products use GeckoView as their core entry-way into Gecko. For example,
     26 Android Components has GeckoView as a dependency and uses it to communicate with Gecko.
     27 Fenix, Focus, and Reference Browser have Android Components as a dependency and build a browser
     28 on top of this framework.
     29 
     30 The architecture, in broad strokes, looks like this:
     31 
     32 Gecko <-> GeckoView <-> Android Components <-> Fenix or Focus or Reference Browser
     33 
     34 *   **Gecko** is the fundamental platform that the rest are built on. It is a multilayered robust platform that conforms to standards related to browser mechanics.
     35 *   **GeckoView** exposes key portions of Gecko for API consumers to use in Android systems. A subset of key Gecko functionality is exposed this way. It is a public API, so public API changes are designed to always be non-breaking and follow a deprecation process.
     36 *   **Android Components** links to GeckoView to support Gecko browsers. It is platform-independent of Gecko and GeckoView. For example, another browser engine could be used instead of Gecko. It also provides other reusable browser-building components.
     37 *   **Fenix or Focus or Reference Browser** are the end app products. They contain the primary view layer and connect everything together to form a final product.
     38 
     39 Please keep this architecture in mind while solving bugs. Identifying the correct layer to solve a bug is an important first step for any bug.
     40 
     41 Performing a bug fix
     42 --------------------
     43 
     44 As a first step, you need to set up :ref:`mozilla-central <mozilla-central-setup>`,
     45 and :ref:`Bootstrap <bootstrap-setup>` and build the project.
     46 
     47 Once you have got GeckoView building and running, you will want to start
     48 contributing. There is a general guide to `Performing a Bug Fix for Git
     49 Developers <contributing-to-firefox.html>`_ for you to follow. To contribute to
     50 GeckoView specifically, you will need the following additional
     51 information.
     52 
     53 Debugging code
     54 ~~~~~~~~~~~~~~~~~~~~
     55 Because GeckoView is on many layers, often the best debugging tool depends on the layer the bug is on.
     56 For Java or Kotlin code, using the Android Studio IDE is an easy way to connect a debugger and set breakpoints. It can
     57 also be used with C++ code once native debugging is setup. Please see this guide on `Native Debugging <native-debugging.html>`_.
     58 
     59 For JavaScript code, it is possible to connect a debugger using Firefox Desktop Nightly's `about:debugging` section. The device must be setup to support
     60 USB connections and the device likely needs developer mode enabled.
     61 
     62 Sometimes it is easier to leave logs to help trace exactly which layer the bug is on first, to do this on the various layers:
     63 
     64 * **Java** - ``Log.i("Any Tag", "Any string " + variable.toString())``
     65 
     66  * May be used for permanent logging in GeckoView, but should follow existing logging practices. Requires an import.
     67 
     68  * Note, Android Components has different permanent logging practices.
     69 
     70 * **JavaScript** - ``dump("Any string " + variable)``
     71 
     72  * May not be used for permanent logging.
     73 
     74  * May need to use ``JSON.stringify(variable)`` to deserialize objects in JavaScript.
     75 
     76 * **JavaScript** - ``debug`Any String ${variable}```
     77 
     78  * May be used for permanent logging, but should follow existing logging practices. Requires an import.
     79 
     80  * Recommend ``dump`` for earlier debugging.
     81 
     82 * **JavaScript** - ``console.log("Any String " + variable)``
     83 
     84  * May be viewed using ``about:debugging`` on Desktop to a connected device and then connecting to the content process.
     85 
     86 * **C++** - ``MOZ_LOG``
     87 
     88  * Use ``about:logging`` or set the ``logging`` preference directly. For example, ``--setpref="logging.LOG_MODULE_NAME=LOG_MODULE_VALUE"`` or manually in ``about:config``.
     89 
     90 * **C++** - ``printf_stderr("Any String")`` or ``__android_log_write(ANDROID_LOG_INFO, "Any Tag", "Any string");`` or ``__android_log_print(ANDROID_LOG_INFO, "Any Tag", "Any string");``
     91 
     92  * None of these may be used for permanent logging, only for debugging. Use ``MOZ_LOG`` for permanent logging.
     93 
     94  * Variable logging will need to be converted to a C string or other supported logging string.
     95 
     96  * Permanent logging for a GeckoView C++ file could be setup similar to:
     97 
     98      ::
     99 
    100          #define GVS_LOG(...) MOZ_LOG(sGVSupportLog, LogLevel::Info, (__VA_ARGS__))
    101          static mozilla::LazyLogModule sGVSupportLog("Any Tag");
    102          GVS_LOG("Any string");
    103 
    104 Please be sure to remove any non-permanent debugging logs prior to requesting landing.
    105 
    106 To view logging on Android, attach a device, and run ``adb logcat -v color`` for colorful logs or else use the Android Studio log frame.
    107 
    108 Running tests and linter locally
    109 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    110 
    111 To ensure that your patch does not break existing functionality in
    112 GeckoView, you can run the junit test suite with the following command
    113 
    114 ::
    115 
    116   ./mach geckoview-junit
    117 
    118 This command also allows you to run individual tests or test classes,
    119 e.g.
    120 
    121 ::
    122 
    123   ./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
    124   ./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
    125 
    126 To see information on other options, simply run
    127 ``./mach geckoview-junit --help``; of particular note for dealing with
    128 intermittent test failures are ``--repeat N`` and
    129 ``--run-until-failure``, both of which do exactly what you’d expect.
    130 If a test is intermittently failing, consult `Debugging Intermittent Test Failures </testing/debugging-intermittents/index.html>`_ for additional tips.
    131 
    132 Other tests, such as mochitests, may be ran using:
    133 
    134 ::
    135 
    136   ./mach test <path-or-dir-to-test>
    137 
    138 
    139 Core GeckoView lints are:
    140 
    141 ::
    142 
    143   # Will perform general Android specific formatting and linting.
    144   ./mach lint -l android-format
    145   # Will determine if GeckoView API changes happened, find more info at API documentation below, if changes occurred.
    146   ./mach lint --linter android-api-lint
    147   # Will perform static analysis and report required changes.
    148   ./mach lint --warnings --outgoing
    149 
    150 For the linters below, add ``--fix`` to the command for the linter to fix the issue automatically.
    151 Note, using ``--fix`` will make changes. Most commands also accept a specific file or directory to
    152 speed up linting.
    153 
    154 If your patch makes a GeckoView JavaScript module, you should run ESLint:
    155 
    156 ::
    157 
    158   ./mach lint -l eslint mobile/android/modules/geckoview/
    159 
    160 If your patch makes a C++ file change, you should run the C++ linter formatter:
    161 
    162 ::
    163 
    164   ./mach clang-format -p <path/to/file.cpp>
    165 
    166 
    167 If your patch makes a Python file change:
    168 
    169 ::
    170 
    171   ./mach lint --linter flake8
    172   ./mach lint --linter black
    173 
    174 
    175 Additionally, sometimes lints can be automatically detected and fixed on certain files, for example:
    176 
    177 ::
    178 
    179   # Will attempt to detect the linter and fix any issues.
    180   # Note, using ``--fix`` will make code changes.
    181   ./mach lint --fix <path-to-file>
    182 
    183 
    184 Updating the changelog and API documentation
    185 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    186 
    187 GeckoView is a public API. We carefully document changes so that other
    188 users of the API can update accordingly.
    189 
    190 If the patch has made public API changes, then a new `api.txt` and `CHANGELOG.md` entry will be needed.
    191 Additionally, a hash is generated to track these changes. This hash, which is also
    192 sometimes referred to as an API key in this document, is added to the bottom of the changelog.
    193 
    194 The following steps will go through the commands of checking for public API changes,
    195 generating a new updated `api.txt`, generating a new API hash, and recommendations for a `CHANGELOG.md` entry.
    196 
    197 
    198 To check whether your patch has altered the API, run the following
    199 command:
    200 
    201 .. code:: bash
    202 
    203   ./mach lint --linter android-api-lint
    204 
    205 The output of this command will inform you if any changes you have made
    206 break the existing API. The first run of the command will tell you if there are API changes.
    207 It will also provide the next command.
    208 (A second run at the end of the `api.txt` generating process will state the API hash.)
    209 
    210 If a change is needed, the next command to preview the expected API changes will be:
    211 
    212 .. code:: bash
    213 
    214    ./mach gradle geckoview:apiLintDebug
    215 
    216 Running the above command should cause the build to fail and will explain what it detected.
    217 The next step will generate a new `api.txt` file, which is a running list of public functions.
    218 
    219 If the changes look as expected, then it is time to generate `api.txt` by running this command:
    220 
    221 .. code:: bash
    222 
    223    ./mach gradlew geckoview:apiUpdateFileDebug
    224 
    225 The build should pass this time, and an updated `api.txt` file will be generated for the changes.
    226 
    227 Finally, follow the next command to get the API hash for the CHANGELOG:
    228 
    229 .. code:: bash
    230 
    231    ./mach lint --linter android-api-lint
    232 
    233 In the `CHANGELOG` `file <https://searchfox.org/mozilla-central/source/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md>`_.
    234 at the bottom, swap `[api-version]` with the new hash provided by the linter and add an entry for what changed.
    235 
    236 The feature and methods should also be documented in the changelog similar to the example below.
    237 
    238 The format should be as follows:
    239 
    240 ::
    241 
    242   - Summary of changes that should mention the method name, along with the respective class /
    243     interface name, the major version and the index, and the bug ID, along with the
    244     bugzilla link.
    245 
    246   [<major_version>.<index>]: {{javadoc_uri}}/<url_path>
    247 
    248 To determine the index, take the next index in the list of
    249 ``[<major_version>.<index>]``. If no list is present, start with ``index = 1``.
    250 
    251 - **Example for Adding a Method Changelog Entry**
    252 
    253 ::
    254 
    255   # v71
    256   - Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
    257     not `about:config` should be available.
    258     ([bug 1540065]({{bugzilla}}1540065))
    259 
    260   [71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled(boolean)
    261 
    262 On more complicated features, sometimes it isn't obvious what the URL signature is for the
    263 CHANGELOG. In that case, create the javadoc locally (instructions below) to confirm the URL paths.
    264 
    265 If patch changes are made during review, be sure to re-generate new signatures and API hashes. Generally,
    266 unstaging `api.txt` is the easiest way to accomplish this.
    267 
    268 A special situation is when a patch changing the API may need to be uplifted to an earlier
    269 branch of mozilla-central, for example, to the beta channel. To do this, follow the usual uplift
    270 steps and make a version of the patch for uplift that is graphed onto the new target branch and
    271 rerun the API linter commands and update the CHANGELOG to the release it will be graphed onto.
    272 
    273 Creating JavaDoc Locally
    274 ~~~~~~~~~~~~~~~~~~~~~~~~
    275 GeckoView is a public API, so well maintained javadoc is an important practice. To create the
    276 javadoc locally, we use the following command:
    277 
    278 .. code:: bash
    279 
    280   ./mach android geckoview-docs
    281 
    282 
    283 To view the javadoc locally, first find the directory:
    284 
    285 - In your ``mozilla-unified`` directory, type the following command:
    286 
    287  .. code:: bash
    288 
    289     find . -name javadoc  -path '*/geckoview/*'
    290 
    291  This should return the relative path of the local geckoview javadoc.
    292 
    293  As an example, the output could be this:
    294 
    295  .. code:: bash
    296 
    297      ./obj-aarch64-unknown-linux-android/gradle/build/mobile/android/geckoview/docs/javadoc
    298 
    299  Then, use the following command to go into the directory of the local javadoc:
    300 
    301  .. code:: bash
    302 
    303     cd path_of_javadoc_from_above
    304 
    305 Now, we want to launch a local web server. To launch locally, use any web server, for example:
    306 
    307 .. code:: bash
    308 
    309   python3 -m http.server 8000
    310 
    311 
    312 In this example, navigate to the web docs via ``http://localhost:8000/``.
    313 
    314 .. note::
    315    If you get a 404 error, please ensure that you have navigated to the correct directory and try
    316    launching the web server again.
    317 
    318 Then, look for the changed method in the list displayed on the webpage and click into it.
    319 
    320 For using this to identify URLs for the `CHANGELOG`, copy everything after ``.../org/mozilla/geckoview/``.
    321 Fill in the entry by doing ``{{javadoc_uri}}/<paste_the_copied_text>``. See the example above
    322 for reference.
    323 
    324 Deprecation Policy
    325 ~~~~~~~~~~~~~~~~~~~
    326 GeckoView follows a deprecation policy you can learn more in this
    327 `design doc <https://firefox-source-docs.mozilla.org/mobile/android/geckoview/design/breaking-changes.html>`_.
    328 
    329 To deprecate an API, add the deprecation flags with an identifier for a
    330 deprecation notice, so that all notices with the same identifier will
    331 be removed at the same time (see below for an example). The version is the major version of when
    332 we expect to remove the deprecated member attached to the annotation.
    333 The GeckoView team instituted a deprecation policy which requires each
    334 backward-incompatible change to keep the old code for 3 releases,
    335 allowing downstream consumers, like Fenix, time to migrate asynchronously
    336 to the new code without breaking the build.
    337 
    338 ::
    339 
    340    @Deprecated
    341    @DeprecationSchedule(id = "<interface_or_class_of_method>-<method_name>", version = <Current Nightly + 3>)
    342 
    343 Since this is a public API, the changelog must also be updated. Please ensure that you
    344 follow the correct format for changelog entries. Under the heading for
    345 the next release version, add a new entry for the changes that you are
    346 making to the API, along with links to any relevant files, and bug
    347 number.
    348 
    349 - **Example for Deprecating a Method Changelog**
    350 
    351 ::
    352 
    353   - ⚠️ Deprecated [`GeckoSession.ContentDelegate.onProductUrl`][128.5], will now be removed in v131.
    354   ([bug 1898055]({{bugzilla}}1898055))
    355 
    356   [128.5]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onProductUrl(org.mozilla.geckoview.GeckoSession)
    357 
    358 If an API is deprecated, file a follow-up bug or leave the bug open by
    359 adding the keyword `leave-open` to remove and clean up the deprecated
    360 API for the version it is to be removed on. Also, ensure that running the API linter commands
    361 has changed the javadoc of the deprecated method to indicate that the method has been scheduled
    362 for deprecation. If not, ensure to do this manually.
    363 
    364 Submitting to the ``try`` server
    365 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    366 
    367 It is advisable to run your tests before submitting your patch. You can
    368 do this using Mozilla’s ``try`` server. To submit a GeckoView patch to
    369 ``try`` before submitting it for review, type:
    370 
    371 .. code:: bash
    372 
    373   ./mach try --preset android-geckoview
    374 
    375 This will automatically run critical tests from the GeckoView test suite. If your patch
    376 passes on ``try`` you can be (fairly) confident that it will land successfully
    377 after review.
    378 
    379 Failures on ``try`` will show up with the test name highlighted in orange. Select the test to find out more.
    380 Intermittent failures occasionally occur due to issues with the test harness. Retriggering the test is a good way
    381 to confirm it is an intermittent failure and not due to the patch. Usually there will also be a bug number with
    382 a portion of the stack trace as well for documented intermittent failures.
    383 See `Intermittent Test Failures </devtools/tests/debugging-intermittents.html>`_ for more information.
    384 
    385 To debug failures on try, it is always a good idea to check the logcat. To do this, select the individual test,
    386 select "Artifacts and Debugging" and then open the log from "logcat-emulator-5554.log".
    387 
    388 Tagging a reviewer
    389 ~~~~~~~~~~~~~~~~~~
    390 
    391 When submitting a patch to Phabricator, if you know who you want to
    392 review your patch, put their Phabricator handle against the
    393 ``reviewers`` field.
    394 
    395 If you don’t know who to tag for a review in the Phabricator submission
    396 message, leave the field blank and, after submission, follow the link to
    397 the patch in Phabricator and scroll to the bottom of the screen until
    398 you see the comment box.
    399 
    400 - Select the ``Add Action`` drop down and pick the ``Change Reviewers`` option.
    401 - 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.
    402 - Click ``Submit`` to submit the reviewer change request.
    403 
    404 
    405 GeckoView, Android Components, Fenix, Focus, and Reference Browser Dependency Substitution
    406 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    407 Internal product dependency substitution is handled automatically in mozilla-central on full builds. When building, the substitution
    408 into these other products will happen automatically after `./mach build` is ran. However, in artifact builds, changes in
    409 Gecko or GeckoView will not consistently be reflected. If making changes to Gecko or GeckoView, it is **strongly** recommended
    410 to only use full builds as changes in Gecko or GeckoView may not be reflected when using artifact builds.
    411 
    412 Include GeckoView as a dependency
    413 ---------------------------------
    414 
    415 If you want to include a development version of GeckoView as a
    416 dependency inside another app, you must link to a local copy. There are
    417 several ways to achieve this, but the preferred way is to use Gradle’s
    418 *dependency substitution* mechanism, for which there is first-class
    419 support in ``mozilla-central`` and a pattern throughout Mozilla’s
    420 GeckoView-consuming ecosystem.
    421 
    422 The good news is that ``mach build`` produces everything you need, so
    423 that after the configuration below, you should find that the following
    424 commands rebuild your local GeckoView and then consume your local
    425 version in the downstream project.
    426 
    427 .. code:: sh
    428 
    429   cd /path/to/mozilla-central && ./mach build
    430   cd /path/to/project && ./gradlew assembleDebug
    431 
    432 **Be sure that your ``mozconfig`` specifies the correct ``--target``
    433 argument for your target device.** Many projects use “ABI splitting” to
    434 include only the target device’s native code libraries in APKs deployed
    435 to the device. On x86-64 and aarch64 devices, this can result in
    436 GeckoView failing to find any libraries, because valid x86 and ARM
    437 libraries were not included in a deployed APK. Avoid this by setting
    438 ``--target`` to the exact ABI that your device supports.
    439 
    440 Dependency substituting your local GeckoView into a non-Mozilla project
    441 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    442 
    443 In projects that don’t have first-class support for dependency
    444 substitution already, you can do the substitution yourself. See the
    445 documentation in
    446 `substitue-local-geckoview.gradle <https://hg.mozilla.org/mozilla-central/file/tip/substitute-local-geckoview.gradle>`_,
    447 but roughly: in each Gradle project that consumes GeckoView, i.e., in
    448 each ``build.gradle`` with a
    449 ``dependencies { ... 'org.mozilla.geckoview:geckoview-...' }`` block,
    450 include lines like:
    451 
    452 .. code:: groovy
    453 
    454   ext.topsrcdir = "/path/to/mozilla-central"
    455   ext.topobjdir = "/path/to/object-directory" // Optional.
    456   apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
    457 
    458 **Remember to remove the lines from all ``build.gradle`` files when you
    459 want to return to using the published GeckoView builds!**
    460 
    461 Next Steps
    462 ----------
    463 
    464 -  Get started with `Native Debugging for Android <native-debugging.html>`_
    465 
    466 .. |alt text| image:: ../assets/DisableInstantRun.png
    467 .. |alt text 1| image:: ../assets/GeckoViewStructure.png