Merge mozilla-central to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 19 Mar 2015 14:10:09 +0100
changeset 234468 661d70e3289993ed2f6477cd5847ab99d9998177
parent 234467 eb6141f8f3a342096e162c17381dec1e22426372 (current diff)
parent 234403 cbd0efcd976c6fa677637d565d948296684441de (diff)
child 234469 c4a67c3317276abea4da080b71c422eea97e3343
push id28446
push userkwierso@gmail.com
push dateFri, 20 Mar 2015 02:15:45 +0000
treeherdermozilla-central@3257d9c4b257 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound
browser/themes/shared/readinglist/sidebar.css
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -2997,17 +2997,17 @@
         ]]></setter>
       </property>
       <property name="_notificationType">
         <getter><![CDATA[
           // Use the popupid attribute to identify the notification type,
           // otherwise just rely on the panel id for common arrowpanels.
           let type = this._panel.firstChild.getAttribute("popupid") ||
                      this._panel.id;
-          if (type.startsWith("password-"))
+          if (type == "password")
             return "passwords";
           if (type == "editBookmarkPanel")
             return "bookmarks";
           if (type == "addon-install-complete") {
             if (!Services.prefs.prefHasUserValue("services.sync.username"))
               return "addons";
             if (!Services.prefs.getBoolPref("services.sync.engine.addons"))
               return "addons-sync-disabled";
--- a/browser/components/readinglist/sidebar.js
+++ b/browser/components/readinglist/sidebar.js
@@ -49,16 +49,17 @@ let RLSidebar = {
    * Initialize the sidebar UI.
    */
   init() {
     log.debug("Initializing");
 
     addEventListener("unload", () => this.uninit());
 
     this.list = document.getElementById("list");
+    this.emptyListInfo = document.getElementById("emptyListInfo");
     this.itemTemplate = document.getElementById("item-template");
 
     this.list.addEventListener("click", event => this.onListClick(event));
     this.list.addEventListener("mousemove", event => this.onListMouseMove(event));
     this.list.addEventListener("keydown", event => this.onListKeyDown(event), true);
 
     this.listPromise = this.ensureListItems();
     ReadingList.addListener(this);
@@ -86,31 +87,35 @@ let RLSidebar = {
   onItemAdded(item) {
     log.trace(`onItemAdded: ${item}`);
 
     let itemNode = document.importNode(this.itemTemplate.content, true).firstElementChild;
     this.updateItem(item, itemNode);
     this.list.appendChild(itemNode);
     this.itemNodesById.set(item.id, itemNode);
     this.itemsById.set(item.id, item);
+
+    this.emptyListInfo.hidden = true;
   },
 
   /**
    * Handle an item being deleted from the ReadingList.
    * @param {ReadingListItem} item - Item that was deleted.
    */
   onItemDeleted(item) {
     log.trace(`onItemDeleted: ${item}`);
 
     let itemNode = this.itemNodesById.get(item.id);
     itemNode.remove();
     this.itemNodesById.delete(item.id);
     this.itemsById.delete(item.id);
     // TODO: ensureListItems doesn't yet cope with needing to add one item.
     //this.ensureListItems();
+
+    this.emptyListInfo.hidden = (this.numItems > 0);
   },
 
   /**
    * Handle an item in the ReadingList having any of its properties changed.
    * @param {ReadingListItem} item - Item that was updated.
    */
   onItemUpdated(item) {
     log.trace(`onItemUpdated: ${item}`);
@@ -143,16 +148,17 @@ let RLSidebar = {
     yield ReadingList.forEachItem(item => {
       // TODO: Should be batch inserting via DocumentFragment
       try {
         this.onItemAdded(item);
       } catch (e) {
         log.warn("Error adding item", e);
       }
     });
+    this.emptyListInfo.hidden = (this.numItems > 0);
   }),
 
   /**
    * Get the number of items currently displayed in the list.
    * @type {number}
    */
   get numItems() {
     return this.list.childElementCount;
@@ -345,16 +351,21 @@ let RLSidebar = {
    * Handle a click event on the list box.
    * @param {Event} event - Triggering event.
    */
   onListClick(event) {
     let itemNode = this.findParentItemNode(event.target);
     if (!itemNode)
       return;
 
+    if (event.target.classList.contains("remove-button")) {
+      ReadingList.deleteItem(this.getItemFromNode(itemNode));
+      return;
+    }
+
     this.activeItem = itemNode;
     this.openActiveItem(event);
   },
 
   /**
    * Handle a mousemove event over the list box.
    * @param {Event} event - Triggering event.
    */
--- a/browser/components/readinglist/sidebar.xhtml
+++ b/browser/components/readinglist/sidebar.xhtml
@@ -6,25 +6,29 @@
 <!DOCTYPE html [
   <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
   %browserDTD;
 ]>
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <script src="chrome://browser/content/readinglist/sidebar.js" type="application/javascript;version=1.8"></script>
     <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/readinglist/sidebar.css"/>
-    <!-- <title>&readingList.label;</title> -->
+    <title>&readingList.label;</title>
   </head>
 
   <body role="application">
     <template id="item-template">
       <div class="item" role="option" tabindex="-1">
         <div class="item-thumb-container"></div>
         <div class="item-summary-container">
-          <div class="item-title"></div>
+          <div class="item-title-lines">
+            <p class="item-title"/>
+            <button class="remove-button" title="&readingList.sidebar.delete.tooltip;"/>
+          </div>
           <div class="item-domain"></div>
         </div>
       </div>
     </template>
 
+    <div id="emptyListInfo" hidden="true">&readingList.sidebar.emptyText;</div>
     <div id="list" role="listbox" tabindex="1"></div>
   </body>
 </html>
--- a/browser/devtools/webide/content/wifi-auth.js
+++ b/browser/devtools/webide/content/wifi-auth.js
@@ -4,18 +4,16 @@
 
 "use strict";
 
 const Cu = Components.utils;
 const { Services } = Cu.import("resource://gre/modules/Services.jsm");
 const { require } =
   Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
 const QR = require("devtools/toolkit/qrcode/index");
-const PROPERTIES = "chrome://browser/locale/devtools/webide.properties";
-const Strings = Services.strings.createBundle(PROPERTIES);
 
 window.addEventListener("load", function onLoad() {
   window.removeEventListener("load", onLoad);
   document.getElementById("close").onclick = () => window.close();
   document.getElementById("no-scanner").onclick = showToken;
   document.getElementById("yes-scanner").onclick = hideToken;
   buildUI();
 });
@@ -28,20 +26,16 @@ function buildUI() {
 
 function createQR(oob) {
   let oobData = JSON.stringify(oob);
   let imgData = QR.encodeToDataURI(oobData, "L" /* low quality */);
   document.querySelector("#qr-code img").src = imgData.src;
 }
 
 function createToken(oob) {
-  let spacedCert = oob.sha256.replace(/:/g, " ").toLowerCase();
-  let certText = Strings.formatStringFromName("wifi_auth_cert",
-                                              [spacedCert], 1);
-  document.querySelector("#cert").textContent = certText;
   let token = oob.sha256.replace(/:/g, "").toLowerCase() + oob.k;
   document.querySelector("#token pre").textContent = token;
 }
 
 function showToken() {
   document.querySelector("body").setAttribute("token", "true");
 }
 
--- a/browser/devtools/webide/content/wifi-auth.xhtml
+++ b/browser/devtools/webide/content/wifi-auth.xhtml
@@ -19,17 +19,16 @@
   <body>
 
     <div id="controls">
       <a id="close">&deck_close;</a>
     </div>
 
     <h3 id="header">&wifi_auth_header;</h3>
     <div id="scan-request">&wifi_auth_scan_request;</div>
-    <div id="cert"></div>
 
     <div id="qr-code">
       <div id="qr-code-wrapper">
         <img/>
       </div>
       <a id="no-scanner" class="toggle-scanner">&wifi_auth_no_scanner;</a>
     </div>
 
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -848,13 +848,12 @@ just addresses the organization to follo
 
 <!ENTITY readingList.label                        "Reading List">
 <!ENTITY readingList.sidebar.commandKey           "R">
 <!ENTITY readingList.showSidebar.label            "Show Reading List Sidebar">
 <!-- Pre-landed string for bug 1124153 -->
 <!ENTITY readingList.sidebar.showMore.label       "Show moreā€¦">
 <!-- Pre-landed string for bug 1133662 -->
 <!ENTITY readingList.sidebar.emptyText            "Add articles to your Reading List to save them for later and find them easily when you need them.">
-<!-- Pre-landed string for bug 1123525 -->
 <!ENTITY readingList.sidebar.delete.tooltip       "Remove this from your Reading List">
 <!-- Pre-landed strings for bug 1123519 -->
 <!ENTITY readingList.sidebar.add.label            "Add to Reading List">
 <!ENTITY readingList.sidebar.add.tooltip          "Add this page to your Reading List">
--- a/browser/locales/en-US/chrome/browser/devtools/webide.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/webide.properties
@@ -72,14 +72,8 @@ runtimedetails_notUSBDevice=Not a USB de
 status_tooltip=Validation status: %1$S
 status_valid=VALID
 status_warning=WARNINGS
 status_error=ERRORS
 status_unknown=UNKNOWN
 
 # Device preferences and settings
 device_reset_default=Reset to default
-
-# WiFi Auth
-# LOCALIZATION NOTE (wifi_auth_cert): Part of the dialog that instructs the
-# user to transfer an authentication token to the server.
-# %1$S: The client's cert fingerprint
-wifi_auth_cert=My Cert: %1$S
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1190,18 +1190,17 @@ toolbarbutton[sdk-button="true"][cui-are
 }
 
 .popup-notification-icon[popupid="indexedDB-permissions-prompt"],
 .popup-notification-icon[popupid*="offline-app-requested"],
 .popup-notification-icon[popupid="offline-app-usage"] {
   list-style-image: url(chrome://global/skin/icons/question-64.png);
 }
 
-.popup-notification-icon[popupid="password-save"],
-.popup-notification-icon[popupid="password-change"] {
+.popup-notification-icon[popupid="password"] {
   list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
 }
 
 .popup-notification-icon[popupid="webapps-install-progress"],
 .popup-notification-icon[popupid="webapps-install"] {
   list-style-image: url(chrome://global/skin/icons/webapps-64.png);
 }
 
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -88,17 +88,17 @@ browser.jar:
   skin/classic/browser/undoCloseTab.png                        (../shared/undoCloseTab.png)
   skin/classic/browser/urlbar-arrow.png
   skin/classic/browser/session-restore.svg                  (../shared/incontent-icons/session-restore.svg)
   skin/classic/browser/tab-crashed.svg                      (../shared/incontent-icons/tab-crashed.svg)
   skin/classic/browser/welcome-back.svg                     (../shared/incontent-icons/welcome-back.svg)
   skin/classic/browser/reader-mode-16.png             (../shared/reader/reader-mode-16.png)
   skin/classic/browser/readinglist/icons.svg          (../shared/readinglist/icons.svg)
   skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
-  skin/classic/browser/readinglist/sidebar.css        (../shared/readinglist/sidebar.css)
+* skin/classic/browser/readinglist/sidebar.css        (readinglist/sidebar.css)
   skin/classic/browser/webRTC-shareDevice-16.png
   skin/classic/browser/webRTC-shareDevice-64.png
   skin/classic/browser/webRTC-sharingDevice-16.png    (../shared/webrtc/webRTC-sharingDevice-16.png)
   skin/classic/browser/webRTC-shareMicrophone-16.png
   skin/classic/browser/webRTC-shareMicrophone-64.png
   skin/classic/browser/webRTC-sharingMicrophone-16.png (../shared/webrtc/webRTC-sharingMicrophone-16.png)
   skin/classic/browser/webRTC-shareScreen-16.png      (../shared/webrtc/webRTC-shareScreen-16.png)
   skin/classic/browser/webRTC-shareScreen-64.png      (../shared/webrtc/webRTC-shareScreen-64.png)
new file mode 100644
--- /dev/null
+++ b/browser/themes/linux/readinglist/sidebar.css
@@ -0,0 +1,29 @@
+/* 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/. */
+
+%include ../../shared/readinglist/sidebar.inc.css
+
+.item {
+  -moz-padding-end: 0;
+}
+
+.item-title {
+  margin: 1px 0 0;
+}
+
+.item-title, .item-domain {
+  -moz-margin-end: 6px;
+}
+
+.remove-button {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 16, 16, 0);
+}
+
+.remove-button:hover {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 32, 16, 16);
+}
+
+.remove-button:hover:active {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 48, 16, 32);
+}
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -4215,18 +4215,17 @@ notification[value="loop-sharing-notific
 }
 
 .popup-notification-icon[popupid="indexedDB-permissions-prompt"],
 .popup-notification-icon[popupid*="offline-app-requested"],
 .popup-notification-icon[popupid="offline-app-usage"] {
   list-style-image: url(chrome://global/skin/icons/question-64.png);
 }
 
-.popup-notification-icon[popupid="password-save"],
-.popup-notification-icon[popupid="password-change"] {
+.popup-notification-icon[popupid="password"] {
   list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
 }
 
 .popup-notification-icon[popupid="webapps-install-progress"],
 .popup-notification-icon[popupid="webapps-install"] {
   list-style-image: url(chrome://global/skin/icons/webapps-64.png);
 }
 
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -139,17 +139,17 @@ browser.jar:
   skin/classic/browser/urlbar-popup-blocked@2x.png
   skin/classic/browser/session-restore.svg            (../shared/incontent-icons/session-restore.svg)
   skin/classic/browser/tab-crashed.svg                (../shared/incontent-icons/tab-crashed.svg)
   skin/classic/browser/welcome-back.svg               (../shared/incontent-icons/welcome-back.svg)
   skin/classic/browser/reader-mode-16.png             (../shared/reader/reader-mode-16.png)
   skin/classic/browser/reader-mode-16@2x.png          (../shared/reader/reader-mode-16@2x.png)
   skin/classic/browser/readinglist/icons.svg          (../shared/readinglist/icons.svg)
   skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
-  skin/classic/browser/readinglist/sidebar.css        (../shared/readinglist/sidebar.css)
+* skin/classic/browser/readinglist/sidebar.css        (readinglist/sidebar.css)
   skin/classic/browser/webRTC-shareDevice-16.png
   skin/classic/browser/webRTC-shareDevice-16@2x.png
   skin/classic/browser/webRTC-shareDevice-64.png
   skin/classic/browser/webRTC-shareDevice-64@2x.png
   skin/classic/browser/webRTC-sharingDevice-16.png    (../shared/webrtc/webRTC-sharingDevice-16.png)
   skin/classic/browser/webRTC-sharingDevice-16@2x.png (../shared/webrtc/webRTC-sharingDevice-16@2x.png)
   skin/classic/browser/webRTC-shareMicrophone-16.png
   skin/classic/browser/webRTC-shareMicrophone-16@2x.png
new file mode 100644
--- /dev/null
+++ b/browser/themes/osx/readinglist/sidebar.css
@@ -0,0 +1,35 @@
+/* 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/. */
+
+%include ../../shared/readinglist/sidebar.inc.css
+
+.item-title {
+  margin: 4px 0 0;
+}
+
+.remove-button {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 16, 16, 0);
+}
+
+.remove-button:hover {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 32, 16, 16);
+}
+
+.remove-button:hover:active {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 48, 16, 32);
+}
+
+@media (min-resolution: 2dppx) {
+  .remove-button {
+    background-image: -moz-image-rect(url("chrome://global/skin/icons/close@2x.png"), 0, 32, 32, 0);
+  }
+
+  .remove-button:hover {
+    background-image: -moz-image-rect(url("chrome://global/skin/icons/close@2x.png"), 0, 64, 32, 32);
+  }
+
+  .remove-button:hover:active {
+    background-image: -moz-image-rect(url("chrome://global/skin/icons/close@2x.png"), 0, 96, 32, 64);
+  }
+}
rename from browser/themes/shared/readinglist/sidebar.css
rename to browser/themes/shared/readinglist/sidebar.inc.css
--- a/browser/themes/shared/readinglist/sidebar.css
+++ b/browser/themes/shared/readinglist/sidebar.inc.css
@@ -1,26 +1,32 @@
-/* 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/. */
+% 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/.
 
 :root, body {
   height: 100%;
   overflow-x: hidden;
 }
 
 body {
   margin: 0;
   font: message-box;
   background: #F8F7F8;
   color: #333333;
   -moz-user-select: none;
   overflow: hidden;
 }
 
+#emptyListInfo {
+  cursor: default;
+  padding: 3em 1em;
+  text-align: center;
+}
+
 #list {
   height: 100%;
   overflow-x: auto;
 }
 
 .item {
   display: flex;
   flex-flow: row;
@@ -47,26 +53,46 @@ body {
   margin: 5px;
 }
 
 .item-summary-container {
   display: flex;
   flex-flow: column;
   -moz-padding-start: 4px;
   overflow: hidden;
+  flex-grow: 1;
+}
+
+.item-title-lines {
+  display: flex;
 }
 
 .item-title {
   overflow: hidden;
-  height: 2.8em;
+  max-height: 2.8em;
+  line-height: 1.4;
+  flex-grow: 1;
 }
 
 .item-domain {
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
   max-height: 1.4em;
   color: #0095DD;
 }
 
 .item:hover .item-domain {
   color: #008ACB;
 }
+
+.item:not(:hover) .remove-button {
+  display: none;
+}
+
+.remove-button {
+  width: 16px;
+  height: 16px;
+  background-size: contain;
+  background-color: transparent;
+  border-width: 0;
+}
+
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2212,18 +2212,17 @@ toolbarbutton.bookmark-item[dragover="tr
 }
 
 .popup-notification-icon[popupid="indexedDB-permissions-prompt"],
 .popup-notification-icon[popupid*="offline-app-requested"],
 .popup-notification-icon[popupid="offline-app-usage"] {
   list-style-image: url(chrome://global/skin/icons/question-64.png);
 }
 
-.popup-notification-icon[popupid="password-save"],
-.popup-notification-icon[popupid="password-change"] {
+.popup-notification-icon[popupid="password"] {
   list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
 }
 
 .popup-notification-icon[popupid="webapps-install-progress"],
 .popup-notification-icon[popupid="webapps-install"] {
   list-style-image: url(chrome://global/skin/icons/webapps-64.png);
 }
 
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -107,17 +107,17 @@ browser.jar:
         skin/classic/browser/urlbar-popup-blocked.png
         skin/classic/browser/urlbar-history-dropmarker.png
         skin/classic/browser/session-restore.svg                     (../shared/incontent-icons/session-restore.svg)
         skin/classic/browser/tab-crashed.svg                         (../shared/incontent-icons/tab-crashed.svg)
         skin/classic/browser/welcome-back.svg                        (../shared/incontent-icons/welcome-back.svg)
         skin/classic/browser/reader-mode-16.png                      (../shared/reader/reader-mode-16.png)
         skin/classic/browser/readinglist/icons.svg                   (../shared/readinglist/icons.svg)
         skin/classic/browser/readinglist/readinglist-icon.svg        (../shared/readinglist/readinglist-icon.svg)
-        skin/classic/browser/readinglist/sidebar.css                 (../shared/readinglist/sidebar.css)
+*       skin/classic/browser/readinglist/sidebar.css                 (readinglist/sidebar.css)
         skin/classic/browser/notification-pluginNormal.png           (../shared/plugins/notification-pluginNormal.png)
         skin/classic/browser/notification-pluginAlert.png            (../shared/plugins/notification-pluginAlert.png)
         skin/classic/browser/notification-pluginBlocked.png          (../shared/plugins/notification-pluginBlocked.png)
         skin/classic/browser/webRTC-shareDevice-16.png
         skin/classic/browser/webRTC-shareDevice-64.png
         skin/classic/browser/webRTC-sharingDevice-16.png             (../shared/webrtc/webRTC-sharingDevice-16.png)
         skin/classic/browser/webRTC-shareMicrophone-16.png
         skin/classic/browser/webRTC-shareMicrophone-64.png
@@ -579,17 +579,17 @@ browser.jar:
         skin/classic/aero/browser/urlbar-popup-blocked.png
         skin/classic/aero/browser/urlbar-history-dropmarker.png
         skin/classic/aero/browser/session-restore.svg               (../shared/incontent-icons/session-restore.svg)
         skin/classic/aero/browser/tab-crashed.svg                   (../shared/incontent-icons/tab-crashed.svg)
         skin/classic/aero/browser/welcome-back.svg                  (../shared/incontent-icons/welcome-back.svg)
         skin/classic/aero/browser/reader-mode-16.png                (../shared/reader/reader-mode-16.png)
         skin/classic/aero/browser/readinglist/icons.svg             (../shared/readinglist/icons.svg)
         skin/classic/aero/browser/readinglist/readinglist-icon.svg  (../shared/readinglist/readinglist-icon.svg)
-        skin/classic/aero/browser/readinglist/sidebar.css           (../shared/readinglist/sidebar.css)
+*       skin/classic/aero/browser/readinglist/sidebar.css           (readinglist/sidebar.css)
         skin/classic/aero/browser/notification-pluginNormal.png     (../shared/plugins/notification-pluginNormal.png)
         skin/classic/aero/browser/notification-pluginAlert.png      (../shared/plugins/notification-pluginAlert.png)
         skin/classic/aero/browser/notification-pluginBlocked.png    (../shared/plugins/notification-pluginBlocked.png)
         skin/classic/aero/browser/webRTC-shareDevice-16.png
         skin/classic/aero/browser/webRTC-shareDevice-64.png
         skin/classic/aero/browser/webRTC-sharingDevice-16.png             (../shared/webrtc/webRTC-sharingDevice-16.png)
         skin/classic/aero/browser/webRTC-shareMicrophone-16.png
         skin/classic/aero/browser/webRTC-shareMicrophone-64.png
new file mode 100644
--- /dev/null
+++ b/browser/themes/windows/readinglist/sidebar.css
@@ -0,0 +1,30 @@
+/* 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/. */
+
+%include ../../shared/readinglist/sidebar.inc.css
+
+.item {
+  -moz-padding-end: 0;
+}
+
+.item-title {
+  margin: 1px 0 0;
+}
+
+.item-title, .item-domain {
+  -moz-margin-end: 6px;
+}
+
+.remove-button {
+  -moz-margin-end: 2px;
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 16, 16, 0);
+}
+
+.remove-button:hover {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 32, 16, 16);
+}
+
+.remove-button:hover:active {
+  background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 48, 16, 32);
+}
--- a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
+++ b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
@@ -849,20 +849,22 @@ LoginManagerPrompter.prototype = {
             pwmgr.setLoginSavingEnabled(aLogin.hostname, false);
             browser.focus();
           }
         }
       ];
 
       var { browser } = this._getNotifyWindow();
 
-      aNotifyObj.show(browser, "password-save", notificationText,
+      aNotifyObj.show(browser, "password", notificationText,
                       "password-notification-icon", mainAction,
-                      secondaryActions, { timeout: Date.now() + 10000,
-                                          persistWhileVisible: true });
+                      secondaryActions,
+                      { timeout: Date.now() + 10000,
+                        persistWhileVisible: true,
+                        passwordNotificationType: "password-save" });
     } else {
       var notNowButtonText =
             this._getLocalizedString("notifyBarNotNowButtonText");
       var notNowButtonAccessKey =
             this._getLocalizedString("notifyBarNotNowButtonAccessKey");
       var buttons = [
         // "Remember" button
         {
@@ -901,17 +903,17 @@ LoginManagerPrompter.prototype = {
 
   /*
    * _removeLoginNotifications
    *
    */
   _removeLoginNotifications : function () {
     var popupNote = this._getPopupNote();
     if (popupNote)
-      popupNote = popupNote.getNotification("password-save");
+      popupNote = popupNote.getNotification("password");
     if (popupNote)
       popupNote.remove();
 
     var notifyBox = this._getNotifyBox();
     if (notifyBox) {
       var oldBar = notifyBox.getNotificationWithValue("password-save");
       if (oldBar) {
         this.log("Removing save-password notification bar.");
@@ -1047,20 +1049,21 @@ LoginManagerPrompter.prototype = {
           self._updateLogin(aOldLogin, aNewPassword);
           promptHistogram.add(PROMPT_UPDATE);
         }
       };
 
       var { browser } = this._getNotifyWindow();
 
       Services.telemetry.getHistogramById("PWMGR_PROMPT_UPDATE_ACTION").add(PROMPT_DISPLAYED);
-      aNotifyObj.show(browser, "password-change", notificationText,
+      aNotifyObj.show(browser, "password", notificationText,
                       "password-notification-icon", mainAction,
                       null, { timeout: Date.now() + 10000,
-                              persistWhileVisible: true });
+                              persistWhileVisible: true,
+                              passwordNotificationType: "password-change" });
     } else {
       var dontChangeButtonText =
             this._getLocalizedString("notifyBarDontChangeButtonText");
       var dontChangeButtonAccessKey =
             this._getLocalizedString("notifyBarDontChangeButtonAccessKey");
       var buttons = [
         // "Yes" button
         {
--- a/toolkit/components/passwordmgr/test/browser/browser.ini
+++ b/toolkit/components/passwordmgr/test/browser/browser.ini
@@ -1,10 +1,12 @@
 [DEFAULT]
 support-files =
   authenticate.sjs
+  form_basic.html
 
+[browser_notifications.js]
 [browser_passwordmgr_fields.js]
 [browser_passwordmgr_observers.js]
 [browser_passwordmgr_sort.js]
 [browser_passwordmgr_switchtab.js]
 [browser_passwordmgrcopypwd.js]
 [browser_passwordmgrdlg.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/browser/browser_notifications.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(function* test_save() {
+  let tab = gBrowser.addTab("https://example.com/browser/toolkit/components/" +
+                            "passwordmgr/test/browser/form_basic.html");
+  let browser = tab.linkedBrowser;
+  yield BrowserTestUtils.browserLoaded(browser);
+  gBrowser.selectedTab = tab;
+
+  let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
+                                                   "Shown");
+  yield ContentTask.spawn(browser, null, function* () {
+    content.document.getElementById("form-basic-username").value = "username";
+    content.document.getElementById("form-basic-password").value = "password";
+    content.document.getElementById("form-basic").submit();
+  });
+  yield promiseShown;
+  let notificationElement = PopupNotifications.panel.childNodes[0];
+
+  let promiseLogin = TestUtils.topicObserved("passwordmgr-storage-changed",
+                                             (_, data) => data == "addLogin");
+  notificationElement.button.doCommand();
+  let [login] = yield promiseLogin;
+  login.QueryInterface(Ci.nsILoginInfo);
+
+  Assert.equal(login.username, "username");
+  Assert.equal(login.password, "password");
+
+  // Cleanup.
+  Services.logins.removeAllLogins();
+  gBrowser.removeTab(tab);
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/browser/form_basic.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+
+<!-- Simplest form with username and password fields. -->
+<form id="form-basic">
+  <input id="form-basic-username" name="username">
+  <input id="form-basic-password" name="password" type="password">
+  <input id="form-basic-submit" type="submit">
+</form>
+
+</body></html>
--- a/toolkit/components/passwordmgr/test/notification_common.js
+++ b/toolkit/components/passwordmgr/test/notification_common.js
@@ -34,17 +34,21 @@ function getPopupNotifications(aWindow) 
 
 
 /*
  * getPopup
  *
  */
 function getPopup(aPopupNote, aKind) {
     ok(true, "Looking for " + aKind + " popup notification");
-    return aPopupNote.getNotification(aKind);
+    var notification = aPopupNote.getNotification("password");
+    if (notification) {
+      is(notification.options.passwordNotificationType, aKind);
+    }
+    return notification;
 }
 
 
 /*
  * clickPopupButton
  *
  * Clicks the specified popup notification button.
  */
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -639,16 +639,19 @@ PopupNotifications.prototype = {
       notificationsToShow.forEach(function (n) {
         // Remember the time the notification was shown for the security delay.
         n.timeShown = this.window.performance.now();
       }, this);
       this.panel.openPopup(anchorElement, "bottomcenter topleft");
       notificationsToShow.forEach(function (n) {
         this._fireCallback(n, NOTIFICATION_EVENT_SHOWN);
       }, this);
+      // This notification is used by tests to know when all the processing
+      // required to display the panel has happened.
+      this.panel.dispatchEvent(new this.window.CustomEvent("Shown"));
     });
   },
 
   /**
    * Updates the notification state in response to window activation or tab
    * selection changes.
    *
    * @param notifications an array of Notification instances. if null,
--- a/toolkit/mozapps/update/tests/TestAUSHelper.cpp
+++ b/toolkit/mozapps/update/tests/TestAUSHelper.cpp
@@ -94,38 +94,47 @@ CheckMsg(const NS_tchar *path, const cha
 
   FILE *inFP = NS_tfopen(path, NS_T("rb"));
   if (!inFP) {
     return false;
   }
 
   struct stat ms;
   if (fstat(fileno(inFP), &ms)) {
+    fclose(inFP);
+    inFP = nullptr;
     return false;
   }
 
   char *mbuf = (char *) malloc(ms.st_size + 1);
   if (!mbuf) {
+    fclose(inFP);
+    inFP = nullptr;
     return false;
   }
 
   size_t r = ms.st_size;
   char *rb = mbuf;
   size_t c = fread(rb, sizeof(char), 50, inFP);
   r -= c;
   rb += c;
   if (c == 0 && r) {
+    free(mbuf);
+    fclose(inFP);
+    inFP = nullptr;
     return false;
   }
   mbuf[ms.st_size] = '\0';
   rb = mbuf;
 
+  bool isMatch = strcmp(rb, expected) == 0;
+  free(mbuf);
   fclose(inFP);
   inFP = nullptr;
-  return strcmp(rb, expected) == 0;
+  return isMatch;
 }
 
 #ifdef XP_WIN
 /**
  * Verifies the trust of the specified file path.
  *
  * @param  filePath  The file path to check.
  * @return ERROR_SUCCESS if successful, or the last error code otherwise.
--- a/toolkit/themes/windows/global/aboutReader.css
+++ b/toolkit/themes/windows/global/aboutReader.css
@@ -23,21 +23,21 @@ body {
 
 .sepia,
 .sepia-button {
   color: #333333;
   background-color: #f0ece7;
 }
 
 .sans-serif {
-  font-family: sans-serif;
+  font-family: "Fira Sans", Helvetica, Arial, sans-serif;
 }
 
 .serif {
-  font-family: serif;
+  font-family: "Charis SIL", Georgia, "Times New Roman", serif;
 }
 
 .font-size1 {
   font-size: 10px;
 }
 
 .font-size2 {
   font-size: 12px;
@@ -88,17 +88,17 @@ body {
   text-align: start;
   display: none;
 }
 
 .domain {
   font-size: 0.9rem;
   line-height: 1.33rem;
   padding-bottom: 4px;
-  font-family: sans-serif;
+  font-family: "Fira Sans", Helvetica, Arial, sans-serif;
   text-decoration: none;
   border-bottom: 1px solid;
   color: #0095dd;
 }
 
 .light > .container > .header > .domain,
 .sepia > .container > .header > .domain {
   border-bottom-color: #333333;
@@ -226,17 +226,17 @@ body {
 .content ol {
   -moz-padding-start: 30px;
   list-style: decimal;
 }
 
 /*======= Controls toolbar =======*/
 
 .toolbar {
-  font-family: sans-serif;
+  font-family: "Fira Sans", Helvetica, Arial, sans-serif;
   position: fixed;
   height: 100%;
   top: 0px;
   left: 0px;
   margin: 0;
   padding: 0;
   list-style: none;
   background-color: #FBFBFB;
@@ -281,17 +281,17 @@ body {
   min-width: 250px;
   text-align: start;
   position: absolute;
   left: 48px; /* offset to account for toolbar width */
   z-index: 1000;
   background-color: #FBFBFB;
   visibility: hidden;
   border-radius: 4px;
-  border: 1px solid #B5B5B5;
+  border: 1px 1px 0 1px solid #B5B5B5;
   box-shadow: 0px 1px 12px #666;
 }
 
 .dropdown-popup > hr {
   width: 100%;
   height: 0px;
   border: 0px;
   border-top: 1px solid #B5B5B5;
@@ -314,16 +314,29 @@ body {
 
 #font-type-buttons,
 #font-size-buttons,
 #color-scheme-buttons {
   display: flex;
   flex-direction: row;
 }
 
+#font-type-buttons > button:first-child {
+  border-top-left-radius: 3px;
+}
+#font-type-buttons > button:last-child {
+  border-top-right-radius: 3px;
+}
+#color-scheme-buttons > button:first-child {
+  border-bottom-left-radius: 3px;
+}
+#color-scheme-buttons > button:last-child {
+  border-bottom-right-radius: 3px;
+}
+
 #font-type-buttons > button,
 #font-size-buttons > button,
 #color-scheme-buttons > button {
   text-align: center;
   border-left: 1px solid #B5B5B5;
   border-right: 0;
   border-top: 0;
   border-bottom: 0;
@@ -332,61 +345,63 @@ body {
 
 #font-type-buttons > button,
 #font-size-buttons > button {
   width: 50%;
   background-color: transparent;
 }
 
 #color-scheme-buttons > button {
-  width: 33%;
+  width: 33.33%;
   font-size: 14px;
 }
 
 #font-type-buttons > button:first-child,
 #font-size-buttons > button:first-child,
 #color-scheme-buttons > button:first-child {
   border-left: 0px;
 }
 
 #font-type-buttons > button {
   display: inline-block;
   font-size: 48px;
-  border-bottom: 3px solid transparent;
 }
 
 #font-type-buttons > button:active:hover,
-#font-type-buttons > button.selected {
-  border-bottom: 3px solid #FC6420;
+#font-type-buttons > button.selected,
+#color-scheme-buttons > button:active:hover,
+#color-scheme-buttons > button.selected {
+  box-shadow: inset 0 -3px 0 0 #FC6420;
 }
 
 #font-type-buttons > button > div {
   color: #666;
   font-size: 12px;
 }
 
 .button:hover,
-#font-size-buttons > button:hover {
+#font-size-buttons > button:hover,
+#font-type-buttons > button:hover {
   background-color: #EBEBEB;
 }
 
 .dropdown.open,
 .button:active,
 #font-size-buttons > button:active,
 #font-size-buttons > button.selected {
   background-color: #DADADA;
 }
 
 /* Only used on Android */
 #font-size-sample {
   display: none;
 }
 
 .serif-button {
-  font-family: serif;
+  font-family: "Charis SIL", Georgia, "Times New Roman", serif;
 }
 
 .minus-button,
 .plus-button {
   background-color: transparent;
   border: 0;
   height: 50px;
   background-size: 18px 18px;
@@ -434,8 +449,14 @@ body {
 
 .minus-button {
   background-image: url("chrome://global/skin/reader/RM-Minus-24x24.svg");
 }
 
 .plus-button {
   background-image: url("chrome://global/skin/reader/RM-Plus-24x24.svg");
 }
+
+@media print {
+  .toolbar {
+    display: none;
+  }
+}