When submitting an add-on to addons.mozilla.org (AMO), it is sometimes necessary to attach source code in addition to the xpi file. This usually applies to add-ons with obfuscated code, because a reviewer wouldn’t be able to approve an add-on without reviewing what was obfuscated. Since these types of add-ons are more complex to review, I’ve written some tips on what you can do to help them get through the queue faster.
When to attach sources
When the add-on xpi file you upload to addons.mozilla.org (AMO) contains code that is not completely readable by a human, it is probably a good idea to attach sources.
For example, if you used tools like uglifyJS, Google Closure Compiler, browserify or a custom pre-processor, you will have to upload sources. The same goes if you are using js-ctypes or including other binary components.
There are also a few cases where it is actually NOT required and in fact not recommended. If your library only contains third-party minified libraries (like jQuery or Angular), or if the libraries you are calling via js-ctypes are system libraries or open source, please do not upload sources. Instead, provide links to the repositories of the respective libraries.
What happens during reviews
When you attach sources, the add-on is marked for “admin-review”. This means that your sources and are only accessible to a small group of admins. We do this to protect your sources.
A very important aspect of reviewing sources is reproducing the obfuscation. As we need to treat every extension developer the same, we must verify that the source code we reviewed matches the uploaded xpi. If we skip this step, a malware author could provide us with legitimate-looking sources and add a backdoor to the previously minified xpi file.
Here are the steps we take:
- Download the sources and extract them.
- Run <magic steps>, including minifiers, obfuscators, compilers, or code generators.
- Take the output directory from the previous step and compare it with the add-on xpi that has been uploaded.
- Review the source code files as we would review any other add-on that does not have sources.
In step 3, we use a diff tool to compare the generated sources to the add-on xpi file. There must be no differences at all. To save time, it is very important to provide us with all the <magic steps>. If you don’t add this, we will have to get in touch with you, and that adds time to the review process.
Providing instructions
The easiest way for you to provide the magic steps is to include a README
file in the uploaded sources. If it is just one or two files that are obfuscated, the instructions can be something like “run uglifyjs data/mycoolstuff.js”. If the extension is any more complex, please provide a script that we can run that takes care of everything at once. Things you should mention in your README
include:
- Prerequisites that need to be downloaded separately, for example yuicompressor.
- For less popular or custom-written build tools, provide links where they can be downloaded, as well as installation steps.
- If a specific version of supplemental software needs to be used, please let us know. But avoid doing so if the latest version would work just as well.
- All commands we should run to go from sources to a generated xpi file that matches the one you’ve uploaded, for example
npm install
or a grunt target.
Please assume the reviewer has a vanilla operating system set up. You don’t need to describe how to install common tools including npm, node, the add-on SDK, but please make sure the reviewer can figure out how to install everything needed to generate the xpi file.
Aside from the README
file, you also need to package everything required to build. If your add-on depends on a private repository or frameworks not commonly available, please include them as well.
Desired outcome
Common build tools used are make, grunt, gulp and ant. If you don’t already have a build target that runs the above steps, please add a target that does so. For example, allow us to run grunt firefox-dist
to create the generated xpi. Here is an example of what the sources could look like. The dist
directory is initially empty, until your build script (in this case grunt) generates the directory contents. You could then zip them up and upload them to AMO.
sources ├── README.md ├── Gruntfile.js ├── package.json ├──────────────────────────────── dist │ ├── bootstrap.js │ ├── install.rdf │ ├── package.json ├── data ├── data │ ├── js │ ├── js │ │ ├── dialog.js │ │ ├── dialog.min.js │ │ └── popup.js │ │ └── popup.min.js │ ├── scss │ ├── css │ │ ├── popup.scss │ │ ├── popup.css │ │ ├── dialog.scss │ │ └── dialog.scss │ │ └── common.scss │ │ │ ├── html │ ├── html │ │ ├── dialog.html │ │ ├── dialog.html │ │ └── popup.html │ │ └── popup.html │ ├── vendor │ ├── vendor │ │ └── jquery-2.1.4.min.js │ │ └── jquery-2.1.4.min.js │ └── images │ └── images │ └── logo.png │ └── logo.png ├── lib ├── lib │ └── main.js │ └── main.js └── locale └── locale └── en-US.properties └── en-US.properties
A few more tips
If you can avoid obfuscating or minifying code, your review can be done by any reviewer. Should you still need to attach sources, make sure you provide clear instructions so that our admin reviewers can handle your add-on quickly. Responding to questions quickly and using well-known obfuscation tools also improve review time.
Some last words
While our reviewers, both volunteer and staff, review add-ons around the clock, there may be times when it just takes longer. This can be due to anything from Firefox releases and major product changes, to holiday seasons.
I hope you’ve found this post helpful. There’s a lot to remember, but after you’ve done this once or twice you should get the hang of it. If you’d like a page to bookmark that contains this information and some more details on the topic, please head over to our new article on MDN.
If you also have tips to share, or questions on this topic, please post in our forums. Also, if you ever want to sit with developers on the other side of the table, perhaps consider applying to become an add-on reviewer?
Peter wrote on
Philipp Kewisch wrote on
Noitidart wrote on
Ben Basson wrote on