Bug 1326138 - Add a new profile item binding. r=MattN draft
authorRay Lin <ralin@mozilla.com>
Tue, 24 Jan 2017 23:32:17 +0800
changeset 484724 6f06cff951c39961dc3690797cd5e58939360445
parent 484723 88c4f611174d1db989b56924318ee5fa073aa0be
child 545839 b7b8a472b81cdeeb8c548dfac48c59f0010f40cd
push id45535
push userbmo:ralin@mozilla.com
push dateWed, 15 Feb 2017 17:06:22 +0000
reviewersMattN
bugs1326138
milestone54.0a1
Bug 1326138 - Add a new profile item binding. r=MattN MozReview-Commit-ID: KzbnQteM1pY
browser/extensions/formautofill/bootstrap.js
browser/extensions/formautofill/content/formautofill.css
browser/extensions/formautofill/content/formautofill.xml
--- a/browser/extensions/formautofill/bootstrap.js
+++ b/browser/extensions/formautofill/bootstrap.js
@@ -2,30 +2,86 @@
  * 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 {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
+const STYLESHEET_URI = "chrome://formautofill/content/formautofill.css";
+const CACHED_STYLESHEETS = new WeakMap();
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FormAutofillParent",
                                   "resource://formautofill/FormAutofillParent.jsm");
 
+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]);
+  }
+}
+
+let windowListener = {
+  onOpenWindow(aWindow) {
+    let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+
+    domWindow.addEventListener("load", function onWindowLoaded() {
+      insertStyleSheet(domWindow, STYLESHEET_URI);
+    }, {once: true});
+  },
+};
+
 function startup() {
   // Besides this pref, we'll need dom.forms.autocomplete.experimental enabled
   // as well to make sure form autocomplete works correctly.
   if (!Services.prefs.getBoolPref("browser.formautofill.experimental")) {
     return;
   }
 
   let parent = new FormAutofillParent();
+  let enumerator = Services.wm.getEnumerator("navigator:browser");
+  // Load stylesheet to already opened windows
+  while (enumerator.hasMoreElements()) {
+    let win = enumerator.getNext();
+    let domWindow = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+
+    insertStyleSheet(domWindow, STYLESHEET_URI);
+  }
+
+  Services.wm.addListener(windowListener);
+
   parent.init();
   Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true);
 }
 
-function shutdown() {}
+function shutdown() {
+  Services.wm.removeListener(windowListener);
+
+  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() {}
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/content/formautofill.css
@@ -0,0 +1,7 @@
+/* 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/. */
+
+.autocomplete-richlistitem[originaltype="autofill-profile"] {
+  -moz-binding: url("chrome://formautofill/content/formautofill.xml#autocomplete-profile-listitem");
+}
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/content/formautofill.xml
@@ -0,0 +1,79 @@
+<?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/. -->
+
+<bindings id="formautofillBindings"
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:html="http://www.w3.org/1999/xhtml"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
+
+  <binding id="autocomplete-profile-listitem" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
+    <xbl:content xmlns="http://www.w3.org/1999/xhtml">
+      <div anonid="profile-item-box" class="profile-item-box">
+        <div class="profile-label-col profile-item-col">
+          <span anonid="profile-label" class="profile-label"></span>
+        </div>
+        <div class="profile-comment-col profile-item-col">
+          <span anonid="profile-comment" class="profile-comment"></span>
+        </div>
+      </div>
+    </xbl:content>
+
+    <implementation implements="nsIDOMXULSelectControlItemElement">
+      <constructor>
+        <![CDATA[
+          this._itemBox = document.getAnonymousElementByAttribute(
+            this, "anonid", "profile-item-box"
+          );
+          this._label = document.getAnonymousElementByAttribute(
+            this, "anonid", "profile-label"
+          );
+          this._comment = document.getAnonymousElementByAttribute(
+            this, "anonid", "profile-comment"
+          );
+
+          this._adjustAcItem();
+        ]]>
+      </constructor>
+
+      <method name="_cleanup">
+        <body>
+        <![CDATA[
+            this._itemBox.removeAttribute("size");
+        ]]>
+        </body>
+      </method>
+
+      <method name="_onOverflow">
+        <body></body>
+      </method>
+
+      <method name="_onUnderflow">
+        <body></body>
+      </method>
+
+      <method name="_adjustAcItem">
+        <body>
+        <![CDATA[
+          let outerBoxRect = this.parentNode.getBoundingClientRect();
+          let value = this.getAttribute("ac-value");
+          let comment = this.getAttribute("ac-comment");
+
+          this._comment.textContent = comment;
+          this._label.textContent = value;
+
+          // Use two-lines layout when width is smaller than 150px
+          if (outerBoxRect.width <= 150) {
+            this._itemBox.setAttribute("size", "small");
+          } else {
+            this._itemBox.removeAttribute("size");
+          }
+        ]]>
+        </body>
+      </method>
+    </implementation>
+  </binding>
+
+</bindings>