Bug 1449055 Convert formautofill to a webextension draft
authorAndrew Swan <aswan@mozilla.com>
Tue, 24 Jul 2018 19:40:57 -0700
changeset 828840 fe40d079ce18a1f1564f2468bd9e038b9c1d45c5
parent 828125 937c64cef999caecf6478792683879105877a6db
child 828841 d99c5c49e75afaa4ca18aabf1ae0ffd531c2f0d2
child 828845 ce6ce90b726a202cb2b2b269e1e4e3223ac25f7d
push id118716
push useraswan@mozilla.com
push dateMon, 13 Aug 2018 20:56:24 +0000
bugs1449055
milestone63.0a1
Bug 1449055 Convert formautofill to a webextension MozReview-Commit-ID: Cpecuks22Dz
browser/extensions/formautofill/api.js
browser/extensions/formautofill/background.js
browser/extensions/formautofill/bootstrap.js
browser/extensions/formautofill/content/editAddress.xhtml
browser/extensions/formautofill/content/editCreditCard.xhtml
browser/extensions/formautofill/install.rdf.in
browser/extensions/formautofill/jar.mn
browser/extensions/formautofill/manifest.json
browser/extensions/formautofill/moz.build
browser/extensions/formautofill/schema.json
browser/extensions/formautofill/skin/shared/autocomplete-item-shared.css
browser/extensions/formautofill/skin/shared/autocomplete-item.css
browser/extensions/formautofill/skin/shared/editDialog-shared.css
browser/extensions/formautofill/skin/shared/editDialog.css
toolkit/content/widgets.css
rename from browser/extensions/formautofill/bootstrap.js
rename to browser/extensions/formautofill/api.js
--- a/browser/extensions/formautofill/bootstrap.js
+++ b/browser/extensions/formautofill/api.js
@@ -1,25 +1,22 @@
 /* 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 */
