Bug 530999 - Show site favicons in login manager UI; r?MattN draft
authorJoseph Yeh <jyeh@mozilla.com>
Tue, 19 Apr 2016 14:57:21 +0800
changeset 353136 04f35282816fe855edbd7abba1c2328c91c38e63
parent 352277 1da1937a9e03154ae7c60089f2dcf5ad9ee20fa3
child 518819 8798a83a8922f834d2f598b472a6884469e30ebf
push id15876
push userbmo:jyeh@mozilla.com
push dateTue, 19 Apr 2016 07:19:09 +0000
reviewersMattN
bugs530999
milestone48.0a1
Bug 530999 - Show site favicons in login manager UI; r?MattN MozReview-Commit-ID: Lh9M3scMTwX
toolkit/components/passwordmgr/content/passwordManager.js
toolkit/components/passwordmgr/content/passwordManager.xul
toolkit/themes/osx/global/jar.mn
toolkit/themes/osx/global/passwordmgr.css
toolkit/themes/shared/jar.inc.mn
toolkit/themes/shared/non-mac.jar.inc.mn
toolkit/themes/shared/passwordmgr.css
toolkit/themes/windows/global/passwordmgr.css
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -1,15 +1,34 @@
 /* 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/. */
 
 /*** =================== SAVED SIGNONS CODE =================== ***/
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+                                  "resource://gre/modules/PlacesUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
+                                  "resource://gre/modules/DeferredTask.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "faviconStyleSheet", function() {
+  for (let i = document.styleSheets.length - 1; i >= 0; i--) {
+    let sheet = document.styleSheets[i];
+
+    if (sheet.href === "data:text/css,") {
+      return sheet;
+    }
+  }
+
+  return undefined;
+});
 
 var kSignonBundle;
 var showingPasswords = false;
 var dateFormatter = new Intl.DateTimeFormat(undefined,
                       { day: "numeric", month: "short", year: "numeric" });
 var dateAndTimeFormatter = new Intl.DateTimeFormat(undefined,
                              { day: "numeric", month: "short", year: "numeric",
                                hour: "numeric", minute: "numeric" });
