Develop features for mozAddonManager
The AMO and Discovery Pane apps use the
mozAddonManager
web API to achieve a more seamless add-on installation user experience.
However, this API is only available to a limited list of domains.
If you go to https://addons.mozilla.org (production) in Firefox then mozAddonManager
is available on the page. If you go to a development site then it's not.
Turning on mozAddonManager for development
To access mozAddonManager
on a development site like
https://addons-dev.allizom.org or https://addons.allizom.org
go to about:config
in Firefox and set this property to true
:
extensions.webapi.testing
Refresh the page, open the JavaScript console, and you should see a global mozAddonManager
object.
Install add-ons for development
To fully install add-ons from a development site like
https://addons-dev.allizom.org or https://addons.allizom.org
you will need to tell Firefox to honor their signing certificates.
Go to about:config
in Firefox and set this property to true
:
xpinstall.signatures.dev-root
Restart Firefox to put it into effect. This pref allows you to fully install add-on and theme files.
Developing on Android
The presence of the mozAddonManager
API on Firefox for Android will activate
the add-on installation switch. Again, you will see this on
https://addons.mozilla.org (production) but not on a development site.
To activate access to this API on a development site, first
make sure you set the extensions.webapi.testing
preference to true
.
If you're testing on an Android device then you can now
access mozAddonManager
.
If you're testing on desktop Firefox to emulate Android (for development), you need to make sure your user agent looks like Firefox for Android. You can save a custom device in Responsive Design Mode with a Firefox for Android user agent string. Make sure it is touch enabled. This will let you see the add-on installation switch on desktop.
Developing with a local server
When you're running a server locally for development, you need to grant mozAddonManager
access to your localhost
domain in addition to setting the extensions.webapi.testing
preference to true
.
You can do this by building a version of Firefox with a custom patch.
Start by setting up your machine to build Firefox. That page gives you a link to a helpful bootstrapping script. Run it like this:
python bootstrap.py
It will ask you what version of Firefox you want to build. Choose:
Firefox for Desktop
Do not choose the artifact build because unfortunately you have to compile C++ code. It will prompt you to install some dependencies. Re-run it until you have everything installed and configured.
After you have everything, the bootstrap script prompts you to check out a clone of mozilla-central.
Change into the source directory and apply this patch to allow a local server
at a URL like localhost:3000
.
diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -711,16 +711,11 @@ var LightWeightThemeWebInstaller = {
let uri;
try {
uri = makeURI(srcURIString);
} catch (e) {
// makeURI fails if srcURIString is a nonsense URI
return false;
}
- if (!uri.schemeIs("https")) {
- return false;
- }
-
- let pm = Services.perms;
- return pm.testPermission(uri, "install") == pm.ALLOW_ACTION;
+ return true;
}
};
diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -64,16 +64,17 @@ var PREF_EM_CHECK_COMPATIBILITY = MOZ_CO
const VALID_TYPES_REGEXP = /^[\w\-]+$/;
const WEBAPI_INSTALL_HOSTS = ["addons.mozilla.org", "testpilot.firefox.com"];
const WEBAPI_TEST_INSTALL_HOSTS = [
"addons.allizom.org", "addons-dev.allizom.org",
"testpilot.stage.mozaws.net", "testpilot.dev.mozaws.net",
"example.com",
+ "localhost",
];
const URI_XPINSTALL_DIALOG = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
diff --git a/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp b/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp
--- a/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp
+++ b/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp
@@ -45,16 +45,17 @@ IsValidHost(const nsACString& host) {
// When testing allow access to the developer sites.
if (Preferences::GetBool("extensions.webapi.testing", false)) {
if (host.LowerCaseEqualsLiteral("addons.allizom.org") ||
host.LowerCaseEqualsLiteral("discovery.addons.allizom.org") ||
host.LowerCaseEqualsLiteral("addons-dev.allizom.org") ||
host.LowerCaseEqualsLiteral("discovery.addons-dev.allizom.org") ||
host.LowerCaseEqualsLiteral("testpilot.stage.mozaws.net") ||
host.LowerCaseEqualsLiteral("testpilot.dev.mozaws.net") ||
+ host.LowerCaseEqualsLiteral("localhost") ||
host.LowerCaseEqualsLiteral("example.com")) {
return true;
}
}
return false;
}
@@ -64,19 +65,16 @@ bool
AddonManagerWebAPI::IsValidSite(nsIURI* uri)
{
if (!uri) {
return false;
}
bool isSecure;
nsresult rv = uri->SchemeIs("https", &isSecure);
- if (NS_FAILED(rv) || !isSecure) {
- return false;
- }
nsAutoCString host;
rv = uri->GetHost(host);
if (NS_FAILED(rv)) {
return false;
}
return IsValidHost(host);
This patch will:
1. allow you to use an HTTP connection
2. allow any page at localhost
(on any port) to access mozAddonManager
and
perform some theme actions.
With this patch applied, you are ready to build Firefox. Once again, make sure you aren't configured for an artifact build since that won't work (you'll need to build C++ code). Build it!
./mach build
The first one will take a while but subsequent builds will be faster. Here's how to run it with a named profile so you don't lose your settings:
./mach run --profile mozilla-central
When Firefox starts up, go to about:config
to make sure the development
preference is set to true
:
extensions.webapi.testing
If you go to an add-on detail page on localhost:3000
with the proper Firefox
for Android user agent string (as explained above) then you should see a
fancy installation switch. It worked!
If it doesn't work, you may need to add some logging and re-build Firefox.
Try setting extensions.logging.enabled
to true
in about:config
to see
logging output for the AddonManager.jsm
code.
When you click the switch, it will only let you install add-ons if your
localhost is proxying https://addons-dev.allizom.org or https://addons.allizom.org .
This is because Firefox needs signing certificates and the certs are not configurable.
You can set the xpinstall.signatures.dev-root
preference to true
(as documented above) to activate certificates for the development sites.
Updating your Firefox source code
You will need to periodically update your Firefox source code and rebuild it with your patch.
First, set aside your patch by reverting the changes or using something like the shelve command:
hg shelve
Pull in new updates:
hg pull -u
Re-apply your patch with unshelve
(or by following the steps above):
hg unshelve
Now you are ready to build Firefox again. You can check the output of hg diff
to make sure the patch is still there and then kick off a new build:
./mach build