Bug 1326138 - Add a new profile item binding. r=MattN
MozReview-Commit-ID: KzbnQteM1pY
--- 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>