WebExtensions/Contribution Onramp: Difference between revisions

(Document linting)
 
(20 intermediate revisions by 3 users not shown)
Line 1: Line 1:
If this is your first contribution to the Firefox codebase, welcome! It can be scary to get started contributing to a large and complex codebase, but we’ve prepared some tips to help you fix a good-first-bug and land a patch in Firefox.  
If this is your first contribution to the Firefox codebase, welcome! It can be scary to get started contributing to a large and complex codebase, but we’ve prepared some tips to help you fix a good-first-bug and land a patch in Firefox.  


If we haven’t addressed your question in this document, please ask us by leaving a comment in the bug or by joining us on irc.mozilla.org in the #webextensions channel. For a general overview of how to contribute to Firefox, please [https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Introduction go here].
If we haven’t addressed your question in this document, please ask us by leaving a comment in the bug or by joining us on chat.mozilla.org in the #addons room (see [[Matrix]]). For a general overview of how to contribute to Firefox, please [https://firefox-source-docs.mozilla.org/contributing/contributing_to_mozilla.html go here].


== General Tips ==  
== General Tips ==  
* To make sure your comment in Bugzilla is seen, please “needinfo” the bug’s mentor by checking the box that says “Needs more information from” and then selecting “mentor” from the drop down box.  
* If you see a bug that looks interesting, please leave a comment saying that you would like to work on it, or upload your patch to phabricator and request review. Note: we will only assign the bug to you when a patch is uploaded.
* It's ok to ask questions in Bugzilla comments! It's best if you ask specific questions, like, "Can you help me find the line of code that needs changing," and not general questions like, "can you help me."
* It's normal to try things out and get stuck when you're working on your bug. When that happens, we encourage you to try a few different approaches before you ask for help. A good rule of thumb is to try to only needinfo your mentor once a day.
* It might take mentors a day or two to get back to you. If you haven't heard a response in more than two days, please feel free to ping them on chat.mozilla.org in the #addons room (see [[Matrix]]).


