Bug 1449055 Convert formautofill to a webextension r=MattN,kmag

--HG--
rename : browser/extensions/formautofill/bootstrap.js => browser/extensions/formautofill/api.js
rename : browser/extensions/formautofill/install.rdf.in => browser/extensions/formautofill/manifest.json
rename : browser/extensions/formautofill/skin/shared/autocomplete-item.css => browser/extensions/formautofill/skin/shared/autocomplete-item-shared.css
rename : browser/extensions/formautofill/skin/shared/editDialog.css => browser/extensions/formautofill/skin/shared/editDialog-shared.css
extra : rebase_source : 233ea805630209a07d347e19f19710d9755f595f
extra : source : ecda6532c852b3f225fce998e3ce83ad157760e6
This commit is contained in:
Andrew Swan 2018-07-28 14:06:07 -07:00
Родитель 5a1e9a45a3
Коммит fb72dcb414
46 изменённых файлов: 412 добавлений и 291 удалений

Просмотреть файл

@ -1790,6 +1790,10 @@ FormAutofillStorage.prototype = {
_saveImmediately() { _saveImmediately() {
return this._store._save(); return this._store._save();
}, },
_finalize() {
return this._store.finalize();
},
}; };
// The singleton exposed by this module. // The singleton exposed by this module.

Просмотреть файл

@ -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();
}
}
}
};

Просмотреть файл

@ -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.
});

159
browser/extensions/formautofill/bootstrap.js поставляемый
Просмотреть файл

@ -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() {}

Просмотреть файл

@ -9,9 +9,9 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<title data-localization="addNewAddressTitle"/> <title data-localization="addNewAddressTitle"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editDialog.css"/> <link rel="stylesheet" href="resource://formautofill/editDialog-shared.css"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editAddress.css"/> <link rel="stylesheet" href="resource://formautofill/editAddress.css"/>
<link rel="stylesheet" href="chrome://formautofill/skin/editDialog.css"/> <link rel="stylesheet" href="resource://formautofill/editDialog.css"/>
<script src="chrome://formautofill/content/l10n.js"></script> <script src="chrome://formautofill/content/l10n.js"></script>
<script src="chrome://formautofill/content/editDialog.js"></script> <script src="chrome://formautofill/content/editDialog.js"></script>
<script src="chrome://formautofill/content/autofillEditForms.js"></script> <script src="chrome://formautofill/content/autofillEditForms.js"></script>

Просмотреть файл

@ -9,9 +9,9 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<title data-localization="addNewCreditCardTitle"/> <title data-localization="addNewCreditCardTitle"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editDialog.css"/> <link rel="stylesheet" href="resource://formautofill/editDialog-shared.css"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editCreditCard.css"/> <link rel="stylesheet" href="resource://formautofill/editCreditCard.css"/>
<link rel="stylesheet" href="chrome://formautofill/skin/editDialog.css"/> <link rel="stylesheet" href="resource://formautofill/editDialog.css"/>
<script src="chrome://formautofill/content/l10n.js"></script> <script src="chrome://formautofill/content/l10n.js"></script>
<script src="chrome://formautofill/content/editDialog.js"></script> <script src="chrome://formautofill/content/editDialog.js"></script>
<script src="chrome://formautofill/content/autofillEditForms.js"></script> <script src="chrome://formautofill/content/autofillEditForms.js"></script>

Просмотреть файл

@ -1,32 +0,0 @@
<?xml version="1.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/. -->
#filter substitution
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>formautofill@mozilla.org</em:id>
<em:version>1.0</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:multiprocessCompatible>true</em:multiprocessCompatible>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
<em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>Form Autofill</em:name>
<em:description>Autofill forms with saved profiles</em:description>
</Description>
</RDF>

Просмотреть файл

