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