== Getting Started ==  
== Getting Started ==  
Line 10: Line 13:
* Pick a bug you want to work on from the [https://mzl.la/2yq1XA8 good-first-bugs list].  
* Pick a bug you want to work on from the [https://mzl.la/2yq1XA8 good-first-bugs list].  
* Comment on the bug that you would like to work on it and proceed to set up your developer environment.  
* Comment on the bug that you would like to work on it and proceed to set up your developer environment.  
* Run unit tests to verify that your environment works as expected, preferably tests related to the bug that you want to work on.


== Setting Up Developer Environment ==  
== Setting Up Developer Environment ==
* Now, you need to set up your development environment by [https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_build building Firefox].  There are two ways to do this:
** [recommended] Build Firefox using [https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Artifact_builds Firefox Artifact builds]. If the issue only requires changes to privileged JavaScript code, we recommend you use this method. Artifact builds saves time because it downloads a pre-built version of Firefox sources and applies your local changes on it, instead of rebuilding all of the C++ and Rust pieces from scratch.
** [https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_build Build Firefox from scratch]. Note: doing this can take some time. After the initial build, you can build Firefox using the “mach build” command.


* Next, use [https://searchfox.org Searchfox] to quickly find the code associated with your bug.
'''For a detailed overview, see [https://firefox-source-docs.mozilla.org/setup/index.html Getting Set Up To Work On The Firefox Codebase]'''.
 
In short:
* Now, you need to set up your development environment by [https://firefox-source-docs.mozilla.org/contributing/contribution_quickref.html#clone-the-sources cloning the source] with mercurial or [https://github.com/glandium/git-cinnabar/wiki/Mozilla:-A-git-workflow-for-Gecko-development with Git].
* Then you need to install dependencies with <code>mach bootstrap</code> for building Firefox.  There are two ways to do this:
** [recommended] Build Firefox using [https://firefox-source-docs.mozilla.org/contributing/build/artifact_builds.html Firefox Artifact builds]. If the issue only requires changes to privileged JavaScript code, we recommend you use this method. Artifact builds saves time because it downloads a pre-built version of Firefox sources and applies your local changes on it, instead of rebuilding all of the C++ and Rust pieces from scratch.
*** To build Firefox for Android, see the [https://firefox-source-docs.mozilla.org/mobile/android/geckoview/contributor/geckoview-quick-start.html GeckoView Contributor guide]. For a faster local development experience, we recommend to use the Artifact builds and the Android x86 target (which is especially useful to run the tests locally).
** [default] Build Firefox from scratch, by running <code>mach build</code> without [https://firefox-source-docs.mozilla.org/setup/configuring_build_options.html .mozconfig]. Note: doing this can take some time.
 
* Next, use [https://searchfox.org Searchfox] to find the code associated with your bug.
* Before making any changes, use <code>mach test [path to extension test]</code> to verify that you are able to run unit tests. Being able to run existing tests (and modified or new tests) is necessary, to see that your change works as expected.


==== WebExtensions APIs ====  
==== WebExtensions APIs ====  
You can learn more about how WebExtensions internals are organized and how to work on them by reading this [https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/index.html internal API documentation] and the [[WebExtensions/Hacking|WebExtensions Hacking wiki]].
You can learn more about how WebExtensions internals are organized and how to work on them by reading this [https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/index.html internal API documentation] and the [[WebExtensions/Hacking|WebExtensions Hacking wiki]].
== Fixing the Bug! ==
* You get to drive the actual bug fix. :)
* We encourage you to check in with the mentor to make sure you are on the right path, or ask for feedback on a patch in progress. You can attach your patch to a comment in Bugzilla and needinfo the mentor for review.


== Testing ==
== Testing ==
In order to land code in Firefox, you will need to create tests for your patches. For an overview of the different test systems Firefox uses, please see this [https://developer.mozilla.org/en-US/docs/Mozilla/QA/Automated_testing overview of automated testing]. In the WebExtension API code, most tests are either [https://developer.mozilla.org/en-US/docs/Mozilla/QA/Writing_xpcshell-based_unit_tests xpcshell tests] or [https://developer.mozilla.org/en-US/docs/Mozilla/Browser_chrome_tests browser chrome tests]. Xpcshell tests are preferred because of the lower overhead. Browser tests need to be written when a test interfaces with browser UI, such as tabs or context menus.
In order to land code in Firefox, you will need to create tests for your patches. For an overview of the different test systems Firefox uses, please see this [https://web.archive.org/web/20210308052053/https://developer.mozilla.org/en-US/docs/Mozilla/QA/Automated_testing overview of automated testing] (needs update - [https://bugzilla.mozilla.org/show_bug.cgi?id=1736870 bug 1736870]). In the WebExtension API code, most tests are either [https://firefox-source-docs.mozilla.org/testing/xpcshell/index.html xpcshell tests] or [https://firefox-source-docs.mozilla.org/testing/mochitest-plain/index.html (browser-chrome) mochitests]. Xpcshell tests are preferred because of the lower overhead. Browser tests need to be written when a test interfaces with browser UI, such as tabs or context menus.


The easiest way to get started with tests is to look at existing tests:
The easiest way to get started with tests is to look at existing tests:
Line 28: Line 43:
** toolkit/components/extensions/test/xpcshell/ ([https://searchfox.org/mozilla-central/source/toolkit/components/extensions/test/xpcshell Searchfox link])
** toolkit/components/extensions/test/xpcshell/ ([https://searchfox.org/mozilla-central/source/toolkit/components/extensions/test/xpcshell Searchfox link])
** browser/components/extensions/test/xpcshell/ ([https://searchfox.org/mozilla-central/source/browser/components/extensions/test/xpcshell Searchfox link])
** browser/components/extensions/test/xpcshell/ ([https://searchfox.org/mozilla-central/source/browser/components/extensions/test/xpcshell Searchfox link])
** mobile/android/components/extensions/test/xpcshell ([https://searchfox.org/mozilla-central/source/mobile/android/components/extensions/test/xpcshell Searchfox link])


* Browser-chrome tests:
* Browser-chrome tests:
Line 33: Line 49:
** browser/components/extensions/test/browser/ ([https://searchfox.org/mozilla-central/source/browser/components/extensions/test/browser Searchfox link])
** browser/components/extensions/test/browser/ ([https://searchfox.org/mozilla-central/source/browser/components/extensions/test/browser Searchfox link])


These tests can be run with the “mach test” command. To run a specific test, use “mach test [paths to test files or directories]”.
* Firefox for Android mochitests:
** mobile/android/components/extensions/test/mochitest ([https://searchfox.org/mozilla-central/source/mobile/android/components/extensions/test/mochitest Searchfox link])


=== Running tests ===
These tests can be run with the <code>mach test</code> command. To run specific test(s), pass the name of the test file or directory to <code>mach test</code>.
Sometimes <code>mach test</code> has bugs (e.g. [https://bugzilla.mozilla.org/show_bug.cgi?id=1498636 bug 1498636] and  [https://bugzilla.mozilla.org/show_bug.cgi?id=1495311 bug 1495311]); in that case use <code>mach xpcshell-test</code> or <code>mach mochitest</code> instead of <code>mach test</code> to run the test.
<code>mach test</code> has minimal output by default. To debug test failures, increase the verbosity of the logs with the <code>--verbose --log-mach-verbose</code> flags. The <code>--sequential</code> flag is not required, but allows for easier debugging because only one test is run at a time (instead of multiple in parallel). Al together, the command to run tests and get maximum debug output is:
<code>mach test --verbose --log-mach-verbose --sequential [paths to test files]</code>
=== Adding new tests ===
Add your test to an existing file when it is small and fits in that test. Otherwise, create a new test file, and register the test file in one of the .ini files in the same directory as your test, usually browser-common.ini or xpcshell-common.ini.
Add your test to an existing file when it is small and fits in that test. Otherwise, create a new test file, and register the test file in one of the .ini files in the same directory as your test, usually browser-common.ini or xpcshell-common.ini.
After creating a new test file, run <code>mach build</code> before running tests. It is not necessary to rebuild if you are changing an existing test file.


A test consists of multiple subtasks, which are defined in the test files via add_task(...).
A test consists of multiple subtasks, which are defined in the test files via add_task(...).
Most tests have the following minimal structure:
Most tests have the following minimal structure:


add_task(async function someShortAndSimpleDescriptionHere() {
<nowiki>add_task(async function someShortAndSimpleDescriptionHere() {
   // Define a test extension.
   // Define a test extension.
   let extension = ExtensionTestUtils.loadExtension( .... );
   let extension = ExtensionTestUtils.loadExtension( .... );
Line 52: Line 78:
   await extension.unload();
   await extension.unload();
});
});
</nowiki>


ExtensionTestUtils.loadExtension allows you to quickly generate a test extension, and its input parameters are documented at:
ExtensionTestUtils.loadExtension allows you to quickly generate a test extension, and its input parameters are documented at:
https://searchfox.org/mozilla-central/rev/ef8b3886cb173d5534b954b6fb7eb2d94a9473d0/toolkit/components/extensions/ExtensionTestCommon.jsm#185-212
https://searchfox.org/mozilla-central/rev/5f88c1d6977e03e22d3420d0cdf8ad0113c2eb31/toolkit/components/extensions/ExtensionTestCommon.jsm#387-411


Another common action in tests is to load a web page or extension page.
Another common action in tests is to load a web page or extension page.
Line 60: Line 87:


In browser-chrome tests, the BrowserTestUtils namespace provides many useful test helpers, such as BrowserTestUtils.openNewForegroundTab to open a new tab. BrowserTestUtils is implemented and documented at https://searchfox.org/mozilla-central/source/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
In browser-chrome tests, the BrowserTestUtils namespace provides many useful test helpers, such as BrowserTestUtils.openNewForegroundTab to open a new tab. BrowserTestUtils is implemented and documented at https://searchfox.org/mozilla-central/source/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
Running the tests (xpcshell tests and Firefox for Android mochitests) on the Android emulator requires some [https://wiki.mozilla.org/Mobile/Fennec/Android/Testing#Running_tests_on_the_Android_emulator additional setup of the local development environment].
=== Linting ===
Firefox source code have a consistent formatting and code style, which is enforced through [https://firefox-source-docs.mozilla.org/code-quality/lint/index.html linting]. Most extension code is written with JavaScript, which is linted via eslint. It is recommended to set up and run the linter locally (see [https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint.html eslint docs]). When a patch has been submitted to Phabricator, [https://firefox-source-docs.mozilla.org/code-quality/static-analysis/index.html static analysis] will run and report style errors upon completion (which may take a while to run). The Try Server also offers linting (ES for eslint, per [https://wiki.mozilla.org/WebExtensions/Try_Server WebExtensions/Try Server]).


== Submitting a Patch ==  
== Submitting a Patch ==  


For an overview of how to submit a patch, please see [https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/How_to_Submit_a_Patch this page on MDN].  
For an overview of how to submit a patch, please see [https://firefox-source-docs.mozilla.org/contributing/how_to_submit_a_patch.html How to submit a patch]. In short:


* Create a commit with a meaningful commit message, for example <code>Bug [bug ID here] - [short description of patch here] r=[reviewer name here]</code>.
** Use <code>hg com --amend</code> or <code>git commit --amend</code> to modify the last commit if you want to change the commit title or content.
** If you want to combine multiple commits into one:
*** With mercurial, use <code>hg histedit</code> or <code>hg rebase</code>. For more info, see [https://book.mercurial-scm.org/read/changing-history.html Mercurial - Changing history]
*** With git, use <code>git rebase -i</code>. For more info, see [https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History Git - Rewriting History].
* When you are ready to have your patch reviewed, submit your patch to [https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html Phabricator]:
* When you are ready to have your patch reviewed, submit your patch to [https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html Phabricator]:
** First, install the [https://phabricator.services.mozilla.com/book/phabricator/article/arcanist_quick_start/ arc tool].  
** First, [https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html#creating-an-account create an account] and install the [https://github.com/mozilla-conduit/review/blob/master/README.md#installation moz-phab tool].
** Then, use [https://moz-conduit.readthedocs.io/en/latest/arcanist-user.html these instructions] to submit the patch. Choose your mentor as the reviewer.
** Then [https://github.com/mozilla-conduit/review/blob/master/README.md#execution run moz-phab] to upload your commit. Each commit will become a separe patch, so combine them into one if needed.
** Note that you may go through a few iterations before your code is ready to go.  
** Note that you may go through a few iterations of changes and review before your code is ready to go.  
* When the patch is approved, add the keyword “checkin-needed” to the bug on Bugzilla. If you cannot add the keyword, please ask your mentor to add it for you.  
* If you need to make a change to a patch that has already been submitted to Phabricator, make sure you update the existing revision so the reviewers can check the interdiff and history of changes. <code>moz-phab</code> will automatically modify your commit [https://github.com/mozilla-conduit/review/blob/master/README.md#associating-a-commit-to-an-existing-phabricator-revision to add the relevant link].
* QA will verify your patch after it lands, unless your mentor has added a “qa-not-needed” keyword.  
* When working on unrelated changes at the same time, it is useful to work on them into separate hg bookmarks (or entire separate mozilla-central clones if you are not yet feeling confident enough with how the hg bookmarks works) or git branches.
* When the patch is approved, your mentor will use [https://lando.services.mozilla.com/ Lando] to land the patch.  
* Once your patch is accepted, you can expect to see your code in an upcoming version of Firefox!
* Once your patch is accepted, you can expect to see your code in an upcoming version of Firefox!
== Try server ==
To verify that the patch works as intended, your mentor may schedule a try job on the [[ReleaseEngineering/TryServer#Try_Server|Try Server]] to run tests. Contributors [[ReleaseEngineering/TryServer#Getting_access_to_the_Try_Server|with access to the try server]] can [[ReleaseEngineering/TryServer#How_to_push_to_try|push try jobs]] to run tests themselves.
See [[WebExtensions/Try_Server]] for more information about using the try server to test WebExtension code.

Latest revision as of 12:10, 10 May 2022

If this is your first contribution to the Firefox codebase, welcome! It can be scary to get started contributing to a large and complex codebase, but we’ve prepared some tips to help you fix a good-first-bug and land a patch in Firefox.

If we haven’t addressed your question in this document, please ask us by leaving a comment in the bug or by joining us on chat.mozilla.org in the #addons room (see Matrix). For a general overview of how to contribute to Firefox, please go here.

General Tips

  • If you see a bug that looks interesting, please leave a comment saying that you would like to work on it, or upload your patch to phabricator and request review. Note: we will only assign the bug to you when a patch is uploaded.
  • It's ok to ask questions in Bugzilla comments! It's best if you ask specific questions, like, "Can you help me find the line of code that needs changing," and not general questions like, "can you help me."
  • It's normal to try things out and get stuck when you're working on your bug. When that happens, we encourage you to try a few different approaches before you ask for help. A good rule of thumb is to try to only needinfo your mentor once a day.
  • It might take mentors a day or two to get back to you. If you haven't heard a response in more than two days, please feel free to ping them on chat.mozilla.org in the #addons room (see Matrix).

Getting Started

  • If you haven't already done so, create an account on https://bugzilla.mozilla.org.
  • Pick a bug you want to work on from the good-first-bugs list.
  • Comment on the bug that you would like to work on it and proceed to set up your developer environment.
  • Run unit tests to verify that your environment works as expected, preferably tests related to the bug that you want to work on.

Setting Up Developer Environment

For a detailed overview, see Getting Set Up To Work On The Firefox Codebase.

In short:

  • Now, you need to set up your development environment by cloning the source with mercurial or with Git.
  • Then you need to install dependencies with mach bootstrap for building Firefox. There are two ways to do this:
    • [recommended] Build Firefox using Firefox Artifact builds. If the issue only requires changes to privileged JavaScript code, we recommend you use this method. Artifact builds saves time because it downloads a pre-built version of Firefox sources and applies your local changes on it, instead of rebuilding all of the C++ and Rust pieces from scratch.
      • To build Firefox for Android, see the GeckoView Contributor guide. For a faster local development experience, we recommend to use the Artifact builds and the Android x86 target (which is especially useful to run the tests locally).
    • [default] Build Firefox from scratch, by running mach build without .mozconfig. Note: doing this can take some time.
  • Next, use Searchfox to find the code associated with your bug.
  • Before making any changes, use mach test [path to extension test] to verify that you are able to run unit tests. Being able to run existing tests (and modified or new tests) is necessary, to see that your change works as expected.

WebExtensions APIs

You can learn more about how WebExtensions internals are organized and how to work on them by reading this internal API documentation and the WebExtensions Hacking wiki.

Fixing the Bug!

  • You get to drive the actual bug fix. :)
  • We encourage you to check in with the mentor to make sure you are on the right path, or ask for feedback on a patch in progress. You can attach your patch to a comment in Bugzilla and needinfo the mentor for review.

Testing

In order to land code in Firefox, you will need to create tests for your patches. For an overview of the different test systems Firefox uses, please see this overview of automated testing (needs update - bug 1736870). In the WebExtension API code, most tests are either xpcshell tests or (browser-chrome) mochitests. Xpcshell tests are preferred because of the lower overhead. Browser tests need to be written when a test interfaces with browser UI, such as tabs or context menus.

The easiest way to get started with tests is to look at existing tests:

  • Browser-chrome tests:
  • Firefox for Android mochitests:

Running tests

These tests can be run with the mach test command. To run specific test(s), pass the name of the test file or directory to mach test. Sometimes mach test has bugs (e.g. bug 1498636 and bug 1495311); in that case use mach xpcshell-test or mach mochitest instead of mach test to run the test.

mach test has minimal output by default. To debug test failures, increase the verbosity of the logs with the --verbose --log-mach-verbose flags. The --sequential flag is not required, but allows for easier debugging because only one test is run at a time (instead of multiple in parallel). Al together, the command to run tests and get maximum debug output is: mach test --verbose --log-mach-verbose --sequential [paths to test files]

Adding new tests

Add your test to an existing file when it is small and fits in that test. Otherwise, create a new test file, and register the test file in one of the .ini files in the same directory as your test, usually browser-common.ini or xpcshell-common.ini. After creating a new test file, run mach build before running tests. It is not necessary to rebuild if you are changing an existing test file.

A test consists of multiple subtasks, which are defined in the test files via add_task(...). Most tests have the following minimal structure:

add_task(async function someShortAndSimpleDescriptionHere() {
  // Define a test extension.
  let extension = ExtensionTestUtils.loadExtension( .... );

  // Loads the actual extension.
  await extension.startup();

  // Tests here, often using extension.sendMessage and/or extension.awaitMessage

  // Unload the extension and remove the temporary files.
  await extension.unload();
});

ExtensionTestUtils.loadExtension allows you to quickly generate a test extension, and its input parameters are documented at: https://searchfox.org/mozilla-central/rev/5f88c1d6977e03e22d3420d0cdf8ad0113c2eb31/toolkit/components/extensions/ExtensionTestCommon.jsm#387-411

Another common action in tests is to load a web page or extension page. In xpcshell-tests, use ExtensionTestUtils.loadContentPage.

In browser-chrome tests, the BrowserTestUtils namespace provides many useful test helpers, such as BrowserTestUtils.openNewForegroundTab to open a new tab. BrowserTestUtils is implemented and documented at https://searchfox.org/mozilla-central/source/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm

Running the tests (xpcshell tests and Firefox for Android mochitests) on the Android emulator requires some additional setup of the local development environment.

Linting

Firefox source code have a consistent formatting and code style, which is enforced through linting. Most extension code is written with JavaScript, which is linted via eslint. It is recommended to set up and run the linter locally (see eslint docs). When a patch has been submitted to Phabricator, static analysis will run and report style errors upon completion (which may take a while to run). The Try Server also offers linting (ES for eslint, per WebExtensions/Try Server).

Submitting a Patch

For an overview of how to submit a patch, please see How to submit a patch. In short:

  • Create a commit with a meaningful commit message, for example Bug [bug ID here] - [short description of patch here] r=[reviewer name here].
    • Use hg com --amend or git commit --amend to modify the last commit if you want to change the commit title or content.
    • If you want to combine multiple commits into one:
  • When you are ready to have your patch reviewed, submit your patch to Phabricator:
    • First, create an account and install the moz-phab tool.
    • Then run moz-phab to upload your commit. Each commit will become a separe patch, so combine them into one if needed.
    • Note that you may go through a few iterations of changes and review before your code is ready to go.
  • If you need to make a change to a patch that has already been submitted to Phabricator, make sure you update the existing revision so the reviewers can check the interdiff and history of changes. moz-phab will automatically modify your commit to add the relevant link.
  • When working on unrelated changes at the same time, it is useful to work on them into separate hg bookmarks (or entire separate mozilla-central clones if you are not yet feeling confident enough with how the hg bookmarks works) or git branches.
  • When the patch is approved, your mentor will use Lando to land the patch.
  • Once your patch is accepted, you can expect to see your code in an upcoming version of Firefox!

Try server

To verify that the patch works as intended, your mentor may schedule a try job on the Try Server to run tests. Contributors with access to the try server can push try jobs to run tests themselves.

See WebExtensions/Try_Server for more information about using the try server to test WebExtension code.