@@ -39,17 +58,24 @@ function SignonsStartup() {
 }
 
 function setFilter(aFilterString) {
   document.getElementById("filter").value = aFilterString;
   _filterPasswords();
 }
 
 var signonsTreeView = {
+  // Keep track of which favicons we've appended to the favicon stylesheet.
+  _faviconSet: new Set(),
   _filterSet : [],
+  // Coalesce invalidations to avoid repeated flickering.
+  _invalidateTask: new DeferredTask(function() {
+    signonsTree.treeBoxObject.invalidate();
+    signonsTree.treeBoxObject.clearStyleAndImageCaches();
+  }, 10),
   _lastSelectedRanges : [],
   selection: null,
 
   rowCount : 0,
   setTree : function(tree) {},
   getImageSrc : function(row,column) {},
   getProgressMode : function(row,column) {},
   getCellValue : function(row,column) {},
@@ -88,20 +114,41 @@ var signonsTreeView = {
   },
   isSeparator : function(index) { return false; },
   isSorted : function() { return false; },
   isContainer : function(index) { return false; },
   cycleHeader : function(column) {},
   getRowProperties : function(row) { return ""; },
   getColumnProperties : function(column) { return ""; },
   getCellProperties : function(row,column) {
-    if (column.element.getAttribute("id") == "siteCol")
-      return "ltr";
+    if (column.element.getAttribute("id") !== "siteCol") {
+      return "";
+    }
+
+    const signon = this._filterSet.length ? this._filterSet[row] : signons[row];
+    const props = "ltr " + signon.hostname;
+
+    if (this._faviconSet.has(signon.hostname)) {
+      return props;
+    }
+
+    this._faviconSet.add(signon.hostname);
 
-    return "";
+    PlacesUtils.promiseFaviconLinkUrl(signon.hostname)
+      .then(favicon => {
+        faviconStyleSheet.insertRule(`
+          treechildren::-moz-tree-image(${CSS.escape(signon.hostname)}) {
+            list-style-image: url("moz-anno:${favicon.path}");
+          }
+        `, faviconStyleSheet.cssRules.length);
+
+        this._invalidateTask.arm();
+      }).catch(Cu.reportError);
+
+    return props;
   },
   setCellText : function(row, col, value) {
     // If there is a filter, _filterSet needs to be used, otherwise signons is used.
     let table = signonsTreeView._filterSet.length ? signonsTreeView._filterSet : signons;
     function _editLogin(field) {
       if (value == table[row][field]) {
         return;
       }
--- a/toolkit/components/passwordmgr/content/passwordManager.xul
+++ b/toolkit/components/passwordmgr/content/passwordManager.xul
@@ -1,15 +1,17 @@
 <?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil -*- -->
 # 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/.
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 <?xml-stylesheet href="chrome://global/skin/passwordmgr.css" type="text/css"?>
+<!-- This stylesheet is used to dynamically add rules for login favicons. -->
+<?xml-stylesheet href="data:text/css," type="text/css"?>
 
 <!DOCTYPE dialog SYSTEM "chrome://passwordmgr/locale/passwordManager.dtd" >
 
 <window id="SignonViewerDialog"
         windowtype="Toolkit:PasswordManager"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="Startup(); SignonsStartup();"
         onunload="Shutdown();"
--- a/toolkit/themes/osx/global/jar.mn
+++ b/toolkit/themes/osx/global/jar.mn
@@ -24,17 +24,16 @@ toolkit.jar:
   skin/classic/global/groupbox.css
   skin/classic/global/linkTree.css
   skin/classic/global/listbox.css
   skin/classic/global/menu.css
   skin/classic/global/menulist.css
 * skin/classic/global/notification.css
   skin/classic/global/netError.css
   skin/classic/global/numberbox.css
-  skin/classic/global/passwordmgr.css
   skin/classic/global/popup.css
   skin/classic/global/preferences.css
   skin/classic/global/progressmeter.css
   skin/classic/global/radio.css
   skin/classic/global/resizer.css
   skin/classic/global/richlistbox.css
   skin/classic/global/scrollbars.css                                 (nativescrollbars.css)
   skin/classic/global/scale.css
deleted file mode 100644
--- a/toolkit/themes/osx/global/passwordmgr.css
+++ /dev/null
@@ -1,13 +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/. */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-.contentPane {
-  margin: 9px 8px 5px 8px;
-}
-
-.actionButtons {
-  margin: 0px 3px 6px 3px !important;
-}
--- a/toolkit/themes/shared/jar.inc.mn
+++ b/toolkit/themes/shared/jar.inc.mn
@@ -46,9 +46,10 @@ toolkit.jar:
   skin/classic/global/in-content/dropdown.svg              (../../shared/in-content/dropdown.svg)
   skin/classic/global/in-content/help-glyph.svg            (../../shared/in-content/help-glyph.svg)
   skin/classic/global/in-content/radio.svg                 (../../shared/in-content/radio.svg)
   skin/classic/global/reader/RM-Close-24x24.svg            (../../shared/reader/RM-Close-24x24.svg)
   skin/classic/global/reader/RM-Minus-24x24.svg            (../../shared/reader/RM-Minus-24x24.svg)
   skin/classic/global/reader/RM-Plus-24x24.svg             (../../shared/reader/RM-Plus-24x24.svg)
   skin/classic/global/reader/RM-Type-Controls-24x24.svg    (../../shared/reader/RM-Type-Controls-24x24.svg)
   skin/classic/global/reader/RM-Type-Controls-Arrow.svg    (../../shared/reader/RM-Type-Controls-Arrow.svg)
+  skin/classic/global/passwordmgr.css                      (../../shared/passwordmgr.css)
 
--- a/toolkit/themes/shared/non-mac.jar.inc.mn
+++ b/toolkit/themes/shared/non-mac.jar.inc.mn
@@ -13,17 +13,16 @@
   skin/classic/global/arrow.css                            (../../windows/global/arrow.css)
   skin/classic/global/customizeToolbar.css                 (../../windows/global/customizeToolbar.css)
   skin/classic/global/datetimepicker.css                   (../../windows/global/datetimepicker.css)
   skin/classic/global/dialog.css                           (../../windows/global/dialog.css)
   skin/classic/global/expander.css                         (../../windows/global/expander.css)
   skin/classic/global/filefield.css                        (../../windows/global/filefield.css)
   skin/classic/global/globalBindings.xml                   (../../windows/global/globalBindings.xml)
   skin/classic/global/linkTree.css                         (../../windows/global/linkTree.css)
-  skin/classic/global/passwordmgr.css                      (../../windows/global/passwordmgr.css)
   skin/classic/global/progressmeter.css                    (../../windows/global/progressmeter.css)
   skin/classic/global/resizer.css                          (../../windows/global/resizer.css)
   skin/classic/global/richlistbox.css                      (../../windows/global/richlistbox.css)
   skin/classic/global/scale.css                            (../../windows/global/scale.css)
 #ifndef MOZ_THEME_FASTSTRIPE
   skin/classic/global/scrollbars.css                       (../../windows/global/xulscrollbars.css)
 #endif
   skin/classic/global/spinbuttons.css                      (../../windows/global/spinbuttons.css)
new file mode 100644
--- /dev/null
+++ b/toolkit/themes/shared/passwordmgr.css
@@ -0,0 +1,26 @@
+/* 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/. */
+
+@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+.contentPane {
+  margin: 9px 8px 5px 8px;
+}
+
+.actionButtons {
+  margin: 0px 3px 6px 3px !important;
+}
+
+treechildren::-moz-tree-image(siteCol) {
+  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
+  width: 16px;
+  height: 16px;
+  -moz-margin-end: 5px;
+}
+
+@media (min-resolution: 1.1dppx) {
+  treechildren::-moz-tree-image(siteCol) {
+    list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png");
+  }
+}
deleted file mode 100644
--- a/toolkit/themes/windows/global/passwordmgr.css
+++ /dev/null
@@ -1,13 +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/. */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-.contentPane {
-  margin: 9px 8px 5px 8px;
-}
-
-.actionButtons {
-  margin: 0px 3px 6px 3px !important;
-}