1880511
[gecko.git] / 
blob1880511b906f481a44799d8e414a524a6045f0ae
1 .. -*- Mode: rst; fill-column: 80; -*-
3 .. _geckoview-contributor-guide:
5 =================
6 Contributor Guide
7 =================
9 Table of contents
10 =================
12 .. contents:: :local:
14 GeckoView Contributor Quick Start Guide
15 =======================================
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>`_.
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.
30 The architecture, in broad strokes, looks like this:
32 Gecko <-> GeckoView <-> Android Components <-> Fenix or Focus or Reference Browser
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.
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.
41 Performing a bug fix
42 --------------------
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.
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-mc.html>`_ for you to follow. To contribute to
50 GeckoView specifically, you will need the following additional
51 information.
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>`_.
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.
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:
64 * **Java** - ``Log.i("Any Tag", "Any string " + variable.toString())``
66   * May be used for permanent logging in GeckoView, but should follow existing logging practices. Requires an import.
68   * Note, Android Components has different permanent logging practices.
70 * **JavaScript** - ``dump("Any string " + variable)``
72   * May not be used for permanent logging.
74   * May need to use ``JSON.stringify(variable)`` to deserialize objects in JavaScript.
76 * **JavaScript** - ``debug`Any String ${variable}```
78   * May be used for permanent logging, but should follow existing logging practices. Requires an import.
80   * Recommend ``dump`` for earlier debugging.
82 * **JavaScript** - ``console.log("Any String " + variable)``
84   * May be viewed using ``about:debugging`` on Desktop to a connected device and then connecting to the content process.
86 * **C++** - ``MOZ_LOG`` doesn't show up properly in logcat yet.
88   * Add this line ``CreateOrGetModule("modulename")->SetLevel(LogLevel::Verbose);`` `to this section of code <https://searchfox.org/mozilla-central/rev/1f46481d6c16f27c989e72b898fd1fddce9f445f/xpcom/base/Logging.cpp#416>`_ for a temporary solution to see ``MOZ_LOG`` logging.
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");``
92   * None of these may be used for permanent logging, only for debugging. Use ``MOZ_LOG`` for permanent logging.
94   * Variable logging will need to be converted to a C string or other supported logging string.
96   * Permanent logging for a GeckoView C++ file could be setup similar to:
98       ::
100           #define GVS_LOG(...) MOZ_LOG(sGVSupportLog, LogLevel::Info, (__VA_ARGS__))
101           static mozilla::LazyLogModule sGVSupportLog("Any Tag");
102           GVS_LOG("Any string");
104 Please be sure to remove any non-permanent debugging logs prior to requesting landing.
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.
108 Running tests and linter locally
109 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
116    ./mach geckoview-junit
118 This command also allows you to run individual tests or test classes,
119 e.g.
123    ./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
124    ./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
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 </devtools/tests/debugging-intermittents.html>`_ for additional tips.
132 Other tests, such as mochitests, may be ran using:
136    ./mach test <path-or-dir-to-test>
139 Core GeckoView lints are:
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
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.
154 If your patch makes a GeckoView JavaScript module, you should run ESLint:
158    ./mach lint -l eslint mobile/android/modules/geckoview/
160 If your patch makes a C++ file change, you should run the C++ linter formatter:
164    ./mach clang-format -p <path/to/file.cpp>
167 If your patch makes a Python file change:
171    ./mach lint --linter flake8
172    ./mach lint --linter black
175 Additionally, sometimes lints can be automatically detected and fixed on certain files, for example:
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>
184 Updating the changelog and API documentation
185 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
187 If the patch that you want to submit changes the public API for
188 GeckoView, you must ensure that the API documentation is kept up to
189 date.
191 GeckoView follows a deprecation policy you can learn more in this
192 `design doc <https://firefox-source-docs.mozilla.org/mobile/android/geckoview/design/breaking-changes.html>`_.
193 To deprecate an API, add the deprecation flags with an identifier for a
194 deprecation notice, so that all notices with the same identifier will
195 be removed at the same time (see below for an example). The version is the major version of when
196 we expect to remove the deprecated member attached to the annotation.
197 The GeckoView team instituted a deprecation policy which requires each
198 backward-incompatible change to keep the old code for 3 releases,
199 allowing downstream consumers, like Fenix, time to migrate asynchronously
200 to the new code without breaking the build.
204     @Deprecated
205     @DeprecationSchedule(id = "<interface_or_class_of_method>-<method_name>", version = <Current Nightly + 3>)
207 Since this is a public API, the changelog must also be updated. Please ensure that you
208 follow the correct format for changelog entries. Under the heading for
209 the next release version, add a new entry for the changes that you are
210 making to the API, along with links to any relevant files, and bug
211 number.
213 The format should be as follows:
217    - Summary of changes that should mention the method name, along with the respective class /
218      interface name, the major version and the index, and the bug ID, along with the
219      bugzilla link
221    [<major_version>.<index>]: {{javadoc_uri}}/<url_path>
223 For now, just update the changelog with the summary of changes made to the API (the first line in the example).
224 To determine the index, take the next index in the list of
225 ``[<major_version>.<index>]``. If no list is present, start with ``index = 1``.
228 - **Example for Adding a Method**
232    - Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
233      not `about:config` should be available.
234      ([bug 1540065]({{bugzilla}}1540065))
236    [71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled(boolean)
239 - **Example for Deprecating a Method**
243    - ⚠️ Deprecated [`GeckoSession.ContentDelegate.onProductUrl`][128.5], will now be removed in v131.
244    ([bug 1898055]({{bugzilla}}1898055))
246    [128.5]: {{javadoc_uri}}/GeckoSession.ContentDelegate.html#onProductUrl(org.mozilla.geckoview.GeckoSession)
248 To check whether your patch has altered the API, run the following
249 command:
251 .. code:: bash
253    ./mach lint --linter android-api-lint
255 The output of this command will inform you if any changes you have made
256 break the existing API. The first run of the command will tell you if there are API changes.
257 Review the changes and follow the instructions it provides, if there are changes and they are
258 expected.
260 .. code:: bash
262     ./mach gradle geckoview:apiLintWithGeckoBinariesDebug
264 Running the above command should cause the build to fail and the output should contain an API key,
265 which should be used to update the ``[api-version]`` field in the changelog. Next, run the command
266 again:
268 .. code:: bash
270     ./mach gradle geckoview:apiLintWithGeckoBinariesDebug
272 The build should pass this time, and an api.txt file will be generated for the changes. Next, follow
273 the next command to double check that the changes made do not break the existing API:
275 .. code:: bash
277     ./mach lint --linter android-api-lint
279 If an API is deprecated, file a follow-up bug or leave the bug open by
280 adding the keyword `leave-open` to remove and clean up the deprecated
281 API for the version it is to be removed on. Also, ensure that running the previous two commands
282 has changed the javadoc of the deprecated method to indicate that the method has been scheduled
283 for deprecation. If not, ensure to do this manually.
285 A special situation is when a patch changing the API may need to be uplifted to an earlier
286 branch of mozilla-central, for example, to the beta channel. To do this, follow the usual uplift
287 steps and make a version of the patch for uplift that is graphed onto the new target branch and
288 rerun the API linter commands.
290 Next, we will create the JavaDoc locally:
292 Creating JavaDoc Locally
293 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
294 .. note::
295     Make sure that the API version is updated in the changelog and that the summary of changes
296     made to the API in the changelog are made correctly. Otherwise, this step won't work.
298 GeckoView is a public API, so well maintained javadoc is an important practice. To create the
299 javadoc locally, we use the following command, which should have already been done above:
301 .. code:: bash
303    ./mach gradle geckoview:javadocWithGeckoBinariesDebug
306 To view the javadoc locally, choose one of the two options:
308 - Navigate to
309   ``<mozilla-central root>/<build architecture>/gradle/build/mobile/android/geckoview/docs/javadoc/withGeckoBinaries-debug``
311 - In your ``mozilla-unified`` directory, type the following command:
313   .. code:: bash
315      find . -name withGeckoBinaries-debug
317   This should return the relative path of the local javadoc.
319   As an example, the output could be this:
321   .. code:: bash
323       mozilla-unified/objdir-frontend/gradle/build/mobile/android/geckoview/docs/javadoc/withGeckoBinaries-debug
325   Then, use the following command to go into the directory of the local javadoc:
327   .. code:: bash
329      cd <path_of_javadoc_from_above>
331 Now, we want to launch a local web server. To launch locally, use any web server, for example:
333 .. code:: bash
335    python3 -m http.server 8000
338 In this example, navigate to the web docs via ``http://localhost:8000/org/mozilla/geckoview/``.
340 .. note::
341     If you get a 404 error, please ensure that you have navigated to the correct directory and try
342     launching the web server again.
344 Then, look for the changed method in the list displayed on the webpage and click into it.
346 In the changelog, under the list of summaries for the major version, there should be a list of
347 URLs for the changed methods. Add a new entry for the next index (keeping the major version
348 the same). Then, in the local web server, copy everything after ``.../org/mozilla/geckoview/``.
349 Fill in the entry by doing ``{{javadoc_uri}}/<paste_the_copied_text>``. See the example above
350 for reference.
352 Submitting to the ``try`` server
353 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
355 It is advisable to run your tests before submitting your patch. You can
356 do this using Mozilla’s ``try`` server. To submit a GeckoView patch to
357 ``try`` before submitting it for review, type:
359 .. code:: bash
361    ./mach try --preset android-geckoview
363 This will automatically run critical tests from the GeckoView test suite. If your patch
364 passes on ``try`` you can be (fairly) confident that it will land successfully
365 after review.
367 Failures on ``try`` will show up with the test name highlighted in orange. Select the test to find out more.
368 Intermittent failures occasionally occur due to issues with the test harness. Retriggering the test is a good way
369 to confirm it is an intermittent failure and not due to the patch. Usually there will also be a bug number with
370 a portion of the stack trace as well for documented intermittent failures.
371 See `Intermittent Test Failures </devtools/tests/debugging-intermittents.html>`_ for more information.
373 To debug failures on try, it is always a good idea to check the logcat. To do this, select the individual test,
374 select "Artifacts and Debugging" and then open the log from "logcat-emulator-5554.log".
376 Tagging a reviewer
377 ~~~~~~~~~~~~~~~~~~
379 When submitting a patch to Phabricator, if you know who you want to
380 review your patch, put their Phabricator handle against the
381 ``reviewers`` field.
383 If you don’t know who to tag for a review in the Phabricator submission
384 message, leave the field blank and, after submission, follow the link to
385 the patch in Phabricator and scroll to the bottom of the screen until
386 you see the comment box.
388 - Select the ``Add Action`` drop down and pick the ``Change Reviewers`` option.
389 - 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.
390 - Click ``Submit`` to submit the reviewer change request.
393 GeckoView, Android Components, Fenix, Focus, and Reference Browser Dependency Substitution
394 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
395 Internal product dependency substitution is handled automatically in mozilla-central on full builds. When building, the substitution
396 into these other products will happen automatically after `./mach build` is ran. However, in artifact builds, changes in
397 Gecko or GeckoView will not consistently be reflected. If making changes to Gecko or GeckoView, it is **strongly** recommended
398 to only use full builds as changes in Gecko or GeckoView may not be reflected when using artifact builds.
400 Include GeckoView as a dependency
401 ---------------------------------
403 If you want to include a development version of GeckoView as a
404 dependency inside another app, you must link to a local copy. There are
405 several ways to achieve this, but the preferred way is to use Gradle’s
406 *dependency substitution* mechanism, for which there is first-class
407 support in ``mozilla-central`` and a pattern throughout Mozilla’s
408 GeckoView-consuming ecosystem.
410 The good news is that ``mach build`` produces everything you need, so
411 that after the configuration below, you should find that the following
412 commands rebuild your local GeckoView and then consume your local
413 version in the downstream project.
415 .. code:: sh
417    cd /path/to/mozilla-central && ./mach build
418    cd /path/to/project && ./gradlew assembleDebug
420 **Be sure that your ``mozconfig`` specifies the correct ``--target``
421 argument for your target device.** Many projects use “ABI splitting” to
422 include only the target device’s native code libraries in APKs deployed
423 to the device. On x86-64 and aarch64 devices, this can result in
424 GeckoView failing to find any libraries, because valid x86 and ARM
425 libraries were not included in a deployed APK. Avoid this by setting
426 ``--target`` to the exact ABI that your device supports.
428 Dependency substituting your local GeckoView into a non-Mozilla project
429 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
431 In projects that don’t have first-class support for dependency
432 substitution already, you can do the substitution yourself. See the
433 documentation in
434 `substitue-local-geckoview.gradle <https://hg.mozilla.org/mozilla-central/file/tip/substitute-local-geckoview.gradle>`_,
435 but roughly: in each Gradle project that consumes GeckoView, i.e., in
436 each ``build.gradle`` with a
437 ``dependencies { ... 'org.mozilla.geckoview:geckoview-...' }`` block,
438 include lines like:
440 .. code:: groovy
442    ext.topsrcdir = "/path/to/mozilla-central"
443    ext.topobjdir = "/path/to/object-directory" // Optional.
444    apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
446 **Remember to remove the lines from all ``build.gradle`` files when you
447 want to return to using the published GeckoView builds!**
449 Next Steps
450 ----------
452 -  Get started with `Native Debugging for Android <native-debugging.html>`_
454 .. |alt text| image:: ../assets/DisableInstantRun.png
455 .. |alt text 1| image:: ../assets/GeckoViewStructure.png