+/* 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, "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");
@@ -45,23 +42,16 @@ function onMaybeOpenPopup(evt) {
   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")
@@ -70,90 +60,86 @@ function isAvailable() {
         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));
+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;
+    }
 
-  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);
 
-  if (data.hasOwnProperty("instanceID") && data.instanceID) {
-    if (AddonManagerPrivate.isDBLoaded()) {
-      addUpgradeListener(data.instanceID);
+    // 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 {
-      // 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");
+      Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
     }
-  } else {
-    throw Error("no instanceID passed to bootstrap startup");
+
+    // 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);
   }
 
-  // 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);
+  onShutdown() {
+    resProto.setSubstitution(RESOURCE_HOST, null);
 
-  // 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");
-  }
+    this.chromeHandle.destruct();
+    this.chromeHandle = null;
 
-  // Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
-  Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
+    Services.mm.removeMessageListener("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);
-}
-
-function shutdown() {
-  resProto.setSubstitution(RESOURCE_HOST, null);
+    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);
 
-  Services.mm.removeMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
+      if (!cachedStyleSheets) {
+        continue;
+      }
 
-  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();
+      while (cachedStyleSheets.length !== 0) {
+        cachedStyleSheets.pop().remove();
+      }
     }
   }
-}
-
-function install() {}
-function uninstall() {}
+};
new file mode 100644
--- /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.
+});
--- a/browser/extensions/formautofill/content/editAddress.xhtml
+++ b/browser/extensions/formautofill/content/editAddress.xhtml
@@ -4,19 +4,19 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!DOCTYPE html [
   <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
   %globalDTD;
 ]>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <title data-localization="addNewAddressTitle"/>
-  <link rel="stylesheet" href="chrome://formautofill-shared/skin/editDialog.css"/>
-  <link rel="stylesheet" href="chrome://formautofill-shared/skin/editAddress.css"/>
-  <link rel="stylesheet" href="chrome://formautofill/skin/editDialog.css"/>
+  <link rel="stylesheet" href="resource://formautofill/editDialog-shared.css"/>
+  <link rel="stylesheet" href="resource://formautofill/editAddress.css"/>
+  <link rel="stylesheet" href="resource://formautofill/editDialog.css"/>
   <script src="chrome://formautofill/content/l10n.js"></script>
   <script src="chrome://formautofill/content/editDialog.js"></script>
   <script src="chrome://formautofill/content/autofillEditForms.js"></script>
 </head>
 <body dir="&locale.dir;">
   <form id="form" autocomplete="off">
     <div>
       <div id="name-container">
--- a/browser/extensions/formautofill/content/editCreditCard.xhtml
+++ b/browser/extensions/formautofill/content/editCreditCard.xhtml
@@ -4,19 +4,19 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!DOCTYPE html [
   <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
   %globalDTD;
 ]>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <title data-localization="addNewCreditCardTitle"/>
-  <link rel="stylesheet" href="chrome://formautofill-shared/skin/editDialog.css"/>
-  <link rel="stylesheet" href="chrome://formautofill-shared/skin/editCreditCard.css"/>
-  <link rel="stylesheet" href="chrome://formautofill/skin/editDialog.css"/>
+  <link rel="stylesheet" href="resource://formautofill/editDialog-shared.css"/>
+  <link rel="stylesheet" href="resource://formautofill/editCreditCard.css"/>
+  <link rel="stylesheet" href="resource://formautofill/editDialog.css"/>
   <script src="chrome://formautofill/content/l10n.js"></script>
   <script src="chrome://formautofill/content/editDialog.js"></script>
   <script src="chrome://formautofill/content/autofillEditForms.js"></script>
 </head>
 <body dir="&locale.dir;">
   <form id="form" autocomplete="off">
     <label>
       <span data-localization="cardNumber"/>
--- a/browser/extensions/formautofill/jar.mn
+++ b/browser/extensions/formautofill/jar.mn
@@ -1,18 +1,11 @@
 # 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/.
 
 [features/formautofill@mozilla.org] chrome.jar:
-% resource formautofill %res/
   res/ (*.jsm)
   res/phonenumberutils/ (phonenumberutils/*.jsm)
   res/addressmetadata/ (addressmetadata/*)
-
-% content formautofill %content/
-  content/ (content/*)
+  res/ (skin/shared/*)
 
-% 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/*)
+  content/ (content/*)
rename from browser/extensions/formautofill/install.rdf.in
rename to browser/extensions/formautofill/manifest.json
--- a/browser/extensions/formautofill/install.rdf.in
+++ b/browser/extensions/formautofill/manifest.json
@@ -1,32 +1,26 @@
-<?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/. -->
+{
+  "manifest_version": 2,
+  "name": "Form Autofill",
+  "version": "1.0",
 
-#filter substitution
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+  "applications": {
+    "gecko": {
+      "id": "formautofill@mozilla.org"
+    }
+  },
 
-  <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>
+  "background": {
+    "scripts": ["background.js"]
+  },
 
-    <!-- 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>
+  "experiment_apis": {
+    "formautofill": {
+      "schema": "schema.json",
+      "parent": {
+        "scopes": ["addon_parent"],
+        "script": "api.js",
+        "events": ["startup"]
+      }
+    }
+  }
+}
--- a/browser/extensions/formautofill/moz.build
+++ b/browser/extensions/formautofill/moz.build
@@ -5,22 +5,37 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
 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']
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
 MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
 
 JAR_MANIFESTS += ['jar.mn']
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/schema.json
@@ -0,0 +1,1 @@
+[]
rename from browser/extensions/formautofill/skin/shared/autocomplete-item.css
rename to browser/extensions/formautofill/skin/shared/autocomplete-item-shared.css
rename from browser/extensions/formautofill/skin/shared/editDialog.css
rename to browser/extensions/formautofill/skin/shared/editDialog-shared.css
--- a/toolkit/content/widgets.css
+++ b/toolkit/content/widgets.css
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* ===== widgets.css =====================================================
    == Styles ported from XBL <resources>, loaded by "global.css".
    ======================================================================= */
 
 @import url("chrome://global/content/autocomplete.css");
 @import url("chrome://global/skin/autocomplete.css");
-@import url("chrome://formautofill-shared/skin/autocomplete-item.css");
-@import url("chrome://formautofill/skin/autocomplete-item.css");
+@import url("resource://formautofill/autocomplete-item-shared.css");
+@import url("resource://formautofill/autocomplete-item.css");
 @import url("chrome://global/skin/dialog.css");
 @import url("chrome://global/skin/dropmarker.css");
 @import url("chrome://global/skin/groupbox.css");
 @import url("chrome://global/skin/menu.css");
 @import url("chrome://global/skin/menulist.css");
 @import url("chrome://global/skin/notification.css");
 @import url("chrome://global/skin/popup.css");
 @import url("chrome://global/skin/progressmeter.css");