@ -3,16 +3,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
[features/formautofill@mozilla.org] chrome.jar: [features/formautofill@mozilla.org] chrome.jar:
% resource formautofill %res/
res/ (*.jsm) res/ (*.jsm)
res/phonenumberutils/ (phonenumberutils/*.jsm) res/phonenumberutils/ (phonenumberutils/*.jsm)
res/addressmetadata/ (addressmetadata/*) res/addressmetadata/ (addressmetadata/*)
res/ (skin/shared/*)
% content formautofill %content/
content/ (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/*)

Просмотреть файл

@ -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"]
}
}
}
}

Просмотреть файл

@ -10,12 +10,27 @@ DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
DIRS += ['locales'] DIRS += ['locales']
FINAL_TARGET_FILES.features['formautofill@mozilla.org'] += [ 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'] += [ if CONFIG['OS_ARCH'] == 'Linux':
'install.rdf.in' 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'] BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']

Просмотреть файл

@ -0,0 +1 @@
[]

Просмотреть файл

@ -8,6 +8,8 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm"); ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm"); ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm");
ChromeUtils.import("resource://gre/modules/FormLikeFactory.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/FileTestUtils.jsm");
ChromeUtils.import("resource://testing-common/MockDocument.jsm"); ChromeUtils.import("resource://testing-common/MockDocument.jsm");
ChromeUtils.import("resource://testing-common/TestUtils.jsm"); ChromeUtils.import("resource://testing-common/TestUtils.jsm");
@ -17,9 +19,8 @@ ChromeUtils.defineModuleGetter(this, "DownloadPaths",
ChromeUtils.defineModuleGetter(this, "FileUtils", ChromeUtils.defineModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm"); "resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "resProto", ChromeUtils.defineModuleGetter(this, "ExtensionParent",
"@mozilla.org/network/protocol;1?name=resource", "resource://gre/modules/ExtensionParent.jsm");
"nsISubstitutingProtocolHandler");
do_get_profile(); do_get_profile();
@ -31,26 +32,38 @@ Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js",
/* globals sinon */ /* globals sinon */
// ================================================ // ================================================
// Load our bootstrap extension manifest so we can access our chrome/resource URIs.
const EXTENSION_ID = "formautofill@mozilla.org"; 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)); AddonTestUtils.init(this);
resProto.setSubstitution("formautofill", resURI);
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 // Returns a reference to a temporary file that is guaranteed not to exist and
// is cleaned up later. See FileTestUtils.getTempFile for details. // 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); let profileStorage = new FormAutofillStorage(path);
await profileStorage.initialize(); 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)) { if (!records || !Array.isArray(records)) {
return profileStorage; return profileStorage;
} }
@ -99,9 +121,11 @@ function verifySectionFieldDetails(sections, expectedResults) {
}); });
} }
function runHeuristicsTest(patterns, fixturePathPrefix) { async function runHeuristicsTest(patterns, fixturePathPrefix) {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm"); add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm"); ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
patterns.forEach(testPattern => { patterns.forEach(testPattern => {
add_task(async function() { add_task(async function() {
@ -194,4 +218,6 @@ add_task(async function head_initialize() {
Services.prefs.clearUserPref("extensions.formautofill.section.enabled"); Services.prefs.clearUserPref("extensions.formautofill.section.enabled");
Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill"); Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
}); });
await loadExtension();
}); });

Просмотреть файл

@ -4,7 +4,11 @@
"use strict"; "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() { add_task(async function test_activeStatus_init() {
let formAutofillParent = new FormAutofillParent(); let formAutofillParent = new FormAutofillParent();

Просмотреть файл

@ -1,7 +1,5 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
const SUPPORT_COUNTRIES_TESTCASES = [ const SUPPORT_COUNTRIES_TESTCASES = [
{ {
country: "US", 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() { add_task(async function test_initalState() {
// addressData should not exist // addressData should not exist
Assert.equal(AddressDataLoader._addressData, undefined); Assert.equal(AddressDataLoader._addressData, undefined);

Просмотреть файл

@ -5,8 +5,11 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm"); let MasterPassword;
let {MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {}); add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
({MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {}));
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -4,7 +4,9 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm"); add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -4,7 +4,9 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm"); add_task(async function seutp() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -4,11 +4,15 @@
"use strict"; "use strict";
const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
ChromeUtils.defineModuleGetter(this, "Preferences", ChromeUtils.defineModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm"); "resource://gre/modules/Preferences.jsm");
ChromeUtils.import("resource://gre/modules/CreditCard.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 TEST_STORE_FILE_NAME = "test-credit-card.json";
const COLLECTION_NAME = "creditCards"; const COLLECTION_NAME = "creditCards";

Просмотреть файл

@ -1,6 +1,8 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm"); add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -1,6 +1,8 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm"); add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -4,7 +4,9 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm"); add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
});
const DEFAULT_ADDRESS_RECORD = { const DEFAULT_ADDRESS_RECORD = {
"guid": "123", "guid": "123",

Просмотреть файл

@ -1,7 +1,9 @@
"use strict"; "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() { add_task(async function test_isAddressField_isCreditCardField() {
const TEST_CASES = { const TEST_CASES = {

Просмотреть файл

@ -1,6 +1,8 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm"); add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -1,6 +1,8 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm"); add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -4,10 +4,14 @@
"use strict"; "use strict";
let {FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {});
ChromeUtils.import("resource://formautofill/MasterPassword.jsm");
ChromeUtils.import("resource://gre/modules/CreditCard.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 = { const TEST_ADDRESS_1 = {
"given-name": "Timothy", "given-name": "Timothy",
"additional-name": "John", "additional-name": "John",

Просмотреть файл

@ -4,13 +4,10 @@
"use strict"; "use strict";
// Load bootstrap.js into a sandbox to be able to test `isAvailable` const DOM_ENABLED_PREF = "dom.forms.autocomplete.formautofill";
let sandbox = {};
Services.scriptloader.loadSubScript(bootstrapURI, sandbox, "utf-8");
info("bootstrapURI: " + bootstrapURI);
add_task(async function test_defaultTestEnvironment() { add_task(async function test_defaultTestEnvironment() {
Assert.ok(sandbox.isAvailable()); Assert.ok(Services.prefs.getBoolPref(DOM_ENABLED_PREF));
}); });
add_task(async function test_unsupportedRegion() { add_task(async function test_unsupportedRegion() {
@ -19,7 +16,11 @@ add_task(async function test_unsupportedRegion() {
registerCleanupFunction(function cleanupRegion() { registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region"); 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() { add_task(async function test_supportedRegion() {
@ -28,5 +29,9 @@ add_task(async function test_supportedRegion() {
registerCleanupFunction(function cleanupRegion() { registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region"); 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));
}); });

Просмотреть файл

@ -4,7 +4,9 @@
"use strict"; "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 // Test cases is initially copied from
// https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc // https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc

Просмотреть файл

@ -1,6 +1,8 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm"); add_task(async function seutp() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
const TESTCASES = [ const TESTCASES = [
{ {

Просмотреть файл

@ -1,7 +1,5 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
const TESTCASES = [ const TESTCASES = [
{ {
description: "Form containing 8 fields with autocomplete attribute.", description: "Form containing 8 fields with autocomplete attribute.",
@ -61,9 +59,14 @@ const TESTCASES = [
]; ];
let markedFieldId = []; 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 => { TESTCASES.forEach(testcase => {
add_task(async function() { add_task(async function() {

Просмотреть файл

@ -5,7 +5,11 @@
"use strict"; "use strict";
const {MockRegistrar} = const {MockRegistrar} =
ChromeUtils.import("resource://testing-common/MockRegistrar.jsm", {}); 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 = [{ const TESTCASES = [{
description: "With master password set", description: "With master password set",
@ -67,10 +71,10 @@ registerCleanupFunction(() => {
}); });
TESTCASES.forEach(testcase => { TESTCASES.forEach(testcase => {
let token = MasterPassword._token;
add_task(async function test_encrypt_decrypt() { add_task(async function test_encrypt_decrypt() {
info("Starting testcase: " + testcase.description); info("Starting testcase: " + testcase.description);
let token = MasterPassword._token;
token.initPassword(testcase.masterPassword); token.initPassword(testcase.masterPassword);
// Test only: Force the token login without asking for master password // Test only: Force the token login without asking for master password

Просмотреть файл

@ -4,7 +4,11 @@
"use strict"; "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"; const TEST_STORE_FILE_NAME = "test-profile.json";

Просмотреть файл

@ -4,7 +4,9 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm"); add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
});
// Test cases initially copied from // Test cases initially copied from
// https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc // https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc

Просмотреть файл

@ -1,6 +1,8 @@
"use strict"; "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/", const MOCK_DOC = MockDocument.createTestDocument("http://localhost:8080/test/",
`<form id="form1"> `<form id="form1">

Просмотреть файл

@ -1,6 +1,8 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm"); add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
add_task(async function test_parseAddressFormat() { add_task(async function test_parseAddressFormat() {
const TEST_CASES = [ const TEST_CASES = [

Просмотреть файл

@ -4,8 +4,10 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumber.jsm"); add_task(async function setup() {
ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumberNormalizer.jsm"); ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumber.jsm");
ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumberNormalizer.jsm");
});
function IsPlain(dial, expected) { function IsPlain(dial, expected) {
let result = PhoneNumber.IsPlain(dial); let result = PhoneNumber.IsPlain(dial);

Просмотреть файл

@ -1,8 +1,10 @@
"use strict"; "use strict";
/* global AddressResult, CreditCardResult */ /* global AddressResult, CreditCardResult */
// eslint-disable-next-line no-unused-vars add_task(async function setup() {
ChromeUtils.import("resource://formautofill/ProfileAutoCompleteResult.jsm"); // eslint-disable-next-line no-unused-vars
ChromeUtils.import("resource://formautofill/ProfileAutoCompleteResult.jsm");
});
let matchingProfiles = [{ let matchingProfiles = [{
guid: "test-guid-1", guid: "test-guid-1",
@ -341,15 +343,15 @@ let creditCardTestCases = [{
}, },
}]; }];
let testSets = [{
collectionConstructor: AddressResult,
testCases: addressTestCases,
}, {
collectionConstructor: CreditCardResult,
testCases: creditCardTestCases,
}];
add_task(async function test_all_patterns() { add_task(async function test_all_patterns() {
let testSets = [{
collectionConstructor: AddressResult,
testCases: addressTestCases,
}, {
collectionConstructor: CreditCardResult,
testCases: creditCardTestCases,
}];
testSets.forEach(({collectionConstructor, testCases}) => { testSets.forEach(({collectionConstructor, testCases}) => {
testCases.forEach(testCase => { testCases.forEach(testCase => {
info("Starting testcase: " + testCase.description); info("Starting testcase: " + testCase.description);

Просмотреть файл

@ -4,7 +4,11 @@
"use strict"; "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_profileSavedFieldNames_init() { add_task(async function test_profileSavedFieldNames_init() {
let formAutofillParent = new FormAutofillParent(); let formAutofillParent = new FormAutofillParent();

Просмотреть файл

@ -4,7 +4,10 @@
"use strict"; "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-tombstones.json"; const TEST_STORE_FILE_NAME = "test-tombstones.json";

Просмотреть файл

@ -4,7 +4,10 @@
"use strict"; "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-tombstones.json"; const TEST_STORE_FILE_NAME = "test-tombstones.json";

Просмотреть файл

@ -13,8 +13,11 @@ ChromeUtils.import("resource://services-sync/service.js");
ChromeUtils.import("resource://services-sync/constants.js"); ChromeUtils.import("resource://services-sync/constants.js");
ChromeUtils.import("resource://testing-common/services/sync/utils.js"); ChromeUtils.import("resource://testing-common/services/sync/utils.js");
let {sanitizeStorageObject, AutofillRecord, AddressesEngine} = let sanitizeStorageObject, AutofillRecord, AddressesEngine;
ChromeUtils.import("resource://formautofill/FormAutofillSync.jsm", {}); add_task(async function() {
({sanitizeStorageObject, AutofillRecord, AddressesEngine} =
ChromeUtils.import("resource://formautofill/FormAutofillSync.jsm", {}));
});
Services.prefs.setCharPref("extensions.formautofill.loglevel", "Trace"); Services.prefs.setCharPref("extensions.formautofill.loglevel", "Trace");

Просмотреть файл

@ -1,7 +1,9 @@
"use strict"; "use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm"); add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
add_task(async function test_getCategoriesFromFieldNames() { add_task(async function test_getCategoriesFromFieldNames() {
const TEST_CASES = [ const TEST_CASES = [

Просмотреть файл

@ -4,7 +4,10 @@
"use strict"; "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"; const TEST_STORE_FILE_NAME = "test-profile.json";
@ -901,6 +904,8 @@ add_task(async function test_computeAddressFields() {
profileStorage.addresses.remove(guid); profileStorage.addresses.remove(guid);
}); });
await profileStorage._finalize();
}); });
add_task(async function test_normalizeAddressFields() { add_task(async function test_normalizeAddressFields() {
@ -918,6 +923,8 @@ add_task(async function test_normalizeAddressFields() {
profileStorage.addresses.remove(guid); profileStorage.addresses.remove(guid);
}); });
await profileStorage._finalize();
}); });
add_task(async function test_computeCreditCardFields() { add_task(async function test_computeCreditCardFields() {
@ -935,6 +942,8 @@ add_task(async function test_computeCreditCardFields() {
profileStorage.creditCards.remove(guid); profileStorage.creditCards.remove(guid);
}); });
await profileStorage._finalize();
}); });
add_task(async function test_normalizeCreditCardFields() { add_task(async function test_normalizeCreditCardFields() {
@ -952,4 +961,6 @@ add_task(async function test_normalizeCreditCardFields() {
profileStorage.creditCards.remove(guid); profileStorage.creditCards.remove(guid);
}); });
await profileStorage._finalize();
}); });

Просмотреть файл

@ -118,6 +118,11 @@ XPCOMUtils.defineLazyGetter(FileTestUtils, "_globalTemporaryDirectory",
for (let path of gPathsToRemove) { for (let path of gPathsToRemove) {
await this.tolerantRemove(path); await this.tolerantRemove(path);
} }
if (!(await OS.File.exists(dir.path))) {
return;
}
// Detect any extra files, like the ".part" files of downloads. // Detect any extra files, like the ".part" files of downloads.
let iterator = new OS.File.DirectoryIterator(dir.path); let iterator = new OS.File.DirectoryIterator(dir.path);
try { try {

Просмотреть файл

@ -8,8 +8,8 @@
@import url("chrome://global/content/autocomplete.css"); @import url("chrome://global/content/autocomplete.css");
@import url("chrome://global/skin/autocomplete.css"); @import url("chrome://global/skin/autocomplete.css");
@import url("chrome://formautofill-shared/skin/autocomplete-item.css"); @import url("resource://formautofill/autocomplete-item-shared.css");
@import url("chrome://formautofill/skin/autocomplete-item.css"); @import url("resource://formautofill/autocomplete-item.css");
@import url("chrome://global/skin/dialog.css"); @import url("chrome://global/skin/dialog.css");
@import url("chrome://global/skin/dropmarker.css"); @import url("chrome://global/skin/dropmarker.css");
@import url("chrome://global/skin/groupbox.css"); @import url("chrome://global/skin/groupbox.css");