47
edits
(Add some more skeleton code layout docs) |
(Add link to WebExtension-specific Try server article) |
||
| (15 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
The core WebExtension code lives in the same repository as the Firefox browser. If you've never hacked on Firefox before, there is a [http://areweeveryoneyet.org/onramp/desktop.html quick guide to getting started], which will show you how to check out the code and do your first build. | |||
== Code Style == | == Code Style == | ||
| Line 19: | Line 20: | ||
ESLint will enforce most of these rules. | ESLint will enforce most of these rules. | ||
== Code Guidelines == | |||
For Chrome APIs we'll support the callback interface to maintain compatibility. For new APIs, not Chrome ones, we'll use the promise interface to all APIs. See the [https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API#Callbacks_and_promises MDN docs] for the difference. | |||
== Checking your code with ESLint == | == Checking your code with ESLint == | ||
| Line 24: | Line 29: | ||
All WebExtension directories in <code>mozilla-central</code> are configured with a set of ESLint rules, which all code is required to pass. Many of these rules help to catch serious errors, such as references to non-existent variables, or a missing trailing comma turning an array literal into an array dereference, so it is extremely important that you check you code against them before it lands. | All WebExtension directories in <code>mozilla-central</code> are configured with a set of ESLint rules, which all code is required to pass. Many of these rules help to catch serious errors, such as references to non-existent variables, or a missing trailing comma turning an array literal into an array dereference, so it is extremely important that you check you code against them before it lands. | ||
The simplest way to check your code is using the <code>mach eslint</code> command. This requires that you have [https://docs.npmjs.com/ NPM] installed | The simplest way to check your code is using the <code>mach eslint</code> command. This requires that you have [https://docs.npmjs.com/ NPM] installed. | ||
To setup ESLint, you need to run the following once: | To setup ESLint, you need to run the following once: | ||
| Line 52: | Line 57: | ||
The following assumes that you use the [https://github.com/VundleVim/Vundle.vim Vundle package manager]. It should be easy enough to adapt to any other package manager you happen to prefer, though. | The following assumes that you use the [https://github.com/VundleVim/Vundle.vim Vundle package manager]. It should be easy enough to adapt to any other package manager you happen to prefer, though. | ||
You should configure Syntastic roughly as follows: | <code>mach eslint --setup</code> installs a specific ESLint version and some ESLint plugins to a subdirectory of the repository ([https://bugzilla.mozilla.org/show_bug.cgi?id=1305023 changed in Firefox 55]). | ||
You should configure Syntastic roughly as follows (change <code>/path/to/mozilla-central</code> as needed): | |||
" Initialize Vundle. | " Initialize Vundle. | ||
| Line 61: | Line 67: | ||
Bundle 'scrooloose/syntastic' | Bundle 'scrooloose/syntastic' | ||
" Enable ESLint in | " Enable the specific ESLint checker for files in mozilla-central/ only. | ||
" Enable the HTML plugin, and enable JavaScript linting for HTML files. | " Enable the HTML plugin, and enable JavaScript linting for HTML files. | ||
let | autocmd FileType javascript,html | ||
\ if stridx(expand("%:p"), "/mozilla-central/") != -1 | | |||
\ let b:syntastic_checkers = ['eslint'] | | |||
\ let b:syntastic_eslint_exec = '/path/to/mozilla-central/node_modules/.bin/eslint' | | |||
\ let b:syntastic_html_eslint_args = ['--plugin', 'html'] | | |||
\ endif | |||
After you've added this to your configuration (and have installed Vundle, if necessary), launch Vim and run: | After you've added this to your configuration (and have installed Vundle, if necessary), launch Vim and run: | ||
| Line 99: | Line 107: | ||
;xpcshell tests | ;xpcshell tests | ||
: These reside under <code>toolkit/components/extensions/test/xpcshell/</code>, and are used to test low-level modules which do not require a browser UI, including those under <code>toolkit/modules/addons/</code>, <code>toolkit/components/utils/simpleServices.js</code>, and various pieces of C++ code. | : These reside under <code>toolkit/components/extensions/test/xpcshell/</code>, and are used to test low-level modules which do not require a browser UI, including those under <code>toolkit/modules/addons/</code>, <code>toolkit/components/utils/simpleServices.js</code>, and various pieces of C++ code. | ||
[[WebExtensions/Try_Server]] has more information about using the try server to test WebExtension code. | |||
=== Test tag === | |||
All tests in WebExtensions are [https://bugzilla.mozilla.org/show_bug.cgi?id=1296888 now tagged] with the tag: <code>webextensions</code>, so you can pass the <code>--tag</code> argument to <code>mochitest</code>, <code>xpcshell-test</code> and the [http://trychooser.pub.build.mozilla.org/ try server syntax]. | |||
=== Code coverage tests === | === Code coverage tests === | ||
| Line 113: | Line 127: | ||
: This is code coverage for code run in a tab content process, excluding code run only in the main browser process. | : This is code coverage for code run in a tab content process, excluding code run only in the main browser process. | ||
In general, the total code coverage numbers are what we focus on. However, it is extremely important code which is expected to run in both the main browser process and in a content process to be tested in both. If you know that your code falls into this category, please check that it's tested appropriately. | In general, the total code coverage numbers are what we focus on. However, it is extremely important for code which is expected to run in both the main browser process and in a content process to be tested in both. If you know that your code falls into this category, please check that it's tested appropriately. | ||
The above results are generated using [https://people.mozilla.org/~kmaglione/webext-coverage.patch this patch], which could generously be described as a fairly gross hack. If you'd like to run the tests yourself, you can do so with something like the following: | The above results are generated using [https://people.mozilla.org/~kmaglione/webext-coverage.patch this patch], which could generously be described as a fairly gross hack. If you'd like to run the tests yourself, you can do so with something like the following: | ||
# Install the | # Install the Istanbul code coverage tool | ||
npm install istanbul | npm install -g istanbul | ||
# Apply the code coverage patch | # Apply the code coverage patch | ||
| Line 125: | Line 139: | ||
# Instrument all WebExtension code, run the various test suites, and | # Instrument all WebExtension code, run the various test suites, and | ||
# generate the coverage output files. | # generate the coverage output files. | ||
./toolkit/components/extensions/test_coverage.sh | |||
./toolkit/components/extensions/test_coverage.sh | |||
== Code layout == | == Code layout == | ||
| Line 159: | Line 172: | ||
Each API module must be explicitly registered, in order to be loaded. It must also register a schema if it exports any APIs to extensions. | Each API module must be explicitly registered, in order to be loaded. It must also register a schema if it exports any APIs to extensions. | ||
Generic APIs | Starting from Firefox 50 ([https://bugzilla.mozilla.org/1285063 Bug 1285063], [https://hg.mozilla.org/mozilla-central/rev/e9ca8dc4b42e hg commit e9ca8dc4b42e]) all the APIs schema and <code>ext-*.js</code> files must be registered to the category manager through one of the following manifest files: | ||
* [https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/extensions-toolkit.manifest toolkit/components/extensions/extensions-toolkit.manifest], for Generic APIs registered at toolkit level | |||
* [https://dxr.mozilla.org/mozilla-central/source/browser/components/extensions/extensions-browser.manifest browser/components/extensions/extensions-browser.manifest], for Firefox desktop APIs | |||
* [https://dxr.mozilla.org/mozilla-central/source/mobile/android/components/extensions/extensions-mobile.manifest mobile/android/components/extensions/extensions-mobile.manifest], for Firefox for Android APIs | |||
As an example, here is a snippet of the <code>extension-toolkit.manifest</code>: | |||
# scripts | |||
category webextension-scripts alarms chrome://extensions/content/ext-alarms.js | |||
... | |||
# schemas | |||
category webextension-schemas alarms chrome://extensions/content/schemas/alarms.json | |||
In previous Firefox versions, schemas and <code>ext-*.js</code> files were statically | |||
registered through <code>Extension.jsm</code> and <code>nsBrowserGlue.js</code> source | |||
files: | |||
Generic APIs were registered in <code>Extension.jsm</code> as follows: | |||
ExtensionManagement.registerScript("chrome://extensions/content/ext-foobar.js"); | ExtensionManagement.registerScript("chrome://extensions/content/ext-foobar.js"); | ||
| Line 165: | Line 197: | ||
ExtensionManagement.registerSchema("chrome://extensions/content/schemas/foobar.json"); | ExtensionManagement.registerSchema("chrome://extensions/content/schemas/foobar.json"); | ||
Firefox desktop APIs | Firefox desktop APIs were registered in [https://dxr.mozilla.org/mozilla-central/source/browser/components/nsBrowserGlue.js nsBrowserGlue.js]: | ||
ExtensionManagement.registerScript("chrome://browser/content/ext-bazquux.js"); | ExtensionManagement.registerScript("chrome://browser/content/ext-bazquux.js"); | ||
ExtensionManagement.registerSchema("chrome://browser/content/schemas/bazquux.json"); | ExtensionManagement.registerSchema("chrome://browser/content/schemas/bazquux.json"); | ||
=== Permission strings === | |||
The strings for permissions can be found in [https://dxr.mozilla.org/mozilla-central/source/browser/locales/en-US/chrome/browser/browser.properties browser.properties]. | |||
If you add an API that requires permissions, then you'll need to make sure the corresponding permission strings are also landed. | |||
edits