diff --git a/browser/extensions/formautofill/FormAutofillStorage.jsm b/browser/extensions/formautofill/FormAutofillStorage.jsm
index 29646bb19ca3..7ac5e68c54f4 100644
--- a/browser/extensions/formautofill/FormAutofillStorage.jsm
+++ b/browser/extensions/formautofill/FormAutofillStorage.jsm
@@ -1790,6 +1790,10 @@ FormAutofillStorage.prototype = {
_saveImmediately() {
return this._store._save();
},
+
+ _finalize() {
+ return this._store.finalize();
+ },
};
// The singleton exposed by this module.
diff --git a/browser/extensions/formautofill/api.js b/browser/extensions/formautofill/api.js
new file mode 100644
index 000000000000..9c6e621d0c70
--- /dev/null
+++ b/browser/extensions/formautofill/api.js
@@ -0,0 +1,145 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/* globals ExtensionAPI */
+
+const STYLESHEET_URI = "chrome://formautofill/content/formautofill.css";
+const CACHED_STYLESHEETS = new WeakMap();
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+ChromeUtils.defineModuleGetter(this, "FormAutofill",
+ "resource://formautofill/FormAutofill.jsm");
+ChromeUtils.defineModuleGetter(this, "formAutofillParent",
+ "resource://formautofill/FormAutofillParent.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "resProto",
+ "@mozilla.org/network/protocol;1?name=resource",
+ "nsISubstitutingProtocolHandler");
+
+const RESOURCE_HOST = "formautofill";
+
+function insertStyleSheet(domWindow, url) {
+ let doc = domWindow.document;
+ let styleSheetAttr = `href="${url}" type="text/css"`;
+ let styleSheet = doc.createProcessingInstruction("xml-stylesheet", styleSheetAttr);
+
+ doc.insertBefore(styleSheet, doc.documentElement);
+
+ if (CACHED_STYLESHEETS.has(domWindow)) {
+ CACHED_STYLESHEETS.get(domWindow).push(styleSheet);
+ } else {
+ CACHED_STYLESHEETS.set(domWindow, [styleSheet]);
+ }
+}
+
+function onMaybeOpenPopup(evt) {
+ let domWindow = evt.target.ownerGlobal;
+ if (CACHED_STYLESHEETS.has(domWindow)) {
+ // This window already has autofill stylesheets.
+ return;
+ }
+
+ insertStyleSheet(domWindow, STYLESHEET_URI);
+}
+
+function isAvailable() {
+ let availablePref = Services.prefs.getCharPref("extensions.formautofill.available");
+ if (availablePref == "on") {
+ return true;
+ } else if (availablePref == "detect") {
+ let locale = Services.locale.getRequestedLocale();
+ let region = Services.prefs.getCharPref("browser.search.region", "");
+ let supportedCountries = Services.prefs.getCharPref("extensions.formautofill.supportedCountries")
+ .split(",");
+ if (!Services.prefs.getBoolPref("extensions.formautofill.supportRTL") &&
+ Services.locale.isAppLocaleRTL) {
+ return false;
+ }
+ return locale == "en-US" && supportedCountries.includes(region);
+ }
+ return false;
+}
+
+this.formautofill = class extends ExtensionAPI {
+ onStartup() {
+ // We have to do this before actually determining if we're enabled, since
+ // there are scripts inside of the core browser code that depend on the
+ // FormAutofill JSMs being registered.
+ let uri = Services.io.newURI("chrome/res/", null, this.extension.rootURI);
+ resProto.setSubstitution(RESOURCE_HOST, uri);
+
+ let aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"]
+ .getService(Ci.amIAddonManagerStartup);
+ const manifestURI = Services.io.newURI("manifest.json", null, this.extension.rootURI);
+ this.chromeHandle = aomStartup.registerChrome(manifestURI, [
+ ["content", "formautofill", "chrome/content/"],
+ ["locale", "formautofill", "en-US", "en-US/locale/en-US/"],
+ ]);
+
+ if (!isAvailable()) {
+ Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
+ // reset the sync related prefs incase the feature was previously available
+ // but isn't now.
+ Services.prefs.clearUserPref("services.sync.engine.addresses.available");
+ Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
+ Services.telemetry.scalarSet("formautofill.availability", false);
+ return;
+ }
+
+ // This pref is used for web contents to detect the autocomplete feature.
+ // When it's true, "element.autocomplete" will return tokens we currently
+ // support -- otherwise it'll return an empty string.
+ Services.prefs.setBoolPref("dom.forms.autocomplete.formautofill", true);
+ Services.telemetry.scalarSet("formautofill.availability", true);
+
+ // This pref determines whether the "addresses"/"creditcards" sync engine is
+ // available (ie, whether it is shown in any UI etc) - it *does not* determine
+ // whether the engine is actually enabled or not.
+ Services.prefs.setBoolPref("services.sync.engine.addresses.available", true);
+ if (FormAutofill.isAutofillCreditCardsAvailable) {
+ Services.prefs.setBoolPref("services.sync.engine.creditcards.available", true);
+ } else {
+ Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
+ }
+
+ // Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
+ Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
+
+ formAutofillParent.init().catch(Cu.reportError);
+ /* eslint-disable no-unused-vars */
+ Services.ppmm.loadProcessScript("data:,new " + function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
+ }, true);
+ /* eslint-enable no-unused-vars */
+ Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true, true);
+ }
+
+ onShutdown() {
+ resProto.setSubstitution(RESOURCE_HOST, null);
+
+ this.chromeHandle.destruct();
+ this.chromeHandle = null;
+
+ Services.mm.removeMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
+
+ let enumerator = Services.wm.getEnumerator("navigator:browser");
+ while (enumerator.hasMoreElements()) {
+ let win = enumerator.getNext();
+ let domWindow = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+ let cachedStyleSheets = CACHED_STYLESHEETS.get(domWindow);
+
+ if (!cachedStyleSheets) {
+ continue;
+ }
+
+ while (cachedStyleSheets.length !== 0) {
+ cachedStyleSheets.pop().remove();
+ }
+ }
+ }
+};
diff --git a/browser/extensions/formautofill/background.js b/browser/extensions/formautofill/background.js
new file mode 100644
index 000000000000..efe296ff2278
--- /dev/null
+++ b/browser/extensions/formautofill/background.js
@@ -0,0 +1,8 @@
+/* eslint-env webextensions */
+
+"use strict";
+
+browser.runtime.onUpdateAvailable.addListener(details => {
+ // By listening to but ignoring this event, any updates will
+ // be delayed until the next browser restart.
+});
diff --git a/browser/extensions/formautofill/bootstrap.js b/browser/extensions/formautofill/bootstrap.js
deleted file mode 100644
index 45c0165049e4..000000000000
--- a/browser/extensions/formautofill/bootstrap.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/* exported startup, shutdown, install, uninstall */
-
-const STYLESHEET_URI = "chrome://formautofill/content/formautofill.css";
-const CACHED_STYLESHEETS = new WeakMap();
-
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-ChromeUtils.defineModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
-ChromeUtils.defineModuleGetter(this, "AddonManagerPrivate",
- "resource://gre/modules/AddonManager.jsm");
-ChromeUtils.defineModuleGetter(this, "FormAutofill",
- "resource://formautofill/FormAutofill.jsm");
-ChromeUtils.defineModuleGetter(this, "formAutofillParent",
- "resource://formautofill/FormAutofillParent.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "resProto",
- "@mozilla.org/network/protocol;1?name=resource",
- "nsISubstitutingProtocolHandler");
-
-const RESOURCE_HOST = "formautofill";
-
-function insertStyleSheet(domWindow, url) {
- let doc = domWindow.document;
- let styleSheetAttr = `href="${url}" type="text/css"`;
- let styleSheet = doc.createProcessingInstruction("xml-stylesheet", styleSheetAttr);
-
- doc.insertBefore(styleSheet, doc.documentElement);
-
- if (CACHED_STYLESHEETS.has(domWindow)) {
- CACHED_STYLESHEETS.get(domWindow).push(styleSheet);
- } else {
- CACHED_STYLESHEETS.set(domWindow, [styleSheet]);
- }
-}
-
-function onMaybeOpenPopup(evt) {
- let domWindow = evt.target.ownerGlobal;
- if (CACHED_STYLESHEETS.has(domWindow)) {
- // This window already has autofill stylesheets.
- return;
- }
-
- insertStyleSheet(domWindow, STYLESHEET_URI);
-}
-
-function addUpgradeListener(instanceID) {
- AddonManager.addUpgradeListener(instanceID, upgrade => {
- // don't install the upgrade by doing nothing here.
- // The upgrade will be installed upon next restart.
- });
-}
-
-function isAvailable() {
- let availablePref = Services.prefs.getCharPref("extensions.formautofill.available");
- if (availablePref == "on") {
- return true;
- } else if (availablePref == "detect") {
- let locale = Services.locale.getRequestedLocale();
- let region = Services.prefs.getCharPref("browser.search.region", "");
- let supportedCountries = Services.prefs.getCharPref("extensions.formautofill.supportedCountries")
- .split(",");
- if (!Services.prefs.getBoolPref("extensions.formautofill.supportRTL") &&
- Services.locale.isAppLocaleRTL) {
- return false;
- }
- return locale == "en-US" && supportedCountries.includes(region);
- }
- return false;
-}
-
-function startup(data) {
- // We have to do this before actually determining if we're enabled, since
- // there are scripts inside of the core browser code that depend on the
- // FormAutofill JSMs being registered.
- resProto.setSubstitution(RESOURCE_HOST,
- Services.io.newURI("chrome/res/", null, data.resourceURI));
-
- if (!isAvailable()) {
- Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
- // reset the sync related prefs incase the feature was previously available
- // but isn't now.
- Services.prefs.clearUserPref("services.sync.engine.addresses.available");
- Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
- Services.telemetry.scalarSet("formautofill.availability", false);
- return;
- }
-
- if (data.hasOwnProperty("instanceID") && data.instanceID) {
- if (AddonManagerPrivate.isDBLoaded()) {
- addUpgradeListener(data.instanceID);
- } else {
- // Wait for the extension database to be loaded so we don't cause its init.
- Services.obs.addObserver(function xpiDatabaseLoaded() {
- Services.obs.removeObserver(xpiDatabaseLoaded, "xpi-database-loaded");
- addUpgradeListener(data.instanceID);
- }, "xpi-database-loaded");
- }
- } else {
- throw Error("no instanceID passed to bootstrap startup");
- }
-
- // This pref is used for web contents to detect the autocomplete feature.
- // When it's true, "element.autocomplete" will return tokens we currently
- // support -- otherwise it'll return an empty string.
- Services.prefs.setBoolPref("dom.forms.autocomplete.formautofill", true);
- Services.telemetry.scalarSet("formautofill.availability", true);
-
- // This pref determines whether the "addresses"/"creditcards" sync engine is
- // available (ie, whether it is shown in any UI etc) - it *does not* determine
- // whether the engine is actually enabled or not.
- Services.prefs.setBoolPref("services.sync.engine.addresses.available", true);
- if (FormAutofill.isAutofillCreditCardsAvailable) {
- Services.prefs.setBoolPref("services.sync.engine.creditcards.available", true);
- } else {
- Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
- }
-
- // Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
- Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
-
- formAutofillParent.init().catch(Cu.reportError);
- /* eslint-disable no-unused-vars */
- Services.ppmm.loadProcessScript("data:,new " + function() {
- ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
- }, true);
- /* eslint-enable no-unused-vars */
- Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true, true);
-}
-
-function shutdown() {
- resProto.setSubstitution(RESOURCE_HOST, null);
-
- Services.mm.removeMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
-
- let enumerator = Services.wm.getEnumerator("navigator:browser");
- while (enumerator.hasMoreElements()) {
- let win = enumerator.getNext();
- let domWindow = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
- let cachedStyleSheets = CACHED_STYLESHEETS.get(domWindow);
-
- if (!cachedStyleSheets) {
- continue;
- }
-
- while (cachedStyleSheets.length !== 0) {
- cachedStyleSheets.pop().remove();
- }
- }
-}
-
-function install() {}
-function uninstall() {}
diff --git a/browser/extensions/formautofill/content/editAddress.xhtml b/browser/extensions/formautofill/content/editAddress.xhtml
index 958c8de3a7ad..8ab2b2e8f832 100644
--- a/browser/extensions/formautofill/content/editAddress.xhtml
+++ b/browser/extensions/formautofill/content/editAddress.xhtml
@@ -9,9 +9,9 @@
-
-
-
+
+
+
diff --git a/browser/extensions/formautofill/content/editCreditCard.xhtml b/browser/extensions/formautofill/content/editCreditCard.xhtml
index b443f820616f..f63ce78c99b0 100644
--- a/browser/extensions/formautofill/content/editCreditCard.xhtml
+++ b/browser/extensions/formautofill/content/editCreditCard.xhtml
@@ -9,9 +9,9 @@
-
-
-
+
+
+
diff --git a/browser/extensions/formautofill/install.rdf.in b/browser/extensions/formautofill/install.rdf.in
deleted file mode 100644
index 5e34051ba022..000000000000
--- a/browser/extensions/formautofill/install.rdf.in
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-#filter substitution
-
-
-
-
- formautofill@mozilla.org
- 1.0
- 2
- true
- true
-
-
-
-
- {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
- @MOZ_APP_VERSION@
- @MOZ_APP_MAXVERSION@
-
-
-
-
- Form Autofill
- Autofill forms with saved profiles
-
-
diff --git a/browser/extensions/formautofill/jar.mn b/browser/extensions/formautofill/jar.mn
index bd0a83c9b452..ec0cf877c52a 100644
--- a/browser/extensions/formautofill/jar.mn
+++ b/browser/extensions/formautofill/jar.mn
@@ -3,16 +3,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[features/formautofill@mozilla.org] chrome.jar:
-% resource formautofill %res/
res/ (*.jsm)
res/phonenumberutils/ (phonenumberutils/*.jsm)
res/addressmetadata/ (addressmetadata/*)
+ res/ (skin/shared/*)
-% content formautofill %content/
content/ (content/*)
-
-% skin formautofill classic/1.0 %skin/linux/ os=LikeUnix
-% skin formautofill classic/1.0 %skin/osx/ os=Darwin
-% skin formautofill classic/1.0 %skin/windows/ os=WINNT
-% skin formautofill-shared classic/1.0 %skin/shared/
- skin/ (skin/*)
diff --git a/browser/extensions/formautofill/manifest.json b/browser/extensions/formautofill/manifest.json
new file mode 100644
index 000000000000..b513d05166cd
--- /dev/null
+++ b/browser/extensions/formautofill/manifest.json
@@ -0,0 +1,26 @@
+{
+ "manifest_version": 2,
+ "name": "Form Autofill",
+ "version": "1.0",
+
+ "applications": {
+ "gecko": {
+ "id": "formautofill@mozilla.org"
+ }
+ },
+
+ "background": {
+ "scripts": ["background.js"]
+ },
+
+ "experiment_apis": {
+ "formautofill": {
+ "schema": "schema.json",
+ "parent": {
+ "scopes": ["addon_parent"],
+ "script": "api.js",
+ "events": ["startup"]
+ }
+ }
+ }
+}
diff --git a/browser/extensions/formautofill/moz.build b/browser/extensions/formautofill/moz.build
index 7ec138ea8fae..de5d562d6bbd 100644
--- a/browser/extensions/formautofill/moz.build
+++ b/browser/extensions/formautofill/moz.build
@@ -10,12 +10,27 @@ DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
DIRS += ['locales']
FINAL_TARGET_FILES.features['formautofill@mozilla.org'] += [
- 'bootstrap.js'
+ 'api.js',
+ 'background.js',
+ 'manifest.json',
+ 'schema.json',
]
-FINAL_TARGET_PP_FILES.features['formautofill@mozilla.org'] += [
- 'install.rdf.in'
-]
+if CONFIG['OS_ARCH'] == 'Linux':
+ FINAL_TARGET_FILES.features['formautofill@mozilla.org'].chrome.res += [
+ 'skin/linux/autocomplete-item.css',
+ 'skin/linux/editDialog.css',
+ ]
+elif CONFIG['OS_ARCH'] == 'Darwin':
+ FINAL_TARGET_FILES.features['formautofill@mozilla.org'].chrome.res += [
+ 'skin/osx/autocomplete-item.css',
+ 'skin/osx/editDialog.css',
+ ]
+elif CONFIG['OS_ARCH'] == 'WINNT':
+ FINAL_TARGET_FILES.features['formautofill@mozilla.org'].chrome.res += [
+ 'skin/windows/autocomplete-item.css',
+ 'skin/windows/editDialog.css',
+ ]
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
diff --git a/browser/extensions/formautofill/schema.json b/browser/extensions/formautofill/schema.json
new file mode 100644
index 000000000000..fe51488c7066
--- /dev/null
+++ b/browser/extensions/formautofill/schema.json
@@ -0,0 +1 @@
+[]
diff --git a/browser/extensions/formautofill/skin/shared/autocomplete-item.css b/browser/extensions/formautofill/skin/shared/autocomplete-item-shared.css
similarity index 100%
rename from browser/extensions/formautofill/skin/shared/autocomplete-item.css
rename to browser/extensions/formautofill/skin/shared/autocomplete-item-shared.css
diff --git a/browser/extensions/formautofill/skin/shared/editDialog.css b/browser/extensions/formautofill/skin/shared/editDialog-shared.css
similarity index 100%
rename from browser/extensions/formautofill/skin/shared/editDialog.css
rename to browser/extensions/formautofill/skin/shared/editDialog-shared.css
diff --git a/browser/extensions/formautofill/test/unit/head.js b/browser/extensions/formautofill/test/unit/head.js
index 28ccf14c410f..6312cb4f672a 100644
--- a/browser/extensions/formautofill/test/unit/head.js
+++ b/browser/extensions/formautofill/test/unit/head.js
@@ -8,6 +8,8 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm");
ChromeUtils.import("resource://gre/modules/FormLikeFactory.jsm");
+ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
+ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm");
ChromeUtils.import("resource://testing-common/FileTestUtils.jsm");
ChromeUtils.import("resource://testing-common/MockDocument.jsm");
ChromeUtils.import("resource://testing-common/TestUtils.jsm");
@@ -17,9 +19,8 @@ ChromeUtils.defineModuleGetter(this, "DownloadPaths",
ChromeUtils.defineModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "resProto",
- "@mozilla.org/network/protocol;1?name=resource",
- "nsISubstitutingProtocolHandler");
+ChromeUtils.defineModuleGetter(this, "ExtensionParent",
+ "resource://gre/modules/ExtensionParent.jsm");
do_get_profile();
@@ -31,26 +32,38 @@ Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js",
/* globals sinon */
// ================================================
-// Load our bootstrap extension manifest so we can access our chrome/resource URIs.
const EXTENSION_ID = "formautofill@mozilla.org";
-let extensionDir = Services.dirsvc.get("GreD", Ci.nsIFile);
-extensionDir.append("browser");
-extensionDir.append("features");
-extensionDir.append(EXTENSION_ID);
-let bootstrapFile = extensionDir.clone();
-bootstrapFile.append("bootstrap.js");
-let bootstrapURI = Services.io.newFileURI(bootstrapFile).spec;
-// If the unpacked extension doesn't exist, use the packed version.
-if (!extensionDir.exists()) {
- extensionDir = extensionDir.parent;
- extensionDir.append(EXTENSION_ID + ".xpi");
- let jarURI = Services.io.newFileURI(extensionDir);
- bootstrapURI = "jar:" + jarURI.spec + "!/bootstrap.js";
-}
-Components.manager.addBootstrappedManifestLocation(extensionDir);
-let resURI = Services.io.newURI("chrome/res/", null, Services.io.newURI(bootstrapURI));
-resProto.setSubstitution("formautofill", resURI);
+AddonTestUtils.init(this);
+
+async function loadExtension() {
+ AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+ await AddonTestUtils.promiseStartupManager();
+
+ let extensionPath = Services.dirsvc.get("GreD", Ci.nsIFile);
+ extensionPath.append("browser");
+ extensionPath.append("features");
+ extensionPath.append(EXTENSION_ID);
+
+ if (!extensionPath.exists()) {
+ extensionPath.leafName = `${EXTENSION_ID}.xpi`;
+ }
+
+ let startupPromise = new Promise(resolve => {
+ const {apiManager} = ExtensionParent;
+ function onReady(event, extension) {
+ if (extension.id == EXTENSION_ID) {
+ apiManager.off("ready", onReady);
+ resolve();
+ }
+ }
+
+ apiManager.on("ready", onReady);
+ });
+
+ await AddonManager.installTemporaryAddon(extensionPath);
+ await startupPromise;
+}
// Returns a reference to a temporary file that is guaranteed not to exist and
// is cleaned up later. See FileTestUtils.getTempFile for details.
@@ -64,6 +77,15 @@ async function initProfileStorage(fileName, records, collectionName = "addresses
let profileStorage = new FormAutofillStorage(path);
await profileStorage.initialize();
+ // AddonTestUtils inserts its own directory provider that manages TmpD.
+ // It removes that directory at shutdown, which races with shutdown
+ // handing in JSONFile/DeferredTask (which is used by FormAutofillStorage).
+ // Avoid the race by explicitly finalizing any formautofill JSONFile
+ // instances created manually by individual tests when the test finishes.
+ registerCleanupFunction(function finalizeAutofillStorage() {
+ return profileStorage._finalize();
+ });
+
if (!records || !Array.isArray(records)) {
return profileStorage;
}
@@ -99,9 +121,11 @@ function verifySectionFieldDetails(sections, expectedResults) {
});
}
-function runHeuristicsTest(patterns, fixturePathPrefix) {
- ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
- ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
+async function runHeuristicsTest(patterns, fixturePathPrefix) {
+ add_task(async function setup() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
+ ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
+ });
patterns.forEach(testPattern => {
add_task(async function() {
@@ -194,4 +218,6 @@ add_task(async function head_initialize() {
Services.prefs.clearUserPref("extensions.formautofill.section.enabled");
Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
});
+
+ await loadExtension();
});
diff --git a/browser/extensions/formautofill/test/unit/test_activeStatus.js b/browser/extensions/formautofill/test/unit/test_activeStatus.js
index b8b73a861305..efc21f040490 100644
--- a/browser/extensions/formautofill/test/unit/test_activeStatus.js
+++ b/browser/extensions/formautofill/test/unit/test_activeStatus.js
@@ -4,7 +4,11 @@
"use strict";
-let {FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {});
+let FormAutofillParent;
+
+add_task(async function setup() {
+ ({FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {}));
+});
add_task(async function test_activeStatus_init() {
let formAutofillParent = new FormAutofillParent();
diff --git a/browser/extensions/formautofill/test/unit/test_addressDataLoader.js b/browser/extensions/formautofill/test/unit/test_addressDataLoader.js
index b3b59e978ad0..edfa43303b9a 100644
--- a/browser/extensions/formautofill/test/unit/test_addressDataLoader.js
+++ b/browser/extensions/formautofill/test/unit/test_addressDataLoader.js
@@ -1,7 +1,5 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
-
const SUPPORT_COUNTRIES_TESTCASES = [
{
country: "US",
@@ -17,6 +15,10 @@ const SUPPORT_COUNTRIES_TESTCASES = [
},
];
+add_task(async function setup() {
+ ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
+});
+
add_task(async function test_initalState() {
// addressData should not exist
Assert.equal(AddressDataLoader._addressData, undefined);
diff --git a/browser/extensions/formautofill/test/unit/test_autofillFormFields.js b/browser/extensions/formautofill/test/unit/test_autofillFormFields.js
index 95c8e9d4a00a..a646d2dbb075 100644
--- a/browser/extensions/formautofill/test/unit/test_autofillFormFields.js
+++ b/browser/extensions/formautofill/test/unit/test_autofillFormFields.js
@@ -5,8 +5,11 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
-let {MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {});
+let MasterPassword;
+add_task(async function setup() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
+ ({MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {}));
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_collectFormFields.js b/browser/extensions/formautofill/test/unit/test_collectFormFields.js
index c395e06c5774..bda549e56ab0 100644
--- a/browser/extensions/formautofill/test/unit/test_collectFormFields.js
+++ b/browser/extensions/formautofill/test/unit/test_collectFormFields.js
@@ -4,7 +4,9 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
+add_task(async function setup() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_createRecords.js b/browser/extensions/formautofill/test/unit/test_createRecords.js
index 80bb23f1eca6..c3254cd72ae1 100644
--- a/browser/extensions/formautofill/test/unit/test_createRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_createRecords.js
@@ -4,7 +4,9 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
+add_task(async function seutp() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_creditCardRecords.js b/browser/extensions/formautofill/test/unit/test_creditCardRecords.js
index 3986ae5a3317..0672183a7d14 100644
--- a/browser/extensions/formautofill/test/unit/test_creditCardRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_creditCardRecords.js
@@ -4,11 +4,15 @@
"use strict";
-const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
ChromeUtils.defineModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
ChromeUtils.import("resource://gre/modules/CreditCard.jsm");
+let FormAutofillStorage;
+add_task(async function setup() {
+ ({FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {}));
+});
+
const TEST_STORE_FILE_NAME = "test-credit-card.json";
const COLLECTION_NAME = "creditCards";
diff --git a/browser/extensions/formautofill/test/unit/test_extractLabelStrings.js b/browser/extensions/formautofill/test/unit/test_extractLabelStrings.js
index cc98a7cf8245..69368114de65 100644
--- a/browser/extensions/formautofill/test/unit/test_extractLabelStrings.js
+++ b/browser/extensions/formautofill/test/unit/test_extractLabelStrings.js
@@ -1,6 +1,8 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
+add_task(async function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_findLabelElements.js b/browser/extensions/formautofill/test/unit/test_findLabelElements.js
index fefa856aa231..4ebfecb0a34f 100644
--- a/browser/extensions/formautofill/test/unit/test_findLabelElements.js
+++ b/browser/extensions/formautofill/test/unit/test_findLabelElements.js
@@ -1,6 +1,8 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
+add_task(async function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_getAdaptedProfiles.js b/browser/extensions/formautofill/test/unit/test_getAdaptedProfiles.js
index e5ed1f5b0bc9..0fff540ad5e5 100644
--- a/browser/extensions/formautofill/test/unit/test_getAdaptedProfiles.js
+++ b/browser/extensions/formautofill/test/unit/test_getAdaptedProfiles.js
@@ -4,7 +4,9 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
+add_task(async function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
+});
const DEFAULT_ADDRESS_RECORD = {
"guid": "123",
diff --git a/browser/extensions/formautofill/test/unit/test_getCategoriesFromFieldNames.js b/browser/extensions/formautofill/test/unit/test_getCategoriesFromFieldNames.js
index baeb083bba7a..c58be815e934 100644
--- a/browser/extensions/formautofill/test/unit/test_getCategoriesFromFieldNames.js
+++ b/browser/extensions/formautofill/test/unit/test_getCategoriesFromFieldNames.js
@@ -1,7 +1,9 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
+add_task(async function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
+});
add_task(async function test_isAddressField_isCreditCardField() {
const TEST_CASES = {
diff --git a/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js b/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
index acff7c6ad3c4..81f0ab4105df 100644
--- a/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
+++ b/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
@@ -1,6 +1,8 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
+add_task(async function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_getInfo.js b/browser/extensions/formautofill/test/unit/test_getInfo.js
index 5eb16102fac4..80a4fcb40e4e 100644
--- a/browser/extensions/formautofill/test/unit/test_getInfo.js
+++ b/browser/extensions/formautofill/test/unit/test_getInfo.js
@@ -1,6 +1,8 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
+add_task(async function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_getRecords.js b/browser/extensions/formautofill/test/unit/test_getRecords.js
index 61c200ab9f6f..f652c21ff02b 100644
--- a/browser/extensions/formautofill/test/unit/test_getRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_getRecords.js
@@ -4,10 +4,14 @@
"use strict";
-let {FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {});
-ChromeUtils.import("resource://formautofill/MasterPassword.jsm");
ChromeUtils.import("resource://gre/modules/CreditCard.jsm");
+let FormAutofillParent;
+add_task(async function setup() {
+ ({FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {}));
+ ChromeUtils.import("resource://formautofill/MasterPassword.jsm");
+});
+
const TEST_ADDRESS_1 = {
"given-name": "Timothy",
"additional-name": "John",
diff --git a/browser/extensions/formautofill/test/unit/test_isAvailable.js b/browser/extensions/formautofill/test/unit/test_isAvailable.js
index a9ba0e597c9c..4633616c265f 100644
--- a/browser/extensions/formautofill/test/unit/test_isAvailable.js
+++ b/browser/extensions/formautofill/test/unit/test_isAvailable.js
@@ -4,13 +4,10 @@
"use strict";
-// Load bootstrap.js into a sandbox to be able to test `isAvailable`
-let sandbox = {};
-Services.scriptloader.loadSubScript(bootstrapURI, sandbox, "utf-8");
-info("bootstrapURI: " + bootstrapURI);
+const DOM_ENABLED_PREF = "dom.forms.autocomplete.formautofill";
add_task(async function test_defaultTestEnvironment() {
- Assert.ok(sandbox.isAvailable());
+ Assert.ok(Services.prefs.getBoolPref(DOM_ENABLED_PREF));
});
add_task(async function test_unsupportedRegion() {
@@ -19,7 +16,11 @@ add_task(async function test_unsupportedRegion() {
registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region");
});
- Assert.ok(!sandbox.isAvailable());
+
+ let addon = await AddonManager.getAddonByID(EXTENSION_ID);
+ await addon.reload();
+
+ Assert.ok(!Services.prefs.getBoolPref(DOM_ENABLED_PREF));
});
add_task(async function test_supportedRegion() {
@@ -28,5 +29,9 @@ add_task(async function test_supportedRegion() {
registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region");
});
- Assert.ok(sandbox.isAvailable());
+
+ let addon = await AddonManager.getAddonByID(EXTENSION_ID);
+ await addon.reload();
+
+ Assert.ok(Services.prefs.getBoolPref(DOM_ENABLED_PREF));
});
diff --git a/browser/extensions/formautofill/test/unit/test_isCJKName.js b/browser/extensions/formautofill/test/unit/test_isCJKName.js
index 053aade850dd..0fafb270f176 100644
--- a/browser/extensions/formautofill/test/unit/test_isCJKName.js
+++ b/browser/extensions/formautofill/test/unit/test_isCJKName.js
@@ -4,7 +4,9 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
+add_task(async function setup() {
+ ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
+});
// Test cases is initially copied from
// https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc
diff --git a/browser/extensions/formautofill/test/unit/test_isFieldEligibleForAutofill.js b/browser/extensions/formautofill/test/unit/test_isFieldEligibleForAutofill.js
index 3ba013c3c7ec..dd01cfe3b787 100644
--- a/browser/extensions/formautofill/test/unit/test_isFieldEligibleForAutofill.js
+++ b/browser/extensions/formautofill/test/unit/test_isFieldEligibleForAutofill.js
@@ -1,6 +1,8 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
+add_task(async function seutp() {
+ ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
+});
const TESTCASES = [
{
diff --git a/browser/extensions/formautofill/test/unit/test_markAsAutofillField.js b/browser/extensions/formautofill/test/unit/test_markAsAutofillField.js
index 06e54c19a48e..e54f3254c071 100644
--- a/browser/extensions/formautofill/test/unit/test_markAsAutofillField.js
+++ b/browser/extensions/formautofill/test/unit/test_markAsAutofillField.js
@@ -1,7 +1,5 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
-
const TESTCASES = [
{
description: "Form containing 8 fields with autocomplete attribute.",
@@ -61,9 +59,14 @@ const TESTCASES = [
];
let markedFieldId = [];
-FormAutofillContent._markAsAutofillField = function(field) {
- markedFieldId.push(field.id);
-};
+
+add_task(async function setup() {
+ ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
+
+ FormAutofillContent._markAsAutofillField = function(field) {
+ markedFieldId.push(field.id);
+ };
+});
TESTCASES.forEach(testcase => {
add_task(async function() {
diff --git a/browser/extensions/formautofill/test/unit/test_masterPassword.js b/browser/extensions/formautofill/test/unit/test_masterPassword.js
index 5e7ead8e34a2..9c945ef63222 100644
--- a/browser/extensions/formautofill/test/unit/test_masterPassword.js
+++ b/browser/extensions/formautofill/test/unit/test_masterPassword.js
@@ -5,7 +5,11 @@
"use strict";
const {MockRegistrar} =
ChromeUtils.import("resource://testing-common/MockRegistrar.jsm", {});
-let {MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {});
+
+let MasterPassword;
+add_task(async function setup() {
+ ({MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {}));
+});
const TESTCASES = [{
description: "With master password set",
@@ -67,10 +71,10 @@ registerCleanupFunction(() => {
});
TESTCASES.forEach(testcase => {
- let token = MasterPassword._token;
-
add_task(async function test_encrypt_decrypt() {
info("Starting testcase: " + testcase.description);
+
+ let token = MasterPassword._token;
token.initPassword(testcase.masterPassword);
// Test only: Force the token login without asking for master password
diff --git a/browser/extensions/formautofill/test/unit/test_migrateRecords.js b/browser/extensions/formautofill/test/unit/test_migrateRecords.js
index c5a0a7dde906..00f2c78a170e 100644
--- a/browser/extensions/formautofill/test/unit/test_migrateRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_migrateRecords.js
@@ -4,7 +4,11 @@
"use strict";
-const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
+let FormAutofillStorage;
+
+add_task(async function setup() {
+ ({FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {}));
+});
const TEST_STORE_FILE_NAME = "test-profile.json";
diff --git a/browser/extensions/formautofill/test/unit/test_nameUtils.js b/browser/extensions/formautofill/test/unit/test_nameUtils.js
index b9a36989585c..b1a82d862df0 100644
--- a/browser/extensions/formautofill/test/unit/test_nameUtils.js
+++ b/browser/extensions/formautofill/test/unit/test_nameUtils.js
@@ -4,7 +4,9 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
+add_task(async function() {
+ ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
+});
// Test cases initially copied from
// https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc
diff --git a/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js b/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
index 10fb13476c41..4634f2c500fb 100644
--- a/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
+++ b/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
@@ -1,6 +1,8 @@
"use strict";
-ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
+add_task(async function setup() {
+ ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
+});
const MOCK_DOC = MockDocument.createTestDocument("http://localhost:8080/test/",
`