Merge m-c to b2ginbound, a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 07 Aug 2015 17:35:30 -0700
changeset 288604 d6eaf951ffa6d82c71c72e822de4f3921a0a53e1
parent 288603 b02a34551c919c510399e5b231e1e55bdf3ef0d8 (current diff)
parent 288543 943b79d9c65ff504b3d656d2188a29f6a42871c0 (diff)
child 288605 0d89677508b2164a7dd7e8b5d04886b38ab27cd8
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone42.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 m-c to b2ginbound, a=merge
browser/themes/shared/devtools/images/debugger-no-pause-exceptions.png
browser/themes/shared/devtools/images/debugger-no-pause-exceptions@2x.png
browser/themes/shared/devtools/images/debugger-pause-all-exceptions.png
browser/themes/shared/devtools/images/debugger-pause-all-exceptions@2x.png
browser/themes/shared/devtools/images/debugger-pause-uncaught-exceptions.png
browser/themes/shared/devtools/images/debugger-pause-uncaught-exceptions@2x.png
browser/themes/shared/mask-and-shield.svg
browser/themes/shared/mask.png
browser/themes/shared/mask@2x.png
security/manager/ssl/tests/unit/test_ocsp_fetch_method/a.der
security/manager/ssl/tests/unit/test_ocsp_fetch_method/b.der
security/manager/ssl/tests/unit/test_ocsp_fetch_method/ca.der
security/manager/ssl/tests/unit/test_ocsp_fetch_method/cert9.db
security/manager/ssl/tests/unit/test_ocsp_fetch_method/generate.py
security/manager/ssl/tests/unit/test_ocsp_fetch_method/int.der
security/manager/ssl/tests/unit/test_ocsp_fetch_method/key4.db
security/manager/ssl/tests/unit/test_ocsp_fetch_method/pkcs11.txt
toolkit/devtools/server/tests/mochitest/test_memory_allocations_07.html
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -412,16 +412,33 @@
       <menuitem hidden="true" id="context-bidi-text-direction-toggle"
                 label="&bidiSwitchTextDirectionItem.label;"
                 accesskey="&bidiSwitchTextDirectionItem.accesskey;"
                 command="cmd_switchTextDirection"/>
       <menuitem hidden="true" id="context-bidi-page-direction-toggle"
                 label="&bidiSwitchPageDirectionItem.label;"
                 accesskey="&bidiSwitchPageDirectionItem.accesskey;"
                 oncommand="gContextMenu.switchPageDirection();"/>
+      <menuseparator id="fill-login-separator" hidden="true"/>
+      <menu id="fill-login"
+            label="&fillPasswordMenu.label;"
+            class="menu-iconic"
+            accesskey="&fillPasswordMenu.accesskey;"
+            hidden="true">
+        <menupopup id="fill-login-popup">
+          <menuitem id="fill-login-no-logins"
+                    label="&noLoginSuggestions.label;"
+                    disabled="true"
+                    hidden="true"/>
+          <menuseparator id="saved-logins-separator"/>
+          <menuitem id="fill-login-saved-passwords"
+                    label="&viewSavedLogins.label;"
+                    oncommand="gContextMenu.openPasswordManager();"/>
+        </menupopup>
+      </menu>
       <menuseparator id="inspect-separator" hidden="true"/>
       <menuitem id="context-inspect"
                 hidden="true"
                 label="&inspectContextMenu.label;"
                 accesskey="&inspectContextMenu.accesskey;"
                 oncommand="gContextMenu.inspectNode();"/>
       <menuseparator id="context-media-eme-separator" hidden="true"/>
       <menuitem id="context-media-eme-learnmore"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7911,14 +7911,15 @@ let PanicButtonNotifier = {
 let AboutPrivateBrowsingListener = {
   init: function () {
     window.messageManager.addMessageListener(
       "AboutPrivateBrowsing:OpenPrivateWindow",
       msg => {
         OpenBrowserWindow({private: true});
     });
     window.messageManager.addMessageListener(
-      "AboutPrivateBrowsing:EnableTrackingProtection",
+      "AboutPrivateBrowsing:ToggleTrackingProtection",
       msg => {
-        Services.prefs.setBoolPref("privacy.trackingprotection.pbmode.enabled", true);
+        const PREF = "privacy.trackingprotection.pbmode.enabled";
+        Services.prefs.setBoolPref(PREF, !Services.prefs.getBoolPref(PREF));
     });
   }
 };
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1,22 +1,25 @@
 /* vim: set ts=2 sw=2 sts=2 et tw=80: */
 # 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/.
 
 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
+Components.utils.import("resource://gre/modules/LoginManagerContextMenu.jsm");
 Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Pocket",
   "resource:///modules/Pocket.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
+  "resource://gre/modules/LoginHelper.jsm");
 
 var gContextMenuContentData = null;
 
 function nsContextMenu(aXulMenu, aIsShift) {
   this.shouldDisplay = true;
   this.initMenu(aXulMenu, aIsShift);
 }
 
@@ -62,16 +65,17 @@ nsContextMenu.prototype = {
     this._checkTelemetryForMenu(aXulMenu);
   },
 
   hiding: function CM_hiding() {
     gContextMenuContentData = null;
     InlineSpellCheckerUI.clearSuggestionsFromMenu();
     InlineSpellCheckerUI.clearDictionaryListFromMenu();
     InlineSpellCheckerUI.uninit();
+    LoginManagerContextMenu.clearLoginsFromMenu(document);
 
     // This handler self-deletes, only run it if it is still there:
     if (this._onPopupHiding) {
       this._onPopupHiding();
     }
   },
 
   initItems: function CM_initItems() {
@@ -81,16 +85,17 @@ nsContextMenu.prototype = {
     this.initViewItems();
     this.initMiscItems();
     this.initSpellingItems();
     this.initSaveItems();
     this.initClipboardItems();
     this.initMediaPlayerItems();
     this.initLeaveDOMFullScreenItems();
     this.initClickToPlayItems();
+    this.initPasswordManagerItems();
   },
 
   initPageMenuSeparator: function CM_initPageMenuSeparator() {
     this.showItem("page-menu-separator", this.hasPageMenu);
   },
 
   initOpenItems: function CM_initOpenItems() {
     var isMailtoInternal = false;
@@ -495,16 +500,43 @@ nsContextMenu.prototype = {
   },
 
   initClickToPlayItems: function() {
     this.showItem("context-ctp-play", this.onCTPPlugin);
     this.showItem("context-ctp-hide", this.onCTPPlugin);
     this.showItem("context-sep-ctp", this.onCTPPlugin);
   },
 
+  initPasswordManagerItems: function() {
+    let showFillPassword = this.onPassword;
+    let disableFillPassword = !Services.logins.isLoggedIn || this.target.disabled || this.target.readOnly;
+    this.showItem("fill-login-separator", showFillPassword);
+    this.showItem("fill-login", showFillPassword);
+    this.setItemAttr("fill-login", "disabled", disableFillPassword);
+
+    if (!showFillPassword || disableFillPassword) {
+      return;
+    }
+    let documentURI = gContextMenuContentData.documentURIObject;
+    let fragment = LoginManagerContextMenu.addLoginsToMenu(this.target, this.browser, documentURI);
+
+    this.showItem("fill-login-no-logins", !fragment);
+
+    if (!fragment) {
+      return;
+    }
+    let popup = document.getElementById("fill-login-popup");
+    let insertBeforeElement = document.getElementById("fill-login-no-logins");
+    popup.insertBefore(fragment, insertBeforeElement);
+  },
+
+  openPasswordManager: function() {
+    LoginHelper.openPasswordManager(window, gContextMenuContentData.documentURIObject.host);
+  },
+
   inspectNode: function CM_inspectNode() {
     let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
     let gBrowser = this.browser.ownerDocument.defaultView.gBrowser;
     let tt = devtools.TargetFactory.forTab(gBrowser.selectedTab);
     return gDevTools.showToolbox(tt, "inspector").then(function(toolbox) {
       let inspector = toolbox.getCurrentPanel();
       if (this.isRemote) {
         this.browser.messageManager.sendAsyncMessage("debug:inspect", {}, {node: this.target});
@@ -566,16 +598,17 @@ nsContextMenu.prototype = {
     this.inSrcdocFrame     = false;
     this.inSyntheticDoc    = false;
     this.hasBGImage        = false;
     this.bgImageURL        = "";
     this.onEditableArea    = false;
     this.isDesignMode      = false;
     this.onCTPPlugin       = false;
     this.canSpellCheck     = false;
+    this.onPassword        = false;
 
     if (this.isRemote) {
       this.selectionInfo = gContextMenuContentData.selectionInfo;
     } else {
       this.selectionInfo = BrowserUtils.getSelectionDetails(window);
     }
 
     this.textSelected      = this.selectionInfo.text;
@@ -663,16 +696,17 @@ nsContextMenu.prototype = {
         if (this.target.isEncrypted) {
           this.onDRMMedia = true;
         }
       }
       else if (editFlags & (SpellCheckHelper.INPUT | SpellCheckHelper.TEXTAREA)) {
         this.onTextInput = (editFlags & SpellCheckHelper.TEXTINPUT) !== 0;
         this.onNumeric = (editFlags & SpellCheckHelper.NUMERIC) !== 0;
         this.onEditableArea = (editFlags & SpellCheckHelper.EDITABLE) !== 0;
+        this.onPassword = (editFlags & SpellCheckHelper.PASSWORD) !== 0;
         if (this.onEditableArea) {
           if (this.isRemote) {
             InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
           }
           else {
             InlineSpellCheckerUI.init(this.target.QueryInterface(Ci.nsIDOMNSEditableElement).editor);
             InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
           }
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -230,34 +230,34 @@ let AboutHomeListener = {
   },
 };
 AboutHomeListener.init(this);
 
 let AboutPrivateBrowsingListener = {
   init(chromeGlobal) {
     chromeGlobal.addEventListener("AboutPrivateBrowsingOpenWindow", this,
                                   false, true);
-    chromeGlobal.addEventListener("AboutPrivateBrowsingEnableTrackingProtection", this,
+    chromeGlobal.addEventListener("AboutPrivateBrowsingToggleTrackingProtection", this,
                                   false, true);
   },
 
   get isAboutPrivateBrowsing() {
     return content.document.documentURI.toLowerCase() == "about:privatebrowsing";
   },
 
   handleEvent(aEvent) {
     if (!this.isAboutPrivateBrowsing) {
       return;
     }
     switch (aEvent.type) {
       case "AboutPrivateBrowsingOpenWindow":
         sendAsyncMessage("AboutPrivateBrowsing:OpenPrivateWindow");
         break;
-      case "AboutPrivateBrowsingEnableTrackingProtection":
-        sendAsyncMessage("AboutPrivateBrowsing:EnableTrackingProtection");
+      case "AboutPrivateBrowsingToggleTrackingProtection":
+        sendAsyncMessage("AboutPrivateBrowsing:ToggleTrackingProtection");
         break;
     }
   },
 };
 AboutPrivateBrowsingListener.init(this);
 
 let AboutReaderListener = {
 
--- a/browser/base/content/test/general/browser_audioTabIcon.js
+++ b/browser/base/content/test/general/browser_audioTabIcon.js
@@ -110,22 +110,38 @@ function* test_swapped_browser(oldTab, n
   ok(oldTab.hasAttribute("muted"), "Expected the correct muted attribute on the old tab");
   is(oldTab.hasAttribute("soundplaying"), isPlaying, "Expected the correct soundplaying attribute on the old tab");
 
   let newTab = gBrowser.getTabForBrowser(newBrowser);
   let AttrChangePromise = BrowserTestUtils.waitForEvent(newTab, "TabAttrModified", false, event => {
     return (event.detail.changed.indexOf("soundplaying") >= 0 || !isPlaying) &&
            event.detail.changed.indexOf("muted") >= 0;
   });
+  let AudioPlaybackPromise = new Promise(resolve => {
+    let observer = (subject, topic, data) => {
+      ok(false, "Should not see an audio-playback notification");
+    };
+    Services.obs.addObserver(observer, "audio-playback", false);
+    setTimeout(() => {
+      Services.obs.removeObserver(observer, "audio-playback");
+      resolve();
+    }, 100);
+  });
 
   gBrowser.swapBrowsersAndCloseOther(newTab, oldTab);
   yield AttrChangePromise;
 
   ok(newTab.hasAttribute("muted"), "Expected the correct muted attribute on the new tab");
   is(newTab.hasAttribute("soundplaying"), isPlaying, "Expected the correct soundplaying attribute on the new tab");
+
+  // Wait to see if an audio-playback event is dispatched.  This should not happen!
+  yield AudioPlaybackPromise;
+
+  ok(newTab.hasAttribute("muted"), "Expected the correct muted attribute on the new tab");
+  is(newTab.hasAttribute("soundplaying"), isPlaying, "Expected the correct soundplaying attribute on the new tab");
 }
 
 function* test_browser_swapping(tab, browser) {
   // First, test swapping with a playing but muted tab.
   yield ContentTask.spawn(browser, {}, function* () {
     let audio = content.document.querySelector("audio");
     audio.play();
   });
--- a/browser/base/content/test/general/browser_urlbar_autoFill_backspaced.js
+++ b/browser/base/content/test/general/browser_urlbar_autoFill_backspaced.js
@@ -16,17 +16,17 @@ function* test_autocomplete(data) {
   is(gURLBar.value, modified, "backspaced value is as expected");
 
   yield promiseSearchComplete();
 
   ok(gURLBar.popup.richlistbox.children.length > 0, "Should get at least 1 result");
   let result = gURLBar.popup.richlistbox.children[0];
   let type = result.getAttribute("type");
   let types = type.split(/\s+/);
-  ok(types.includes(action), `The type attribute "${type}" includes the expected action "${action}"`);
+  ok(types.indexOf(action) >= 0, `The type attribute "${type}" includes the expected action "${action}"`);
 
   gURLBar.popup.hidePopup();
   yield promisePopupHidden(gURLBar.popup);
   gURLBar.blur();
 };
 
 add_task(function* () {
   registerCleanupFunction(function* () {
--- a/browser/base/content/test/general/contextmenu_common.js
+++ b/browser/base/content/test/general/contextmenu_common.js
@@ -56,17 +56,19 @@ function getVisibleMenuItems(aMenu, aDat
             ok(label.length, "menuitem " + item.id + " has a label");
             if (isSpellSuggestion) {
               is(key, "", "Spell suggestions shouldn't have an access key");
               items.push("*" + label);
             } else if (isGenerated) {
               items.push("+" + label);
             } else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
                        item.id != "spell-no-suggestions" &&
-                       item.id != "spell-add-dictionaries-main") {
+                       item.id != "spell-add-dictionaries-main" &&
+                       item.id != "fill-login-saved-passwords" &&
+                       item.id != "fill-login-no-logins") {
               ok(key, "menuitem " + item.id + " has an access key");
               if (accessKeys[key])
                   ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
               else
                   accessKeys[key] = item.id;
             }
             if (!isSpellSuggestion && !isGenerated) {
               items.push(item.id);
--- a/browser/base/content/test/general/test_contextmenu.html
+++ b/browser/base/content/test/general/test_contextmenu.html
@@ -75,16 +75,26 @@ function runTest(testNum) {
   ok(true, "Starting test #" + testNum);
 
   var inspectItems = [];
   if (SpecialPowers.getBoolPref("devtools.inspector.enabled")) {
     inspectItems = ["---", null,
                     "context-inspect", true];
   }
 
+  var passwordFillItems = [
+    "---", null,
+    "fill-login", null,
+      [
+        "fill-login-no-logins", false,
+        "---", null,
+        "fill-login-saved-passwords", true
+      ], null,
+  ];
+
   var tests = [
     function () {
         // Invoke context menu for next test.
         openContextMenuFor(text);
     },
 
     function () {
         // Context menu for plain text
@@ -660,17 +670,18 @@ function runTest(testNum) {
                           "context-selectall",   true,
                           "---",                 null,
                           "spell-check-enabled", true,
                           //spell checker is shown on input[type="password"] on this testcase
                           "spell-dictionaries",  true,
                               ["spell-check-dictionary-en-US", true,
                                "---",                          null,
                                "spell-add-dictionaries",       true], null
-                         ].concat(inspectItems));
+                         ].concat(passwordFillItems)
+                          .concat(inspectItems));
         closeContextMenu();
         subwindow.getSelection().removeAllRanges();
         openContextMenuFor(plugin);
     },
 
     function () {
         // Context menu for click-to-play blocked plugin
         checkContextMenu(["context-navigation", null,
--- a/browser/base/content/test/general/test_contextmenu_input.html
+++ b/browser/base/content/test/general/test_contextmenu_input.html
@@ -162,16 +162,21 @@ function runTest(testNum) {
                           "---",                 null,
                           "context-cut",         true,
                           "context-copy",        true,
                           "context-paste",       null, // ignore clipboard state
                           "context-delete",      false,
                           "---",                 null,
                           "context-selectall",   false,
                           "---",                 null,
+                          "fill-login",          null,
+                            ["fill-login-no-logins",       false,
+                             "---",                        null,
+                             "fill-login-saved-passwords", true], null,
+                          "---",                 null,
                           "context-inspect",     true]);
 
         closeContextMenu();
 
         input.type = 'email';
 
         openContextMenuFor(input); // Invoke context menu for next test.
         break;
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -54,21 +54,21 @@
             class="identity-popup-section"
             when-connection="not-secure secure secure-ev file">
         <vbox id="tracking-protection-content" flex="1">
           <description class="identity-popup-headline"
                        crop="end"
                        value="&trackingProtection.title;" />
 
           <label id="tracking-blocked"
-                 crop="end">&trackingProtection.detectedBlocked2;</label>
+                 crop="end">&trackingProtection.detectedBlocked3;</label>
           <label id="tracking-loaded"
-                 crop="end">&trackingProtection.detectedNotBlocked2;</label>
+                 crop="end">&trackingProtection.detectedNotBlocked3;</label>
           <label id="tracking-not-detected"
-                 crop="end">&trackingProtection.notDetected2;</label>
+                 crop="end">&trackingProtection.notDetected3;</label>
 
           <button id="tracking-action-unblock"
                   label="&trackingProtection.unblock.label;"
                   accesskey="&trackingProtection.unblock.accesskey;"
                   oncommand="TrackingProtection.disableForCurrentPage();" />
           <button id="tracking-action-unblock-private"
                   label="&trackingProtection.unblockPrivate.label;"
                   accesskey="&trackingProtection.unblockPrivate.accesskey;"
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -98,29 +98,29 @@
         &doNotTrackInfo.label;
       </label>
     </hbox>
   </vbox>
   <vbox id="trackingprotectionbox" hidden="true">
     <hbox align="center">
       <checkbox id="trackingProtection"
                 preference="privacy.trackingprotection.enabled"
-                accesskey="&trackingProtection4.accesskey;"
-                label="&trackingProtection4.label;" />
+                accesskey="&trackingProtection5.accesskey;"
+                label="&trackingProtection5.label;" />
       <label id="trackingProtectionLearnMore"
              class="text-link"
              value="&trackingProtectionLearnMore.label;"/>
     </hbox>
   </vbox>
   <vbox id="trackingprotectionpbmbox">
     <hbox align="center">
       <checkbox id="trackingProtectionPBM"
                 preference="privacy.trackingprotection.pbmode.enabled"
-                accesskey="&trackingProtectionPBM4.accesskey;"
-                label="&trackingProtectionPBM4.label;" />
+                accesskey="&trackingProtectionPBM5.accesskey;"
+                label="&trackingProtectionPBM5.label;" />
       <label id="trackingProtectionPBMLearnMore"
              class="text-link"
              value="&trackingProtectionPBMLearnMore.label;"/>
     </hbox>
   </vbox>
 </groupbox>
 
 <!-- History -->
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -91,18 +91,18 @@
 
     <!-- Tracking -->
     <groupbox id="trackingGroup" align="start">
       <caption label="&tracking.label;"/>
       <vbox id="trackingprotectionbox" hidden="true">
         <hbox align="center">
           <checkbox id="trackingProtection"
                     preference="privacy.trackingprotection.enabled"
-                    accesskey="&trackingProtection4.accesskey;"
-                    label="&trackingProtection4.label;" />
+                    accesskey="&trackingProtection5.accesskey;"
+                    label="&trackingProtection5.label;" />
           <image id="trackingProtectionImage"
                  src="chrome://browser/skin/bad-content-blocked-16.png"/>
         </hbox>
         <hbox align="center"
               class="indent">
           <label id="trackingProtectionLearnMore"
                  class="text-link"
                  value="&trackingProtectionLearnMore.label;"/>
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.css
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.css
@@ -2,145 +2,184 @@
 /* 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/. */
 %endif
 
 @import url("chrome://global/skin/in-content/common.css");
 
 body {
+  min-height: 100vh;
   display: flex;
   flex-direction: column;
-  box-sizing: border-box;
-  min-height: 100vh;
-  padding: 0 48px;
   align-items: center;
   justify-content: center;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-weight: 300;
 }
 
-body.tour {
-  margin: 0;
-  padding: 0;
-  align-items: stretch;
-}
-
+body.private .showNormal,
 body.normal .showPrivate,
-body.private .showNormal,
-body.tour #pageContainer,
-body:not(.tour) .showTour,
 body[tpEnabled] .showTpDisabled,
 body:not([tpEnabled]) .showTpEnabled {
   display: none !important;
 }
 
-#pageContainer {
-  min-width: 320px;
-  max-width: 512px;
-}
-
-.titleText {
-  background: url("chrome://browser/skin/mask.png") left 0 no-repeat;
-  background-size: 45px;
-  -moz-margin-start: -2em;
-  -moz-padding-start: 2em;
-}
-
-.titleText:-moz-dir(rtl) {
-  background-position: right 0;
-}
-
-@media (min-resolution: 2dppx) {
-  .titleText {
-    background-image: url("chrome://browser/skin/mask@2x.png");
-  }
-}
-
-@media (max-width: 675px) {
-  .titleText {
-    padding-top: 0;
-    background-image: none;
-    -moz-margin-start: 0;
-    -moz-padding-start: 0;
+@media screen and (min-width: 1200px) and (min-height: 700px) {
+  body.private {
+    font-size: 1.25em;
   }
 }
 
-a {
-  font-size: 1rem;
+#bar {
+  align-self: stretch;
+  background: url("chrome://browser/skin/privatebrowsing/mask.svg") no-repeat 22px 50%,
+              #8d20ae;
+  background-size: 47px 26px;
+  padding-inline-start: 87px;
+  color: white;
+  font-size: 24pt;
+  font-weight: 200;
+  line-height: 60pt;
 }
 
-#startPrivateBrowsing {
-  margin-top: 1.2em;
-  -moz-margin-start: 0;
+#main {
+  padding: 0 2em;
+  flex: 1;
+  display: flex;
+  flex-flow: row wrap;
+  align-items: center;
+  justify-content: center;
+}
+
+.sectionHeader {
+  font-size: 1.75em;
 }
 
-/* TRACKING PROTECTION TOUR */
+/* PRIVATE BROWSING SECTION */
 
-#tourTop,
-#tourBottom,
-#tourFooter {
-  text-align: center;
-  padding: 0 31px;
+#privateBrowsingSection {
+  margin: 1em;
+  padding: 0 1em;
+}
+
+ul {
+  margin-bottom: 0;
+  padding-inline-start: 8px;
 }
 
-#tourTop,
-#tourBottom {
-  flex: 1;
+li {
+  list-style: none;
+  padding-inline-start: 24px;
+  background-size: 16px 16px;
+  background-repeat: no-repeat;
+  background-position: 0 50%;
+}
+
+#forgotten > li {
+  background-image: url("chrome://browser/skin/privatebrowsing/check.png");
+}
+
+#kept > li {
+  background-image: url("chrome://browser/skin/privatebrowsing/attention.png");
 }
 
-#tourTop {
+@media (min-resolution: 1.1dppx) {
+  #forgotten li {
+    background-image: url("chrome://browser/skin/privatebrowsing/check@2x.png");
+  }
+
+  #kept li {
+    background-image: url("chrome://browser/skin/privatebrowsing/attention@2x.png");
+  }
+}
+
+#list-area {
   display: flex;
-  flex-direction: column;
-  justify-content: flex-end;
-  background-color: rgb(108,192,65);
-  color: white;
-  font-style: italic;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: flex-start;
+}
+
+#list-area > div {
+  margin-inline-end: 1em;
+}
+
+.list-header {
+  font-weight: bold;
+}
+
+/* TRACKING PROTECTION SECTION */
+
+#trackingProtectionSection {
+  margin: 1em;
+  padding: 1em;
+  text-align: center;
+  border: lightgray 2px solid;
+  border-radius: 10px;
 }
 
-#tourTitle {
-  margin: 16px 0 0;
-  background: url("chrome://browser/skin/mask-and-shield.svg") top no-repeat;
-  background-size: 179px 88px;
-  padding-top: 114px;
-  font-size: 38px;
+#tpEnabled,
+#tpDisabled {
+  display: inline-block;
+  margin-inline-start: 0.5em;
+  border-radius: 3px;
+  padding: 0.1em;
+  color: white;
+  font-size: 0.78em;
+  font-weight: bold;
+}
+
+#tpEnabled {
+  background-color: #6fbe4a;
 }
 
-#tourSubtitle {
-  margin: 12px 0 32px;
-  font-size: 24px;
+#tpDisabled {
+  background-color: #c33b32;
 }
 
-#tourDescription,
-#tourFooter {
-  margin: 16px auto;
-  max-width: 550px;
+#tpDiagram {
+  margin-left: auto;
+  margin-right: auto;
+  width: 145px;
+  height: 90px;
+  background: url("chrome://browser/skin/privatebrowsing/shield-page.png") no-repeat;
+  background-size: 145px 90px;
+}
+
+@media (min-resolution: 1.1dppx) {
+  #tpDiagram {
+    background-image: url("chrome://browser/skin/privatebrowsing/shield-page@2x.png");
+  }
+}
+
+#tpStartTour {
+  margin-bottom: 0;
 }
 
 #startTour {
   display: inline-block;
-  width: 255px;
+  width: 16em;
   border-radius: 2px;
   background-color: var(--in-content-primary-button-background);
   color: var(--in-content-selected-text);
-  padding: 2px 5px;
-  line-height: 36px;
+  padding: 0.1em 0.3em;
+  line-height: 2.25em;
   text-decoration: none;
 }
 
 #startTour:hover {
   background-color: var(--in-content-primary-button-background-hover);
 }
 
-#enableTrackingProtection {
-  height: 40px;
-}
-
-#tourFooter {
-  margin: 16px auto;
+#startTour:hover:active {
+  background-color: var(--in-content-primary-button-background-active);
 }
 
-#tourFooter,
-#tourLearnMore {
-  font-size: 12px;
+#startTour:-moz-focusring {
+  outline: 1px dotted var(--in-content-border-focus);
 }
 
-#tourFooterText {
-  opacity: 0.6;
+#enableTrackingProtection,
+#disableTrackingProtection {
+  font-size: 0.875em;
+  cursor: pointer;
 }
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
@@ -3,89 +3,86 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+const FAVICON_QUESTION = "chrome://global/skin/icons/question-16.png";
+const FAVICON_PRIVACY = "chrome://browser/skin/Privacy-16.png";
+
 let stringBundle = Services.strings.createBundle(
                      "chrome://browser/locale/aboutPrivateBrowsing.properties");
 
-let useTour = false;
-try {
-  useTour = Services.prefs.getBoolPref("privacy.trackingprotection.ui.enabled");
-} catch (ex) {
-  // The preference is not available.
-}
-
-if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
-  document.title = stringBundle.GetStringFromName("title.normal");
-  setFavIcon("chrome://global/skin/icons/question-16.png");
-} else {
-  document.title = stringBundle.GetStringFromName("title");
-  setFavIcon("chrome://browser/skin/Privacy-16.png");
-}
-
 let prefBranch = Services.prefs.getBranch("privacy.trackingprotection.pbmode.");
 let prefObserver = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
   observe: function () {
     if (prefBranch.getBoolPref("enabled")) {
       document.body.setAttribute("tpEnabled", "true");
     } else {
       document.body.removeAttribute("tpEnabled");
     }
   },
 };
 prefBranch.addObserver("enabled", prefObserver, true);
 
 function setFavIcon(url) {
-  let icon = document.createElement("link");
-  icon.setAttribute("rel", "icon");
-  icon.setAttribute("type", "image/png");
-  icon.setAttribute("href", url);
-  let head = document.getElementsByTagName("head")[0];
-  head.insertBefore(icon, head.firstChild);
+  document.getElementById("favicon").setAttribute("href", url);
 }
 
 document.addEventListener("DOMContentLoaded", function () {
+  if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
+    document.body.setAttribute("class", "normal");
+    document.title = stringBundle.GetStringFromName("title.normal");
+    document.getElementById("favicon")
+            .setAttribute("href", FAVICON_QUESTION);
+    document.getElementById("startPrivateBrowsing")
+            .addEventListener("command", openPrivateWindow);
+    return;
+  }
+
+  document.title = stringBundle.GetStringFromName("title");
+  document.getElementById("favicon")
+          .setAttribute("href", FAVICON_PRIVACY);
+  document.getElementById("enableTrackingProtection")
+          .addEventListener("click", toggleTrackingProtection);
+  document.getElementById("disableTrackingProtection")
+          .addEventListener("click", toggleTrackingProtection);
+
   let formatURLPref = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
                         .getService(Ci.nsIURLFormatter).formatURLPref;
-  let learnMoreURL = formatURLPref("app.support.baseURL") + "private-browsing";
+  document.getElementById("startTour").setAttribute("href",
+                     formatURLPref("privacy.trackingprotection.introURL"));
+  document.getElementById("learnMore").setAttribute("href",
+                     formatURLPref("app.support.baseURL") + "private-browsing");
+
+  // Update state that depends on preferences.
+  prefObserver.observe();
 
-  if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
-    // Normal browsing window.
-    document.body.setAttribute("class", "normal");
-  } else if (!useTour) {
-    // Private browsing window, classic version.
-    document.getElementById("learnMore").setAttribute("href", learnMoreURL);
-  } else {
-    // Private browsing window, Tracking Protection tour version.
-    document.body.setAttribute("class", "tour");
-    let tourURL = formatURLPref("privacy.trackingprotection.introURL");
-    document.getElementById("startTour").setAttribute("href", tourURL);
-    document.getElementById("tourLearnMore").setAttribute("href", learnMoreURL);
-    // Update state that depends on preferences.
-    prefObserver.observe();
+  // This check can be removed when Tracking Protection is always available.
+  let tpUIEnabled = false;
+  try {
+    tpUIEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.ui.enabled");
+  } catch (ex) {
+    // The preference is not available.
   }
-
-  document.getElementById("startPrivateBrowsing")
-          .addEventListener("command", openPrivateWindow);
-
-  document.getElementById("enableTrackingProtection")
-          .addEventListener("command", enableTrackingProtection);
+  if (!tpUIEnabled) {
+    document.getElementById("trackingProtectionSection")
+            .setAttribute("hidden", "true");
+  }
 }, false);
 
 function openPrivateWindow() {
   // Ask chrome to open a private window
   document.dispatchEvent(
     new CustomEvent("AboutPrivateBrowsingOpenWindow", {bubbles:true}));
 }
 
-function enableTrackingProtection() {
+function toggleTrackingProtection() {
   // Ask chrome to enable tracking protection
   document.dispatchEvent(
-    new CustomEvent("AboutPrivateBrowsingEnableTrackingProtection",
+    new CustomEvent("AboutPrivateBrowsingToggleTrackingProtection",
                     {bubbles:true}));
 }
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
@@ -14,55 +14,75 @@
   <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
   %browserDTD;
   <!ENTITY % aboutPrivateBrowsingDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
   %aboutPrivateBrowsingDTD;
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
+    <link id="favicon" rel="icon" type="image/png"/>
     <link rel="stylesheet" href="chrome://browser/content/aboutPrivateBrowsing.css" type="text/css" media="all"/>
     <script type="application/javascript;version=1.7" src="chrome://browser/content/aboutPrivateBrowsing.js"></script>
   </head>
 
   <body dir="&locale.dir;" class="private">
-    <div id="pageContainer">
-      <h1 class="titleText showPrivate">&aboutPrivateBrowsing.title;</h1>
-      <h1 class="titleText showNormal">&aboutPrivateBrowsing.title.normal;</h1>
-
-      <p class="subtitleText showPrivate">&aboutPrivateBrowsing.subtitle;</p>
-      <p class="subtitleText showNormal">&aboutPrivateBrowsing.subtitle.normal;</p>
-
-      <p class="descriptionText">&aboutPrivateBrowsing.description;</p>
-
-      <p class="notPrivateText showNormal">&aboutPrivateBrowsing.notPrivate;</p>
-
-      <button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-              id="startPrivateBrowsing"
-              class="openPrivate showNormal"
-              label="&privatebrowsingpage.openPrivateWindow.label;"
-              accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;"/>
-      <div class="showPrivate">
-        <p class="moreInfoText">&aboutPrivateBrowsing.moreInfo;</p>
-        <p><a id="learnMore" target="_blank">&aboutPrivateBrowsing.learnMore;</a></p>
+    <p class="showNormal">&aboutPrivateBrowsing.notPrivate;</p>
+    <button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+            id="startPrivateBrowsing"
+            class="showNormal"
+            label="&privatebrowsingpage.openPrivateWindow.label;"
+            accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;"/>
+    <div id="bar" class="showPrivate">&privateBrowsing.title;</div>
+    <div id="main" class="showPrivate">
+      <div id="privateBrowsingSection"
+           style="width: &aboutPrivateBrowsing.width;">
+        <div class="sectionHeader">&aboutPrivateBrowsing.title;</div>
+        <p>&aboutPrivateBrowsing.subtitle;</p>
+        <div id="list-area">
+          <div>
+            <div class="list-header">&aboutPrivateBrowsing.info.forgotten;</div>
+            <ul id="forgotten">
+              <li>&aboutPrivateBrowsing.info.history;</li>
+              <li>&aboutPrivateBrowsing.info.search;</li>
+              <li>&aboutPrivateBrowsing.info.cookies;</li>
+              <li>&aboutPrivateBrowsing.info.temporaryFiles;</li>
+            </ul>
+          </div>
+          <div>
+            <div class="list-header">&aboutPrivateBrowsing.info.kept;</div>
+            <ul id="kept">
+              <li>&aboutPrivateBrowsing.info.downloads;</li>
+              <li>&aboutPrivateBrowsing.info.bookmarks;</li>
+            </ul>
+          </div>
+        </div>
+        <p>&aboutPrivateBrowsing.note;</p>
+        <a id="learnMore" target="_blank">&aboutPrivateBrowsing.learnMore;</a>
+      </div>
+      <div id="trackingProtectionSection"
+           style="width: &trackingProtection.width;">
+        <div class="sectionHeader">&trackingProtection.title;
+          <span id="tpEnabled"
+                style="width: &trackingProtection.state.width;"
+                class="showTpEnabled">&trackingProtection.state.enabled;</span>
+          <span id="tpDisabled"
+                style="width: &trackingProtection.state.width;"
+                class="showTpDisabled">&trackingProtection.state.disabled;</span>
+        </div>
+        <p id="tpDiagram"/>
+        <p class="showTpEnabled">&trackingProtection.description.enabled;</p>
+        <p class="showTpDisabled">&trackingProtection.description.disabled;</p>
+        <!-- Use text links to implement plain styled buttons without an href. -->
+        <label xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+               id="disableTrackingProtection"
+               class="text-link showTpEnabled"
+               value="&trackingProtection.disable;"/>
+        <label xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+               id="enableTrackingProtection"
+               class="text-link showTpDisabled"
+               value="&trackingProtection.enable;"/>
+        <p id="tpStartTour"
+           class="showTpEnabled"><a id="startTour">&trackingProtection.startTour;</a></p>
       </div>
     </div>
-    <div id="tourTop" class="showTour">
-      <p id="tourTitle">&aboutPrivateBrowsing.title;</p>
-      <p id="tourSubtitle">&trackingProtection.subtitle;</p>
-    </div>
-    <div id="tourBottom" class="showTour">
-      <p id="tourDescription">&trackingProtection.description;</p>
-      <p class="showTpEnabled"><a id="startTour">&trackingProtection.startTour;</a></p>
-      <p class="showTpEnabled"><a id="showPreferences" href="about:preferences#privacy"
-        target="_blank">&trackingProtection.showPreferences;</a></p>
-      <button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-              id="enableTrackingProtection"
-              class="primary showTpDisabled"
-              label="&trackingProtection.enable.label;"
-              accesskey="&trackingProtection.enable.accesskey;"/>
-    </div>
-    <p id="tourFooter" class="showTour">
-      <span id="tourFooterText">&aboutPrivateBrowsing.shortdescription;</span>
-      <a id="tourLearnMore" target="_blank">&aboutPrivateBrowsing.learnMore;</a>
-    </p>
   </body>
 </html>
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
@@ -37,103 +37,83 @@ function* testLinkOpensUrl({ win, tab, e
     content.document.getElementById(elementId).click();
   });
   yield loadedPromise;
   is(tab.currentURI.spec, expectedUrl,
      `Clicking ${elementId} opened ${expectedUrl} in the same tab.`);
 }
 
 /**
- * Tests the Learn More action in the classic "about:privatebrowsing" window.
+ * Tests the links in "about:privatebrowsing".
  */
-add_task(function* test_classicActions() {
-  // Use classic version and change the remote URL to prevent network access.
-  Services.prefs.setBoolPref("privacy.trackingprotection.ui.enabled", false);
-  Services.prefs.setCharPref("app.support.baseURL", "https://example.com/");
-  registerCleanupFunction(function () {
-    Services.prefs.clearUserPref("app.support.baseURL");
-    Services.prefs.clearUserPref("privacy.trackingprotection.ui.enabled");
-  });
-
-  let { win, tab } = yield openAboutPrivateBrowsing();
-
-  yield testLinkOpensTab({ win, tab,
-    elementId: "learnMore",
-    expectedUrl: "https://example.com/private-browsing",
-  });
-
-  yield BrowserTestUtils.closeWindow(win);
-});
-
-/**
- * Tests the Tracking Protection tour actions in "about:privatebrowsing".
- */
-add_task(function* test_tourActions() {
-  // Use tour version and change the remote URLs to prevent network access.
+add_task(function* test_links() {
+  // Use full version and change the remote URLs to prevent network access.
   Services.prefs.setBoolPref("privacy.trackingprotection.ui.enabled", true);
   Services.prefs.setCharPref("app.support.baseURL", "https://example.com/");
   Services.prefs.setCharPref("privacy.trackingprotection.introURL",
                              "https://example.com/tour");
   registerCleanupFunction(function () {
     Services.prefs.clearUserPref("privacy.trackingprotection.introURL");
     Services.prefs.clearUserPref("app.support.baseURL");
     Services.prefs.clearUserPref("privacy.trackingprotection.ui.enabled");
   });
 
   let { win, tab } = yield openAboutPrivateBrowsing();
 
   yield testLinkOpensTab({ win, tab,
-    elementId: "showPreferences",
-    expectedUrl: "about:preferences#privacy",
-  });
-
-  yield testLinkOpensTab({ win, tab,
-    elementId: "tourLearnMore",
+    elementId: "learnMore",
     expectedUrl: "https://example.com/private-browsing",
   });
 
   yield testLinkOpensUrl({ win, tab,
     elementId: "startTour",
     expectedUrl: "https://example.com/tour",
   });
 
   yield BrowserTestUtils.closeWindow(win);
 });
 
 /**
- * Tests the action to re-enable Tracking Protection in "about:privatebrowsing"
- * when it has been disabled from the preferences.
+ * Tests the action to disable and re-enable Tracking Protection in
+ * "about:privatebrowsing".
  */
-add_task(function* test_enableTrackingProtection() {
+add_task(function* test_toggleTrackingProtection() {
   // Use tour version but disable Tracking Protection.
   Services.prefs.setBoolPref("privacy.trackingprotection.ui.enabled", true);
   Services.prefs.setBoolPref("privacy.trackingprotection.pbmode.enabled",
-                             false);
+                             true);
   registerCleanupFunction(function () {
     Services.prefs.clearUserPref("privacy.trackingprotection.pbmode.enabled");
     Services.prefs.clearUserPref("privacy.trackingprotection.ui.enabled");
   });
 
   let { win, tab } = yield openAboutPrivateBrowsing();
 
   // Set up the observer for the preference change before triggering the action.
   let prefBranch =
       Services.prefs.getBranch("privacy.trackingprotection.pbmode.");
-  let promisePrefChanged = new Promise(resolve => {
+  let waitForPrefChanged = () => new Promise(resolve => {
     let prefObserver = {
       QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
       observe: function () {
         prefBranch.removeObserver("enabled", prefObserver);
         resolve();
       },
     };
     prefBranch.addObserver("enabled", prefObserver, false);
   });
 
+  let promisePrefChanged = waitForPrefChanged();
+  yield ContentTask.spawn(tab, {}, function* () {
+    content.document.getElementById("disableTrackingProtection").click();
+  });
+  yield promisePrefChanged;
+  ok(!prefBranch.getBoolPref("enabled"), "Tracking Protection is disabled.");
+
+  promisePrefChanged = waitForPrefChanged();
   yield ContentTask.spawn(tab, {}, function* () {
     content.document.getElementById("enableTrackingProtection").click();
   });
-
   yield promisePrefChanged;
   ok(prefBranch.getBoolPref("enabled"), "Tracking Protection is enabled.");
 
   yield BrowserTestUtils.closeWindow(win);
 });
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -126,30 +126,18 @@ this.UITour = {
         panelPopup.removeEventListener("popupshown", aCallback);
       },
     }],
     ["backForward", {
       query: "#back-button",
       widgetName: "urlbar-container",
     }],
     ["bookmarks",   {query: "#bookmarks-menu-button"}],
-    ["controlCenter-trackingUnblock", {
-      infoPanelPosition: "rightcenter topleft",
-      query(aDocument) {
-        let popup = aDocument.defaultView.gIdentityHandler._identityPopup;
-        if (popup.state != "open") {
-          return null;
-        }
-        let buttonId =
-            PrivateBrowsingUtils.isWindowPrivate(aDocument.defaultView) ?
-            "tracking-action-unblock-private" : "tracking-action-unblock";
-        let element = aDocument.getElementById(buttonId);
-        return UITour.isElementVisible(element) ? element : null;
-      },
-    }],
+    ["controlCenter-trackingUnblock", controlCenterTrackingToggleTarget(true)],
+    ["controlCenter-trackingBlock", controlCenterTrackingToggleTarget(false)],
     ["customize",   {
       query: (aDocument) => {
         let customizeButton = aDocument.getElementById("PanelUI-customize");
         return aDocument.getAnonymousElementByAttribute(customizeButton,
                                                         "class",
                                                         "toolbarbutton-icon");
       },
       widgetName: "PanelUI-customize",
@@ -2076,16 +2064,40 @@ this.UITour = {
           params: params,
         };
         messageManager.sendAsyncMessage("UITour:SendPageNotification", detail);
       }
     }
   },
 };
 
+function controlCenterTrackingToggleTarget(aUnblock) {
+  return {
+    infoPanelPosition: "rightcenter topleft",
+    query(aDocument) {
+      let popup = aDocument.defaultView.gIdentityHandler._identityPopup;
+      if (popup.state != "open") {
+        return null;
+      }
+      let buttonId = null;
+      if (aUnblock) {
+        if (PrivateBrowsingUtils.isWindowPrivate(aDocument.defaultView)) {
+          buttonId = "tracking-action-unblock-private";
+        } else {
+          buttonId = "tracking-action-unblock";
+        }
+      } else {
+        buttonId = "tracking-action-block";
+      }
+      let element = aDocument.getElementById(buttonId);
+      return UITour.isElementVisible(element) ? element : null;
+    },
+  };
+}
+
 this.UITour.init();
 
 /**
  * UITour Health Report
  */
 /**
  * Public API to be called by the UITour code
  */
--- a/browser/components/uitour/test/browser_trackingProtection_tour.js
+++ b/browser/components/uitour/test/browser_trackingProtection_tour.js
@@ -20,49 +20,65 @@ let tests = [
     Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
     yield UrlClassifierTestUtils.addTestTrackers();
 
     registerCleanupFunction(function() {
       UrlClassifierTestUtils.cleanupTestTrackers();
       Services.prefs.clearUserPref("privacy.trackingprotection.enabled");
     });
   }),
+
   taskify(function* test_unblock_target() {
-    let popup = document.getElementById("UITourTooltip");
-
-    yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
-      let doc = content.document;
-      let iframe = doc.createElement("iframe");
-      iframe.setAttribute("id", "tracking-element");
-      iframe.setAttribute("src", "https://tracking.example.com/");
-      doc.body.insertBefore(iframe, doc.body.firstChild);
-    });
-
-    let currentTarget = "controlCenter-trackingUnblock";
-
-    let testTargetAvailability = function* (expectedAvailable) {
-      let data = yield getConfigurationPromise("availableTargets");
-      let available = (data.targets.indexOf(currentTarget) != -1);
-      is(available, expectedAvailable, "Target has expected availability.");
-    }
-    yield testTargetAvailability(false);
+    yield* checkToggleTarget("controlCenter-trackingUnblock");
+  }),
 
-    yield showMenuPromise("controlCenter");
-    yield testTargetAvailability(true);
-
-    yield showInfoPromise(currentTarget, "This is " + currentTarget,
-                          "My arrow should be on the side");
-    is(popup.popupBoxObject.alignmentPosition, "end_before",
-       "Check " + currentTarget + " position");
+  taskify(function* setup_block_target() {
+    // Preparation for test_block_target. These are separate since the reload
+    // interferes with UITour as it does a teardown. All we really care about
+    // is the permission manager entry but UITour tests shouldn't rely on that
+    // implementation detail.
+    TrackingProtection.disableForCurrentPage();
+  }),
 
-    let hideMenuPromise =
-        promisePanelElementHidden(window, gIdentityHandler._identityPopup);
-    gContentAPI.hideMenu("controlCenter");
-    yield hideMenuPromise;
-
-    ok(!is_visible(popup), "The tooltip should now be hidden.");
-    yield testTargetAvailability(false);
-
-    yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
-      content.document.getElementById("tracking-element").remove();
-    });
+  taskify(function* test_block_target() {
+    yield* checkToggleTarget("controlCenter-trackingBlock");
+    TrackingProtection.enableForCurrentPage();
   }),
 ];
+
+
+function* checkToggleTarget(targetID) {
+  let popup = document.getElementById("UITourTooltip");
+
+  yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
+    let doc = content.document;
+    let iframe = doc.createElement("iframe");
+    iframe.setAttribute("id", "tracking-element");
+    iframe.setAttribute("src", "https://tracking.example.com/");
+    doc.body.insertBefore(iframe, doc.body.firstChild);
+  });
+
+  let testTargetAvailability = function* (expectedAvailable) {
+    let data = yield getConfigurationPromise("availableTargets");
+    let available = (data.targets.indexOf(targetID) != -1);
+    is(available, expectedAvailable, "Target has expected availability.");
+  };
+  yield testTargetAvailability(false);
+  yield showMenuPromise("controlCenter");
+  yield testTargetAvailability(true);
+
+  yield showInfoPromise(targetID, "This is " + targetID,
+                        "My arrow should be on the side");
+  is(popup.popupBoxObject.alignmentPosition, "end_before",
+     "Check " + targetID + " position");
+
+  let hideMenuPromise =
+        promisePanelElementHidden(window, gIdentityHandler._identityPopup);
+  gContentAPI.hideMenu("controlCenter");
+  yield hideMenuPromise;
+
+  ok(!is_visible(popup), "The tooltip should now be hidden.");
+  yield testTargetAvailability(false);
+
+  yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
+    content.document.getElementById("tracking-element").remove();
+  });
+}
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -122,16 +122,26 @@
                onpopupshowing="DebuggerView.Options._onPopupShowing()"
                onpopuphiding="DebuggerView.Options._onPopupHiding()"
                onpopuphidden="DebuggerView.Options._onPopupHidden()">
       <menuitem id="auto-pretty-print"
                 type="checkbox"
                 label="&debuggerUI.autoPrettyPrint;"
                 accesskey="&debuggerUI.autoPrettyPrint.accesskey;"
                 command="toggleAutoPrettyPrint"/>
+      <menuitem id="pause-on-exceptions"
+                type="checkbox"
+                label="&debuggerUI.pauseExceptions;"
+                accesskey="&debuggerUI.pauseExceptions.accesskey;"
+                command="togglePauseOnExceptions"/>
+      <menuitem id="ignore-caught-exceptions"
+                type="checkbox"
+                label="&debuggerUI.ignoreCaughtExceptions;"
+                accesskey="&debuggerUI.ignoreCaughtExceptions.accesskey;"
+                command="toggleIgnoreCaughtExceptions"/>
       <menuitem id="show-panes-on-startup"
                 type="checkbox"
                 label="&debuggerUI.showPanesOnInit;"
                 accesskey="&debuggerUI.showPanesOnInit.accesskey;"
                 command="toggleShowPanesOnStartup"/>
       <menuitem id="show-vars-only-enum"
                 type="checkbox"
                 label="&debuggerUI.showOnlyEnum;"
@@ -333,19 +343,16 @@
                                  command="prettyPrintCommand"
                                  hidden="true"/>
                 </hbox>
                 <vbox class="devtools-separator"/>
                 <toolbarbutton id="toggle-breakpoints"
                                class="devtools-toolbarbutton"
                                tooltiptext="&debuggerUI.sources.toggleBreakpoints;"
                                command="toggleBreakpointsCommand"/>
-                <toolbarbutton id="toggle-pause-exceptions"
-                               class="devtools-toolbarbutton"
-                               command="togglePauseOnExceptionsCommand"/>
                 <toolbarbutton id="toggle-promise-debugger"
                                class="devtools-toolbarbutton"
                                tooltiptext="&debuggerUI.sources.togglePromiseDebugger;"
                                command="togglePromiseDebuggerCommand"
                                hidden="true"/>
               </toolbar>
             </tabpanel>
             <tabpanel id="callstack-tabpanel">
--- a/browser/devtools/debugger/test/browser_dbg_pause-exceptions-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-exceptions-01.js
@@ -3,37 +3,40 @@
 
 /**
  * Make sure that pausing on exceptions works.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pause-exceptions.html";
 
 let gTab, gPanel, gDebugger;
-let gFrames, gVariables, gPrefs;
+let gFrames, gVariables, gPrefs, gOptions;
 
 function test() {
   requestLongerTimeout(2);
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gVariables = gDebugger.DebuggerView.Variables;
     gPrefs = gDebugger.Prefs;
+    gOptions = gDebugger.DebuggerView.Options;
 
     is(gPrefs.pauseOnExceptions, false,
       "The pause-on-exceptions pref should be disabled by default.");
+    isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
+      "The pause-on-exceptions menu item should not be checked.");
 
     testPauseOnExceptionsDisabled()
-      .then(clickToPauseOnAllExceptions)
-      .then(testPauseOnAllExceptionsEnabled)
-      .then(clickToPauseOnUncaughtExceptions)
-      .then(testPauseOnUncaughtExceptionsEnabled)
-      .then(clickToStopPauseOnExceptions)
+      .then(enablePauseOnExceptions)
+      .then(disableIgnoreCaughtExceptions)
+      .then(testPauseOnExceptionsEnabled)
+      .then(disablePauseOnExceptions)
+      .then(enableIgnoreCaughtExceptions)
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testPauseOnExceptionsDisabled() {
@@ -74,62 +77,19 @@ function testPauseOnExceptionsDisabled()
     return finished;
   });
 
   generateMouseClickInTab(gTab, "content.document.querySelector('button')");
 
   return finished;
 }
 
-function testPauseOnUncaughtExceptionsEnabled() {
-  let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => {
-    info("Testing enabled pause-on-uncaught-exceptions only.");
-
-    is(gDebugger.gThreadClient.state, "paused",
-      "Should only be getting stack frames while paused (1).");
-    ok(isCaretPos(gPanel, 26),
-      "Should be paused on the debugger statement (1).");
-
-    let innerScope = gVariables.getScopeAtIndex(0);
-    let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
-
-    is(gFrames.itemCount, 1,
-      "Should have one frame.");
-    is(gVariables._store.length, 3,
-      "Should have three scopes.");
-
-    is(innerNodes[0].querySelector(".name").getAttribute("value"), "this",
-      "Should have the right property name for 'this'.");
-    is(innerNodes[0].querySelector(".value").getAttribute("value"), "<button>",
-      "Should have the right property value for 'this'.");
-
-    let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
-      isnot(gDebugger.gThreadClient.state, "paused",
-        "Should not be paused after resuming.");
-      ok(isCaretPos(gPanel, 26),
-        "Should be idle on the debugger statement.");
-
-      ok(true, "Frames were cleared, debugger didn't pause again.");
-    });
-
-    EventUtils.sendMouseEvent({ type: "mousedown" },
-      gDebugger.document.getElementById("resume"),
-      gDebugger);
-
-    return finished;
-  });
-
-  generateMouseClickInTab(gTab, "content.document.querySelector('button')");
-
-  return finished;
-}
-
-function testPauseOnAllExceptionsEnabled() {
+function testPauseOnExceptionsEnabled() {
   let finished = waitForCaretAndScopes(gPanel, 19).then(() => {
-    info("Testing enabled pause-on-all-exceptions.");
+    info("Testing enabled pause-on-exceptions.");
 
     is(gDebugger.gThreadClient.state, "paused",
       "Should only be getting stack frames while paused.");
     ok(isCaretPos(gPanel, 19),
       "Should be paused on the debugger statement.");
 
     let innerScope = gVariables.getScopeAtIndex(0);
     let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
@@ -140,17 +100,17 @@ function testPauseOnAllExceptionsEnabled
       "Should have three scopes.");
 
     is(innerNodes[0].querySelector(".name").getAttribute("value"), "<exception>",
       "Should have the right property name for <exception>.");
     is(innerNodes[0].querySelector(".value").getAttribute("value"), "Error",
       "Should have the right property value for <exception>.");
 
     let finished = waitForCaretAndScopes(gPanel, 26).then(() => {
-      info("Testing enabled pause-on-all-exceptions and resumed after pause.");
+      info("Testing enabled pause-on-exceptions and resumed after pause.");
 
       is(gDebugger.gThreadClient.state, "paused",
         "Should only be getting stack frames while paused.");
       ok(isCaretPos(gPanel, 26),
         "Should be paused on the debugger statement.");
 
       let innerScope = gVariables.getScopeAtIndex(0);
       let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
@@ -188,74 +148,93 @@ function testPauseOnAllExceptionsEnabled
     return finished;
   });
 
   generateMouseClickInTab(gTab, "content.document.querySelector('button')");
 
   return finished;
 }
 
-function clickToPauseOnAllExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function enablePauseOnExceptions() {
+  let deferred = promise.defer();
 
   gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Pause on uncaught exceptions",
-      "The button's tooltip text should be 'Pause on uncaught exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 1,
-      "The pause on exceptions button state variable should be 1");
+    is(gPrefs.pauseOnExceptions, true,
+      "The pause-on-exceptions pref should now be enabled.");
+    is(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
+      "The pause-on-exceptions menu item should now be checked.");
 
-      deferred.resolve();
+    ok(true, "Pausing on exceptions was enabled.");
+    deferred.resolve();
   });
 
-  pauseOnExceptionsButton.click();
+  gOptions._pauseOnExceptionsItem.setAttribute("checked", "true");
+  gOptions._togglePauseOnExceptions();
+
+  return deferred.promise;
+}
+
+function disablePauseOnExceptions() {
+  let deferred = promise.defer();
+
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.pauseOnExceptions, false,
+      "The pause-on-exceptions pref should now be disabled.");
+    isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
+      "The pause-on-exceptions menu item should now be unchecked.");
+
+    ok(true, "Pausing on exceptions was disabled.");
+    deferred.resolve();
+  });
+
+  gOptions._pauseOnExceptionsItem.setAttribute("checked", "false");
+  gOptions._togglePauseOnExceptions();
 
   return deferred.promise;
 }
 
-function clickToPauseOnUncaughtExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function enableIgnoreCaughtExceptions() {
+  let deferred = promise.defer();
 
-  gDebugger.gThreadClient.addOneTimeListener("resumed", () =>{
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Do not pause on exceptions",
-      "The button's tooltip text should be 'Do not pause on exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 2,
-      "The pause on exceptions button state variable should be 2");
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.ignoreCaughtExceptions, true,
+      "The ignore-caught-exceptions pref should now be enabled.");
+    is(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
+      "The ignore-caught-exceptions menu item should now be checked.");
 
-      deferred.resolve();
+    ok(true, "Ignore caught exceptions was enabled.");
+    deferred.resolve();
   });
-  pauseOnExceptionsButton.click();
+
+  gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "true");
+  gOptions._toggleIgnoreCaughtExceptions();
+
   return deferred.promise;
 }
 
-function clickToStopPauseOnExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function disableIgnoreCaughtExceptions() {
+  let deferred = promise.defer();
 
-  gDebugger.gThreadClient.addOneTimeListener("resumed", () =>{
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Pause on all exceptions",
-      "The button's tooltip text should be 'Pause on all exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 0,
-      "The pause on exceptions button state variable should be 0");
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.ignoreCaughtExceptions, false,
+      "The ignore-caught-exceptions pref should now be disabled.");
+    isnot(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
+      "The ignore-caught-exceptions menu item should now be unchecked.");
 
-      deferred.resolve();
+    ok(true, "Ignore caught exceptions was disabled.");
+    deferred.resolve();
   });
-  pauseOnExceptionsButton.click();
+
+  gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "false");
+  gOptions._toggleIgnoreCaughtExceptions();
+
   return deferred.promise;
 }
 
-function getPauseOnExceptionsButton() {
-  return gDebugger.document.getElementById("toggle-pause-exceptions");
-}
-
-
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gFrames = null;
   gVariables = null;
   gPrefs = null;
+  gOptions = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pause-exceptions-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-exceptions-02.js
@@ -1,48 +1,51 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
- * Make sure that pausing on exceptions works after tab reload.
+ * Make sure that pausing on exceptions works after reload.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_pause-exceptions.html";
 
 let gTab, gPanel, gDebugger;
-let gFrames, gVariables, gPrefs;
+let gFrames, gVariables, gPrefs, gOptions;
 
 function test() {
-  requestLongerTimeout(2);
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gVariables = gDebugger.DebuggerView.Variables;
     gPrefs = gDebugger.Prefs;
+    gOptions = gDebugger.DebuggerView.Options;
 
     is(gPrefs.pauseOnExceptions, false,
       "The pause-on-exceptions pref should be disabled by default.");
+    isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
+      "The pause-on-exceptions menu item should not be checked.");
 
-    clickToPauseOnAllExceptions()
+    enablePauseOnExceptions()
+      .then(disableIgnoreCaughtExceptions)
       .then(() => reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCE_SHOWN))
-      .then(testPauseOnAllExceptionsEnabledAfterReload)
-      .then(clickToPauseOnUncaughtExceptions)
-      .then(clickToStopPauseOnExceptions)
+      .then(testPauseOnExceptionsAfterReload)
+      .then(disablePauseOnExceptions)
+      .then(enableIgnoreCaughtExceptions)
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
-function testPauseOnAllExceptionsEnabledAfterReload() {
+function testPauseOnExceptionsAfterReload() {
   let finished = waitForCaretAndScopes(gPanel, 19).then(() => {
-    info("Testing enabled pause-on-all-exceptions.");
+    info("Testing enabled pause-on-exceptions.");
 
     is(gDebugger.gThreadClient.state, "paused",
       "Should only be getting stack frames while paused.");
     ok(isCaretPos(gPanel, 19),
       "Should be paused on the debugger statement.");
 
     let innerScope = gVariables.getScopeAtIndex(0);
     let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
@@ -53,17 +56,17 @@ function testPauseOnAllExceptionsEnabled
       "Should have three scopes.");
 
     is(innerNodes[0].querySelector(".name").getAttribute("value"), "<exception>",
       "Should have the right property name for <exception>.");
     is(innerNodes[0].querySelector(".value").getAttribute("value"), "Error",
       "Should have the right property value for <exception>.");
 
     let finished = waitForCaretAndScopes(gPanel, 26).then(() => {
-      info("Testing enabled pause-on-all-exceptions and resumed after pause.");
+      info("Testing enabled pause-on-exceptions and resumed after pause.");
 
       is(gDebugger.gThreadClient.state, "paused",
         "Should only be getting stack frames while paused.");
       ok(isCaretPos(gPanel, 26),
         "Should be paused on the debugger statement.");
 
       let innerScope = gVariables.getScopeAtIndex(0);
       let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
@@ -101,73 +104,93 @@ function testPauseOnAllExceptionsEnabled
     return finished;
   });
 
   generateMouseClickInTab(gTab, "content.document.querySelector('button')");
 
   return finished;
 }
 
-function clickToPauseOnAllExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function enablePauseOnExceptions() {
+  let deferred = promise.defer();
 
   gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Pause on uncaught exceptions",
-      "The button's tooltip text should be 'Pause on uncaught exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 1,
-      "The pause on exceptions button state variable should be 1");
+    is(gPrefs.pauseOnExceptions, true,
+      "The pause-on-exceptions pref should now be enabled.");
+    is(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
+      "The pause-on-exceptions menu item should now be checked.");
 
-      deferred.resolve();
+    ok(true, "Pausing on exceptions was enabled.");
+    deferred.resolve();
   });
 
-  pauseOnExceptionsButton.click();
+  gOptions._pauseOnExceptionsItem.setAttribute("checked", "true");
+  gOptions._togglePauseOnExceptions();
 
   return deferred.promise;
 }
 
-function clickToPauseOnUncaughtExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function disablePauseOnExceptions() {
+  let deferred = promise.defer();
 
-  gDebugger.gThreadClient.addOneTimeListener("resumed", () =>{
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Do not pause on exceptions",
-      "The button's tooltip text should be 'Do not pause on exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 2,
-      "The pause on exceptions button state variable should be 2");
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.pauseOnExceptions, false,
+      "The pause-on-exceptions pref should now be disabled.");
+    isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
+      "The pause-on-exceptions menu item should now be unchecked.");
 
-      deferred.resolve();
+    ok(true, "Pausing on exceptions was disabled.");
+    deferred.resolve();
   });
-  pauseOnExceptionsButton.click();
+
+  gOptions._pauseOnExceptionsItem.setAttribute("checked", "false");
+  gOptions._togglePauseOnExceptions();
+
   return deferred.promise;
 }
 
-function clickToStopPauseOnExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function enableIgnoreCaughtExceptions() {
+  let deferred = promise.defer();
 
-  gDebugger.gThreadClient.addOneTimeListener("resumed", () =>{
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Pause on all exceptions",
-      "The button's tooltip text should be 'Pause on all exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 0,
-      "The pause on exceptions button state variable should be 0");
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.ignoreCaughtExceptions, true,
+      "The ignore-caught-exceptions pref should now be enabled.");
+    is(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
+      "The ignore-caught-exceptions menu item should now be checked.");
 
-      deferred.resolve();
+    ok(true, "Ignore caught exceptions was enabled.");
+    deferred.resolve();
   });
-  pauseOnExceptionsButton.click();
+
+  gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "true");
+  gOptions._toggleIgnoreCaughtExceptions();
+
   return deferred.promise;
 }
 
-function getPauseOnExceptionsButton() {
-  return gDebugger.document.getElementById("toggle-pause-exceptions");
+function disableIgnoreCaughtExceptions() {
+  let deferred = promise.defer();
+
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.ignoreCaughtExceptions, false,
+      "The ignore-caught-exceptions pref should now be disabled.");
+    isnot(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
+      "The ignore-caught-exceptions menu item should now be unchecked.");
+
+    ok(true, "Ignore caught exceptions was disabled.");
+    deferred.resolve();
+  });
+
+  gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "false");
+  gOptions._toggleIgnoreCaughtExceptions();
+
+  return deferred.promise;
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gPanel = null;
   gDebugger = null;
   gFrames = null;
   gVariables = null;
   gPrefs = null;
+  gOptions = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_source-maps-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_source-maps-04.js
@@ -7,106 +7,87 @@
 
 const TAB_URL = EXAMPLE_URL + "doc_minified_bogus_map.html";
 const JS_URL = EXAMPLE_URL + "code_math_bogus_map.js";
 
 // This test causes an error to be logged in the console, which appears in TBPL
 // logs, so we are disabling that here.
 DevToolsUtils.reportingDisabled = true;
 
-let gPanel, gDebugger, gFrames, gSources, gPrefs;
+let gPanel, gDebugger, gFrames, gSources, gPrefs, gOptions;
 
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gSources = gDebugger.DebuggerView.Sources;
     gPrefs = gDebugger.Prefs;
+    gOptions = gDebugger.DebuggerView.Options;
 
     is(gPrefs.pauseOnExceptions, false,
       "The pause-on-exceptions pref should be disabled by default.");
+    isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
+      "The pause-on-exceptions menu item should not be checked.");
 
     waitForSourceShown(gPanel, JS_URL)
       .then(checkInitialSource)
-      .then(clickToPauseOnAllExceptions)
-      .then(clickToPauseOnUncaughtExceptions)
+      .then(enablePauseOnExceptions)
+      .then(disableIgnoreCaughtExceptions)
       .then(testSetBreakpoint)
       .then(reloadPage)
       .then(testHitBreakpoint)
-      .then(clickToStopPauseOnExceptions)
+      .then(enableIgnoreCaughtExceptions)
+      .then(disablePauseOnExceptions)
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function checkInitialSource() {
   isnot(gSources.selectedItem.attachment.source.url.indexOf("code_math_bogus_map.js"), -1,
     "The debugger should show the minified js file.");
 }
 
-function clickToPauseOnAllExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function enablePauseOnExceptions() {
+  let deferred = promise.defer();
 
   gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Pause on uncaught exceptions",
-      "The button's tooltip text should be 'Pause on uncaught exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 1,
-      "The pause on exceptions button state variable should be 1");
+    is(gPrefs.pauseOnExceptions, true,
+      "The pause-on-exceptions pref should now be enabled.");
 
-      deferred.resolve();
+    ok(true, "Pausing on exceptions was enabled.");
+    deferred.resolve();
   });
 
-  pauseOnExceptionsButton.click();
+  gOptions._pauseOnExceptionsItem.setAttribute("checked", "true");
+  gOptions._togglePauseOnExceptions();
 
   return deferred.promise;
 }
 
-function clickToPauseOnUncaughtExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
-
-  gDebugger.gThreadClient.addOneTimeListener("resumed", () =>{
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Do not pause on exceptions",
-      "The button's tooltip text should be 'Do not pause on exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 2,
-      "The pause on exceptions button state variable should be 2");
-
-      deferred.resolve();
-  });
-  pauseOnExceptionsButton.click();
-  return deferred.promise;
-}
-
-function clickToStopPauseOnExceptions() {
-  var deferred = promise.defer();
-  var pauseOnExceptionsButton = getPauseOnExceptionsButton();
+function disableIgnoreCaughtExceptions() {
+  let deferred = promise.defer();
 
   gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
-    is(pauseOnExceptionsButton.getAttribute("tooltiptext"),
-      "Pause on all exceptions",
-      "The button's tooltip text should be 'Pause on all exceptions'.");
-    is(pauseOnExceptionsButton.getAttribute("state"), 0,
-      "The pause on exceptions button state variable should be 0");
+    is(gPrefs.ignoreCaughtExceptions, false,
+      "The ignore-caught-exceptions pref should now be disabled.");
 
-      deferred.resolve();
+    ok(true, "Ignore caught exceptions was disabled.");
+    deferred.resolve();
   });
-  pauseOnExceptionsButton.click();
+
+  gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "false");
+  gOptions._toggleIgnoreCaughtExceptions();
+
   return deferred.promise;
 }
 
-function getPauseOnExceptionsButton() {
-  return gDebugger.document.getElementById("toggle-pause-exceptions");
-}
-
 function testSetBreakpoint() {
   let deferred = promise.defer();
   let sourceForm = getSourceForm(gSources, JS_URL);
   let source = gDebugger.gThreadClient.source(sourceForm);
 
   source.setBreakpoint({ line: 3, column: 18 }, aResponse => {
     ok(!aResponse.error,
       "Should be able to set a breakpoint in a js file.");
@@ -126,24 +107,76 @@ function reloadPage() {
 }
 
 function testHitBreakpoint() {
   let deferred = promise.defer();
 
   gDebugger.gThreadClient.resume(aResponse => {
     ok(!aResponse.error, "Shouldn't get an error resuming.");
     is(aResponse.type, "resumed", "Type should be 'resumed'.");
-    is(gFrames.itemCount, 2, "Should have two frames.");
+
+    waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => {
+      is(gFrames.itemCount, 2, "Should have two frames.");
 
+      // This is weird, but we need to let the debugger a chance to
+      // update first
+      executeSoon(() => {
+        gDebugger.gThreadClient.resume(() => {
+          gDebugger.gThreadClient.addOneTimeListener("paused", () => {
+            gDebugger.gThreadClient.resume(() => {
+              // We also need to make sure the next step doesn't add a
+              // "resumed" handler until this is completely finished
+              executeSoon(() => {
+                deferred.resolve();
+              });
+            });
+          });
+        });
+      });
+    });
+  });
+
+  return deferred.promise;
+}
+
+function enableIgnoreCaughtExceptions() {
+  let deferred = promise.defer();
+
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.ignoreCaughtExceptions, true,
+      "The ignore-caught-exceptions pref should now be enabled.");
+
+    ok(true, "Ignore caught exceptions was enabled.");
     deferred.resolve();
   });
 
+  gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "true");
+  gOptions._toggleIgnoreCaughtExceptions();
+
+  return deferred.promise;
+}
+
+function disablePauseOnExceptions() {
+  let deferred = promise.defer();
+
+  gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
+    is(gPrefs.pauseOnExceptions, false,
+      "The pause-on-exceptions pref should now be disabled.");
+
+    ok(true, "Pausing on exceptions was disabled.");
+    deferred.resolve();
+  });
+
+  gOptions._pauseOnExceptionsItem.setAttribute("checked", "false");
+  gOptions._togglePauseOnExceptions();
+
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
   gPanel = null;
   gDebugger = null;
   gFrames = null;
   gSources = null;
   gPrefs = null;
+  gOptions = null;
   DevToolsUtils.reportingDisabled = false;
 });
--- a/browser/devtools/debugger/views/options-view.js
+++ b/browser/devtools/debugger/views/options-view.js
@@ -12,39 +12,45 @@ const POPUP_HIDDEN_DELAY = 100; // ms
  */
 function OptionsView(DebuggerController, DebuggerView) {
   dumpn("OptionsView was instantiated");
 
   this.DebuggerController = DebuggerController;
   this.DebuggerView = DebuggerView;
 
   this._toggleAutoPrettyPrint = this._toggleAutoPrettyPrint.bind(this);
+  this._togglePauseOnExceptions = this._togglePauseOnExceptions.bind(this);
+  this._toggleIgnoreCaughtExceptions = this._toggleIgnoreCaughtExceptions.bind(this);
   this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this);
   this._toggleShowVariablesOnlyEnum = this._toggleShowVariablesOnlyEnum.bind(this);
   this._toggleShowVariablesFilterBox = this._toggleShowVariablesFilterBox.bind(this);
   this._toggleShowOriginalSource = this._toggleShowOriginalSource.bind(this);
   this._toggleAutoBlackBox = this._toggleAutoBlackBox.bind(this);
 }
 
 OptionsView.prototype = {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function() {
     dumpn("Initializing the OptionsView");
 
     this._button = document.getElementById("debugger-options");
     this._autoPrettyPrint = document.getElementById("auto-pretty-print");
+    this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions");
+    this._ignoreCaughtExceptionsItem = document.getElementById("ignore-caught-exceptions");
     this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup");
     this._showVariablesOnlyEnumItem = document.getElementById("show-vars-only-enum");
     this._showVariablesFilterBoxItem = document.getElementById("show-vars-filter-box");
     this._showOriginalSourceItem = document.getElementById("show-original-source");
     this._autoBlackBoxItem = document.getElementById("auto-black-box");
 
     this._autoPrettyPrint.setAttribute("checked", Prefs.autoPrettyPrint);
+    this._pauseOnExceptionsItem.setAttribute("checked", Prefs.pauseOnExceptions);
+    this._ignoreCaughtExceptionsItem.setAttribute("checked", Prefs.ignoreCaughtExceptions);
     this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup);
     this._showVariablesOnlyEnumItem.setAttribute("checked", Prefs.variablesOnlyEnumVisible);
     this._showVariablesFilterBoxItem.setAttribute("checked", Prefs.variablesSearchboxVisible);
     this._showOriginalSourceItem.setAttribute("checked", Prefs.sourceMapsEnabled);
     this._autoBlackBoxItem.setAttribute("checked", Prefs.autoBlackBox);
 
     this._addCommands();
   },
@@ -58,16 +64,18 @@ OptionsView.prototype = {
   },
 
   /**
    * Add commands that XUL can fire.
    */
   _addCommands: function() {
     XULUtils.addCommands(document.getElementById('debuggerCommands'), {
       toggleAutoPrettyPrint: () => this._toggleAutoPrettyPrint(),
+      togglePauseOnExceptions: () => this._togglePauseOnExceptions(),
+      toggleIgnoreCaughtExceptions: () => this._toggleIgnoreCaughtExceptions(),
       toggleShowPanesOnStartup: () => this._toggleShowPanesOnStartup(),
       toggleShowOnlyEnum: () => this._toggleShowVariablesOnlyEnum(),
       toggleShowVariablesFilterBox: () => this._toggleShowVariablesFilterBox(),
       toggleShowOriginalSource: () => this._toggleShowOriginalSource(),
       toggleAutoBlackBox: () =>  this._toggleAutoBlackBox()
     });
   },
 
@@ -97,16 +105,37 @@ OptionsView.prototype = {
    * Listener handling the 'auto pretty print' menuitem command.
    */
   _toggleAutoPrettyPrint: function(){
     Prefs.autoPrettyPrint =
       this._autoPrettyPrint.getAttribute("checked") == "true";
   },
 
   /**
+   * Listener handling the 'pause on exceptions' menuitem command.
+   */
+  _togglePauseOnExceptions: function() {
+    Prefs.pauseOnExceptions =
+      this._pauseOnExceptionsItem.getAttribute("checked") == "true";
+
+    this.DebuggerController.activeThread.pauseOnExceptions(
+      Prefs.pauseOnExceptions,
+      Prefs.ignoreCaughtExceptions);
+  },
+
+  _toggleIgnoreCaughtExceptions: function() {
+    Prefs.ignoreCaughtExceptions =
+      this._ignoreCaughtExceptionsItem.getAttribute("checked") == "true";
+
+    this.DebuggerController.activeThread.pauseOnExceptions(
+      Prefs.pauseOnExceptions,
+      Prefs.ignoreCaughtExceptions);
+  },
+
+  /**
    * Listener handling the 'show panes on startup' menuitem command.
    */
   _toggleShowPanesOnStartup: function() {
     Prefs.panesVisibleOnStartup =
       this._showPanesOnStartupItem.getAttribute("checked") == "true";
   },
 
   /**
@@ -164,16 +193,17 @@ OptionsView.prototype = {
           useSourceMaps: Prefs.sourceMapsEnabled,
           autoBlackBox: pref
         });
       }, POPUP_HIDDEN_DELAY);
     });
   },
 
   _button: null,
+  _pauseOnExceptionsItem: null,
   _showPanesOnStartupItem: null,
   _showVariablesOnlyEnumItem: null,
   _showVariablesFilterBoxItem: null,
   _showOriginalSourceItem: null,
   _autoBlackBoxItem: null
 };
 
 DebuggerView.Options = new OptionsView(DebuggerController, DebuggerView);
--- a/browser/devtools/debugger/views/sources-view.js
+++ b/browser/devtools/debugger/views/sources-view.js
@@ -3,37 +3,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 // Maps known URLs to friendly source group names and put them at the
 // bottom of source list.
 const KNOWN_SOURCE_GROUPS = {
   "Add-on SDK": "resource://gre/modules/commonjs/",
 };
-const DO_NOT_PAUSE_ON_EXCEPTIONS = 0;
-const PAUSE_ON_ALL_EXCEPTIONS = 1;
-const PAUSE_ON_UNCAUGHT_EXCEPTIONS = 2;
 
 KNOWN_SOURCE_GROUPS[L10N.getStr("anonymousSourcesLabel")] = "anonymous";
 
 /**
  * Functions handling the sources UI.
  */
 function SourcesView(DebuggerController, DebuggerView) {
   dumpn("SourcesView was instantiated");
 
   this.Breakpoints = DebuggerController.Breakpoints;
   this.SourceScripts = DebuggerController.SourceScripts;
   this.DebuggerView = DebuggerView;
-  this.DebuggerController = DebuggerController;
 
   this.togglePrettyPrint = this.togglePrettyPrint.bind(this);
   this.toggleBlackBoxing = this.toggleBlackBoxing.bind(this);
   this.toggleBreakpoints = this.toggleBreakpoints.bind(this);
-  this.togglePauseOnExceptions = this.togglePauseOnExceptions.bind(this);
 
   this._onEditorLoad = this._onEditorLoad.bind(this);
   this._onEditorUnload = this._onEditorUnload.bind(this);
   this._onEditorCursorActivity = this._onEditorCursorActivity.bind(this);
   this._onSourceSelect = this._onSourceSelect.bind(this);
   this._onStopBlackBoxing = this._onStopBlackBoxing.bind(this);
   this._onBreakpointRemoved = this._onBreakpointRemoved.bind(this);
   this._onBreakpointClick = this._onBreakpointClick.bind(this);
@@ -56,40 +51,33 @@ SourcesView.prototype = Heritage.extend(
     this.widget = new SideMenuWidget(document.getElementById("sources"), {
       contextMenu: document.getElementById("debuggerSourcesContextMenu"),
       showArrows: true
     });
 
     this._unnamedSourceIndex = 0;
     this.emptyText = L10N.getStr("noSourcesText");
     this._blackBoxCheckboxTooltip = L10N.getStr("blackBoxCheckboxTooltip");
-    this._pauseAllExceptionsTooltip = L10N.getStr("pauseAllExceptionsTooltip");
-    this._pauseUncaughtExceptionsTooltip = L10N.getStr("pauseUncaughtExceptionsTooltip");
-    this._pauseNoExceptionsTooltip = L10N.getStr("pauseNoExceptionsTooltip");
 
     this._commandset = document.getElementById("debuggerCommands");
     this._popupset = document.getElementById("debuggerPopupset");
     this._cmPopup = document.getElementById("sourceEditorContextMenu");
     this._cbPanel = document.getElementById("conditional-breakpoint-panel");
     this._cbTextbox = document.getElementById("conditional-breakpoint-panel-textbox");
     this._blackBoxButton = document.getElementById("black-box");
     this._stopBlackBoxButton = document.getElementById("black-boxed-message-button");
     this._prettyPrintButton = document.getElementById("pretty-print");
     this._toggleBreakpointsButton = document.getElementById("toggle-breakpoints");
-    this._togglePauseOnExceptionsButton = document.getElementById("toggle-pause-exceptions");
     this._newTabMenuItem = document.getElementById("debugger-sources-context-newtab");
     this._copyUrlMenuItem = document.getElementById("debugger-sources-context-copyurl");
 
     if (Prefs.prettyPrintEnabled) {
       this._prettyPrintButton.removeAttribute("hidden");
     }
 
-    this._togglePauseOnExceptionsButton.setAttribute("tooltiptext", this._pauseAllExceptionsTooltip);
-    this._togglePauseOnExceptionsButton.setAttribute("state", DO_NOT_PAUSE_ON_EXCEPTIONS);
-
     window.on(EVENTS.EDITOR_LOADED, this._onEditorLoad, false);
     window.on(EVENTS.EDITOR_UNLOADED, this._onEditorUnload, false);
     this.widget.addEventListener("select", this._onSourceSelect, false);
     this._stopBlackBoxButton.addEventListener("click", this._onStopBlackBoxing, false);
     this._cbPanel.addEventListener("popupshowing", this._onConditionalPopupShowing, false);
     this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
     this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
     this._cbTextbox.addEventListener("keypress", this._onConditionalTextboxKeyPress, false);
@@ -145,17 +133,16 @@ SourcesView.prototype = Heritage.extend(
   _addCommands: function() {
     XULUtils.addCommands(this._commandset, {
       addBreakpointCommand: e => this._onCmdAddBreakpoint(e),
       addConditionalBreakpointCommand: e => this._onCmdAddConditionalBreakpoint(e),
       blackBoxCommand: () => this.toggleBlackBoxing(),
       unBlackBoxButton: () => this._onStopBlackBoxing(),
       prettyPrintCommand: () => this.togglePrettyPrint(),
       toggleBreakpointsCommand: () =>this.toggleBreakpoints(),
-      togglePauseOnExceptionsCommand: () => this.togglePauseOnExceptions(),
       togglePromiseDebuggerCommand: () => this.togglePromiseDebugger(),
       nextSourceCommand: () => this.selectNextItem(),
       prevSourceCommand: () => this.selectPrevItem()
     });
   },
 
   /**
    * Sets the preferred location to be selected in this sources container.
@@ -624,47 +611,16 @@ SourcesView.prototype = Heritage.extend(
       this._toggleBreakpointsButton.setAttribute("checked", true);
       this._onDisableAll();
     } else {
       this._toggleBreakpointsButton.removeAttribute("checked");
       this._onEnableAll();
     }
   },
 
-  /**
-   * Toggles the pause on exceptions functionality
-   */
-  togglePauseOnExceptions: function() {
-    let state = Number(this._togglePauseOnExceptionsButton.getAttribute("state"));
-    let tooltip;
-
-    state = ++state % 3;
-
-    if (state === DO_NOT_PAUSE_ON_EXCEPTIONS) {
-      tooltip = this._pauseAllExceptionsTooltip;
-      Prefs.pauseOnExceptions = false;
-      Prefs.ignoreCaughtExceptions = false;
-    } else if ( state === PAUSE_ON_ALL_EXCEPTIONS) {
-      tooltip = this._pauseUncaughtExceptionsTooltip;
-      Prefs.pauseOnExceptions = true;
-      Prefs.ignoreCaughtExceptions = false;
-    } else {
-      tooltip = this._pauseNoExceptionsTooltip;
-      Prefs.pauseOnExceptions = true;
-      Prefs.ignoreCaughtExceptions = true;
-    }
-
-    this.DebuggerController.activeThread.pauseOnExceptions(
-      Prefs.pauseOnExceptions,
-      Prefs.ignoreCaughtExceptions);
-
-    this._togglePauseOnExceptionsButton.setAttribute("tooltiptext", tooltip);
-    this._togglePauseOnExceptionsButton.setAttribute("state", state);
-  },
-
   togglePromiseDebugger: function() {
     if (Prefs.promiseDebuggerEnabled) {
       let promisePane = this.DebuggerView._promisePane;
       promisePane.hidden = !promisePane.hidden;
 
       this.DebuggerView._initializePromiseDebugger();
     }
   },
--- a/browser/devtools/debugger/views/stack-frames-view.js
+++ b/browser/devtools/debugger/views/stack-frames-view.js
@@ -238,13 +238,12 @@ StackFramesView.prototype = Heritage.ext
       this.dirty = false;
 
       // Loads more stack frames from the debugger server cache.
       DebuggerController.StackFrames.addMoreFrames();
     }
   },
 
   _mirror: null,
-  _prevBlackBoxedUrl: null,
-  _popupset: null
+  _prevBlackBoxedUrl: null
 });
 
 DebuggerView.StackFrames = new StackFramesView(DebuggerController, DebuggerView);
--- a/browser/devtools/performance/modules/logic/actors.js
+++ b/browser/devtools/performance/modules/logic/actors.js
@@ -366,22 +366,17 @@ MemoryFrontFacade.prototype = {
     if ((yield this.getState()) !== "attached") {
       deferred.resolve();
       return;
     }
 
     let memoryData = yield this.getAllocations();
     // Match the signature of the TimelineFront events, with "timeline-data"
     // being the event name, and the second argument describing the type.
-    this.emit("timeline-data", "allocations", {
-      sites: memoryData.allocations,
-      timestamps: memoryData.allocationsTimestamps,
-      frames: memoryData.frames,
-      counts: memoryData.counts
-    });
+    this.emit("timeline-data", "allocations", memoryData);
 
     deferred.resolve();
   }),
 
   toString: () => "[object MemoryFrontFacade]"
 };
 
 // Bind all the methods that directly proxy to the actor
--- a/browser/devtools/performance/modules/logic/io.js
+++ b/browser/devtools/performance/modules/logic/io.js
@@ -140,17 +140,17 @@ function convertLegacyData (legacyData) 
   // fields just are empty arrays or objects.
   let data = {
     label: profilerData.profilerLabel,
     duration: recordingDuration,
     markers: [],
     frames: [],
     memory: [],
     ticks: ticksData,
-    allocations: { sites: [], timestamps: [], frames: [], counts: [] },
+    allocations: { sites: [], timestamps: [], frames: [] },
     profile: profilerData.profile,
     // Fake a configuration object here if there's tick data,
     // so that it can be rendered
     configuration: {
       withTicks: !!ticksData.length,
       withMarkers: false,
       withMemory: false,
       withAllocations: false
--- a/browser/devtools/performance/modules/logic/recording-model.js
+++ b/browser/devtools/performance/modules/logic/recording-model.js
@@ -111,17 +111,17 @@ RecordingModel.prototype = {
     this._bufferPercent = info.position !== void 0 ? 0 : null;
 
     this._recording = true;
 
     this._markers = [];
     this._frames = [];
     this._memory = [];
     this._ticks = [];
-    this._allocations = { sites: [], timestamps: [], frames: [], counts: [] };
+    this._allocations = { sites: [], timestamps: [], frames: [] };
   },
 
   /**
    * Called when the signal was sent to the front to no longer record more
    * data, and begin fetching the data. There's some delay during fetching,
    * even though the recording is stopped, the model is not yet completed until
    * all the data is fetched.
    */
@@ -365,23 +365,27 @@ RecordingModel.prototype = {
         this._ticks = timestamps;
         break;
       }
       // Accumulate allocation sites into an array. Furthermore, the timestamps
       // do not have a zero epoch, and are microseconds instead of milliseconds,
       // so offset all of them by the start time, also converting from µs to ms.
       case "allocations": {
         if (!config.withAllocations) { break; }
-        let [{ sites, timestamps, frames, counts }] = data;
+        let [{
+          allocations: sites,
+          allocationsTimestamps: timestamps,
+          frames,
+        }] = data;
+
         let timeOffset = this._memoryStartTime;
         RecordingUtils.offsetAndScaleTimestamps(timestamps, timeOffset);
         pushAll(this._allocations.sites, sites);
         pushAll(this._allocations.timestamps, timestamps);
         pushAll(this._allocations.frames, frames);
-        pushAll(this._allocations.counts, counts);
         break;
       }
     }
   },
 
   toString: () => "[object RecordingModel]"
 };
 
--- a/browser/devtools/performance/modules/logic/recording-utils.js
+++ b/browser/devtools/performance/modules/logic/recording-utils.js
@@ -129,17 +129,17 @@ let gProfileThreadFromAllocationCache = 
  *         The "profile" describing the allocations log.
  */
 function getProfileThreadFromAllocations(allocations) {
   let cached = gProfileThreadFromAllocationCache.get(allocations);
   if (cached) {
     return cached;
   }
 
-  let { sites, timestamps, frames, counts } = allocations;
+  let { sites, timestamps, frames } = allocations;
   let uniqueStrings = new UniqueStrings();
 
   // Convert allocation frames to the the stack and frame tables expected by
   // the profiler format.
   //
   // Since the allocations log is already presented as a tree, we would be
   // wasting time if we jumped through the same hoops as deflateProfile below
   // and instead use the existing structure of the allocations log to build up
@@ -215,27 +215,37 @@ function getProfileThreadFromAllocations
     if (frames[stackIndex]) {
       samples[writePos++] = [stackIndex, timestamps[i]];
     }
   }
   samples.length = writePos;
 
   let thread = {
     name: "allocations",
-    samples: samplesWithSchema(samples),
+    samples: allocationsWithSchema(samples),
     stackTable: stackTableWithSchema(stackTable),
     frameTable: frameTableWithSchema(frameTable),
-    stringTable: uniqueStrings.stringTable,
-    allocationsTable: counts
+    stringTable: uniqueStrings.stringTable
   };
 
   gProfileThreadFromAllocationCache.set(allocations, thread);
   return thread;
 }
 
+function allocationsWithSchema (data) {
+  let slot = 0;
+  return {
+    schema: {
+      stack: slot++,
+      time: slot++,
+    },
+    data: data
+  };
+}
+
 /**
  * Deduplicates a profile by deduplicating stacks, frames, and strings.
  *
  * This is used to adapt version 2 profiles from the backend to version 3, for
  * use with older Geckos (like B2G).
  *
  * Note that the schemas used by this must be kept in sync with schemas used
  * by the C++ UniqueStacks class in tools/profiler/ProfileEntry.cpp.
--- a/browser/devtools/performance/test/browser_perf-allocations-to-samples.js
+++ b/browser/devtools/performance/test/browser_perf-allocations-to-samples.js
@@ -34,31 +34,25 @@ let TEST_DATA = {
       parent: 1
     }, {
       source: "C",
       line: 5,
       column: 6,
       functionDisplayName: null,
       parent: 2
     }
-  ],
-  counts: [11, 22, 33, 44]
+  ]
 };
 
 let EXPECTED_OUTPUT = {
   name: "allocations",
   samples: {
     "schema": {
       "stack": 0,
       "time": 1,
-      "responsiveness": 2,
-      "rss": 3,
-      "uss": 4,
-      "frameNumber": 5,
-      "power": 6
     },
     data: [
       [ 1, 150 ],
       [ 2, 200 ],
       [ 3, 250 ]
     ]
   },
   stackTable: {
@@ -88,15 +82,9 @@ let EXPECTED_OUTPUT = {
       [ 2 ]
     ]
   },
   "stringTable": [
     "x (A:1:2)",
     "y (B:3:4)",
     "C:5:6"
   ],
-  "allocationsTable": [
-    11,
-    22,
-    33,
-    44
-  ]
 };
--- a/browser/devtools/performance/test/browser_perf-compatibility-02.js
+++ b/browser/devtools/performance/test/browser_perf-compatibility-02.js
@@ -34,17 +34,16 @@ let test = Task.async(function*() {
 
   isEmptyArray(markers, "markers");
   isEmptyArray(frames, "frames");
   isEmptyArray(memory, "memory");
   isEmptyArray(ticks, "ticks");
   isEmptyArray(allocations.sites, "allocations.sites");
   isEmptyArray(allocations.timestamps, "allocations.timestamps");
   isEmptyArray(allocations.frames, "allocations.frames");
-  isEmptyArray(allocations.counts, "allocations.counts");
 
   let sampleCount = 0;
 
   for (let thread of profile.threads) {
     info("Checking thread: " + thread.name);
 
     for (let sample of thread.samples.data) {
       sampleCount++;
--- a/browser/devtools/performance/test/browser_perf-compatibility-04.js
+++ b/browser/devtools/performance/test/browser_perf-compatibility-04.js
@@ -32,17 +32,16 @@ let test = Task.async(function*() {
 
   is(label, "", "Empty label for mock.");
   is(typeof duration, "number", "duration is a number");
   ok(duration > 0, "duration is not 0");
 
   isEmptyArray(allocations.sites, "allocations.sites");
   isEmptyArray(allocations.timestamps, "allocations.timestamps");
   isEmptyArray(allocations.frames, "allocations.frames");
-  isEmptyArray(allocations.counts, "allocations.counts");
 
   let sampleCount = 0;
 
   for (let thread of profile.threads) {
     info("Checking thread: " + thread.name);
 
     for (let sample of thread.samples.data) {
       sampleCount++;
--- a/browser/devtools/performance/test/browser_perf-compatibility-08.js
+++ b/browser/devtools/performance/test/browser_perf-compatibility-08.js
@@ -49,17 +49,16 @@ function *testMockMemory () {
     "Recording configuration set by target's support, not by UI prefs [No Memory Actor: withTicks]");
 
   ok(markers.length > 0, "markers exist.");
   ok(ticks.length > 0, "ticks exist.");
   isEmptyArray(memory, "memory");
   isEmptyArray(allocations.sites, "allocations.sites");
   isEmptyArray(allocations.timestamps, "allocations.timestamps");
   isEmptyArray(allocations.frames, "allocations.frames");
-  isEmptyArray(allocations.counts, "allocations.counts");
 
   is($("#overview-pane").hidden, false,
     "overview pane not hidden when server not supporting memory actors, yet UI prefs request them.");
   is($("#select-waterfall-view").hidden, false,
     "waterfall view button not hidden when memory mocked, and UI prefs enable them");
   is($("#select-js-calltree-view").hidden, false,
     "jscalltree view button not hidden when memory mocked, and UI prefs enable them");
   is($("#select-js-flamegraph-view").hidden, false,
@@ -106,17 +105,16 @@ function *testMockMemoryAndTimeline() {
   is(config.withTicks, false,
     "Recording configuration set by target's support, not by UI prefs [No Memory/Timeline Actor: withTicks]");
   isEmptyArray(markers, "markers");
   isEmptyArray(ticks, "ticks");
   isEmptyArray(memory, "memory");
   isEmptyArray(allocations.sites, "allocations.sites");
   isEmptyArray(allocations.timestamps, "allocations.timestamps");
   isEmptyArray(allocations.frames, "allocations.frames");
-  isEmptyArray(allocations.counts, "allocations.counts");
 
   is($("#overview-pane").hidden, true,
     "overview pane hidden when server not supporting memory/timeline actors, yet UI prefs request them.");
   is($("#select-waterfall-view").hidden, true,
     "waterfall view button hidden when memory/timeline mocked, and UI prefs enable them");
   is($("#select-js-calltree-view").hidden, false,
     "jscalltree view button not hidden when memory/timeline mocked, and UI prefs enable them");
   is($("#select-js-flamegraph-view").hidden, false,
--- a/browser/devtools/performance/test/browser_perf_recordings-io-04.js
+++ b/browser/devtools/performance/test/browser_perf_recordings-io-04.js
@@ -125,17 +125,17 @@ let test = Task.async(function*() {
   let expected = Object.create({
     label: "",
     duration: 10000,
     markers: [].toSource(),
     frames: [].toSource(),
     memory: [].toSource(),
     ticks: TICKS_DATA.toSource(),
     profile: RecordingUtils.deflateProfile(JSON.parse(JSON.stringify(PROFILER_DATA))).toSource(),
-    allocations: ({sites:[], timestamps:[], frames:[], counts:[]}).toSource(),
+    allocations: ({sites:[], timestamps:[], frames:[]}).toSource(),
     withTicks: true,
     withMemory: false,
     sampleFrequency: void 0
   });
 
   for (let field in expected) {
     if (!!~["withTicks", "withMemory", "sampleFrequency"].indexOf(field)) {
       is(importedData.configuration[field], expected[field], `${field} successfully converted in legacy import.`);
--- a/browser/locales/en-US/chrome/browser/aboutPrivateBrowsing.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutPrivateBrowsing.dtd
@@ -1,32 +1,50 @@
 <!-- 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/. -->
 
-<!ENTITY aboutPrivateBrowsing.title            "You're browsing privately">
-<!ENTITY aboutPrivateBrowsing.title.normal     "Open a private window?">
-
-<!ENTITY aboutPrivateBrowsing.subtitle         "&brandShortName; won't remember any history for this window.">
-<!ENTITY aboutPrivateBrowsing.subtitle.normal  "&brandShortName; won't remember any history for private windows.">
-
-<!ENTITY aboutPrivateBrowsing.description      "That includes browsing history, search history, download history, web form history, cookies, and temporary internet files. However, files you download and bookmarks you make will be kept.">
-
-<!ENTITY aboutPrivateBrowsing.shortdescription "&brandShortName; won't remember any history for this window, but will keep any files you download and bookmarks you make. (Please note that your employer or internet service provider can still track the pages you visit.)">
-
 <!ENTITY aboutPrivateBrowsing.notPrivate       "You are currently not in a private window.">
-
-<!ENTITY aboutPrivateBrowsing.moreInfo         "While this computer won't have a record of your browsing history, your employer or internet service provider can still track the pages you visit.">
-<!ENTITY aboutPrivateBrowsing.learnMore        "Learn More.">
-
 <!ENTITY privatebrowsingpage.openPrivateWindow.label "Open a Private Window">
 <!ENTITY privatebrowsingpage.openPrivateWindow.accesskey "P">
 
-<!ENTITY trackingProtection.subtitle           "Now with Tracking Protection">
+<!ENTITY privateBrowsing.title                 "Private Browsing">
+
+<!-- LOCALIZATION NOTE (aboutPrivateBrowsing.width):
+     Width of the Private Browsing section.
+     -->
+<!ENTITY aboutPrivateBrowsing.width            "25em">
+<!ENTITY aboutPrivateBrowsing.title            "You're browsing privately">
+<!ENTITY aboutPrivateBrowsing.subtitle         "&brandShortName; won't remember any history for this window.">
 
-<!ENTITY trackingProtection.description        "Tracking Protection will block content that tracks your browsing activity so you don't have to worry about it being shared across websites.">
+<!ENTITY aboutPrivateBrowsing.info.forgotten   "Forgotten">
+<!ENTITY aboutPrivateBrowsing.info.history     "History">
+<!ENTITY aboutPrivateBrowsing.info.search      "Search">
+<!ENTITY aboutPrivateBrowsing.info.cookies     "Cookies">
+<!ENTITY aboutPrivateBrowsing.info.temporaryFiles "Temporary Files">
+
+<!ENTITY aboutPrivateBrowsing.info.kept        "Kept">
+<!ENTITY aboutPrivateBrowsing.info.downloads   "Downloads">
+<!ENTITY aboutPrivateBrowsing.info.bookmarks   "Bookmarks">
 
-<!ENTITY trackingProtection.showPreferences    "Privacy Preferences">
+<!ENTITY aboutPrivateBrowsing.note             "Your employer or Internet service provider can still track the pages you visit.">
+<!ENTITY aboutPrivateBrowsing.learnMore        "Learn More.">
+
+<!-- LOCALIZATION NOTE (trackingProtection.width):
+     Width of the Tracking Protection section. This should be enough to
+     accommodate the title as well as the enabled or disabled indicator.
+     -->
+<!ENTITY trackingProtection.width              "22em">
+<!ENTITY trackingProtection.title              "Tracking Protection">
 
-<!ENTITY trackingProtection.startTour          "See what's new">
+<!-- LOCALIZATION NOTE (trackingProtection.state.width):
+     Width of the element representing the enabled or disabled indicator.
+     -->
+<!ENTITY trackingProtection.state.width        "6ch">
+<!ENTITY trackingProtection.state.enabled      "ON">
+<!ENTITY trackingProtection.state.disabled     "OFF">
 
-<!ENTITY trackingProtection.enable.label       "Turn on Tracking Protection">
-<!ENTITY trackingProtection.enable.accesskey   "T">
+<!ENTITY trackingProtection.description.enabled "Private Windows now block content that tracks your browsing activity.">
+<!ENTITY trackingProtection.description.disabled "Private Windows will not block content that tracks your browsing activity.">
+
+<!ENTITY trackingProtection.disable            "Turn Tracking Protection Off">
+<!ENTITY trackingProtection.enable             "Turn Tracking Protection On">
+<!ENTITY trackingProtection.startTour          "See how this works">
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -801,19 +801,19 @@ you can use these alternative items. Oth
 <!ENTITY mixedContentBlocked2.options "Options">
 <!ENTITY mixedContentBlocked2.unblock.label "Disable protection for now">
 <!ENTITY mixedContentBlocked2.unblock.accesskey "D">
 <!ENTITY mixedContentBlocked2.block.label "Enable protection">
 <!ENTITY mixedContentBlocked2.block.accesskey "E">
 <!ENTITY mixedContentBlocked2.disabled.message "Protection is disabled">
 
 <!ENTITY trackingProtection.title "Tracking Protection">
-<!ENTITY trackingProtection.detectedBlocked2 "&brandShortName; is blocking attempts to track your browsing.">
-<!ENTITY trackingProtection.detectedNotBlocked2 "This site includes content that tracks your browsing. You have disabled protection.">
-<!ENTITY trackingProtection.notDetected2 "This site doesn’t include any content that tracks your browsing.">
+<!ENTITY trackingProtection.detectedBlocked3 "&brandShortName; is blocking parts of the page that may track your browsing.">
+<!ENTITY trackingProtection.detectedNotBlocked3 "This site includes elements that may track your browsing. You have disabled protection.">
+<!ENTITY trackingProtection.notDetected3 "No tracking elements detected on this page.">
 <!-- LOCALIZATION NOTE (trackingProtection.unblock.label, trackingProtection.unblock.accesskey):
      The associated button with this label and accesskey is only shown when opening the control
      center while looking at a site with trackers in NON-private browsing mode. -->
 <!ENTITY trackingProtection.unblock.label "Disable protection for this site">
 <!ENTITY trackingProtection.unblock.accesskey "D">
 <!-- LOCALIZATION NOTE (trackingProtection.unblockPrivate.label, trackingProtection.unblockPrivate.accesskey):
      The associated button with this label and accesskey is only shown when opening the control
      center while looking at a site with trackers in PRIVATE browsing mode. -->
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -61,16 +61,26 @@
 <!-- LOCALIZATION NOTE (debuggerUI.clearButton): This is the label for
   -  the button that clears the collected tracing data in the tracing tab. -->
 <!ENTITY debuggerUI.clearButton "Clear">
 
 <!-- LOCALIZATION NOTE (debuggerUI.clearButton.tooltip): This is the tooltip for
   -  the button that clears the collected tracing data in the tracing tab. -->
 <!ENTITY debuggerUI.clearButton.tooltip "Clear the collected traces">
 
+<!-- LOCALIZATION NOTE (debuggerUI.pauseExceptions): This is the label for the
+  -  checkbox that toggles pausing on exceptions. -->
+<!ENTITY debuggerUI.pauseExceptions           "Pause on Exceptions">
+<!ENTITY debuggerUI.pauseExceptions.accesskey "E">
+
+<!-- LOCALIZATION NOTE (debuggerUI.ignoreCaughtExceptions): This is the label for the
+  -  checkbox that toggles ignoring caught exceptions. -->
+<!ENTITY debuggerUI.ignoreCaughtExceptions           "Ignore Caught Exceptions">
+<!ENTITY debuggerUI.ignoreCaughtExceptions.accesskey "C">
+
 <!-- LOCALIZATION NOTE (debuggerUI.showPanesOnInit): This is the label for the
   -  checkbox that toggles visibility of panes when opening the debugger. -->
 <!ENTITY debuggerUI.showPanesOnInit           "Show Panes on Startup">
 <!ENTITY debuggerUI.showPanesOnInit.accesskey "S">
 
 <!-- LOCALIZATION NOTE (debuggerUI.showVarsFilter): This is the label for the
   -  checkbox that toggles visibility of a designated variables filter box. -->
 <!ENTITY debuggerUI.showVarsFilter           "Show Variables Filter Box">
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.properties
@@ -151,31 +151,16 @@ timeEvents=Time
 touchEvents=Touch
 otherEvents=Other
 
 # LOCALIZATION NOTE (blackBoxCheckboxTooltip): The tooltip text to display when
 # the user hovers over the checkbox used to toggle black boxing its associated
 # source.
 blackBoxCheckboxTooltip=Toggle black boxing
 
-# LOCALIZATION NOTE (pauseAllExceptionsTooltip): The tooltip text to display when
-# the user hovers over the pause on exceptions button in the "pause on all
-# exceptions" state.
-pauseAllExceptionsTooltip=Pause on all exceptions
-
-# LOCALIZATION NOTE (pauseUncaughtExceptionsTooltip): The tooltip text to display when
-# the user hovers over the pause on exceptions button in the "pause on uncaught
-# exceptions" state.
-pauseUncaughtExceptionsTooltip=Pause on uncaught exceptions
-
-# LOCALIZATION NOTE (pauseNoExceptionsTooltip): The tooltip text to display when
-# the user hovers over the pause on exceptions button in the "pause on no
-# exceptions" state.
-pauseNoExceptionsTooltip=Do not pause on exceptions
-
 # LOCALIZATION NOTE (noMatchingStringsText): The text to display in the
 # global search results when there are no matching strings after filtering.
 noMatchingStringsText=No matches found
 
 # LOCALIZATION NOTE (emptySearchText): This is the text that appears in the
 # filter text box when it is empty and the scripts container is selected.
 emptySearchText=Search scripts (%S)
 
--- a/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -2,21 +2,21 @@
    - 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/. -->
 
 <!ENTITY tracking.label                 "Tracking">
 
 <!ENTITY dntTrackingNotOkay4.label     "Request that sites not track you">
 <!ENTITY dntTrackingNotOkay4.accesskey "n">
 <!ENTITY doNotTrackInfo.label          "Learn More">
-<!ENTITY trackingProtection4.label     "Stop sites from tracking you">
-<!ENTITY trackingProtection4.accesskey "m">
+<!ENTITY trackingProtection5.label     "Use Tracking Protection">
+<!ENTITY trackingProtection5.accesskey "m">
 <!ENTITY trackingProtectionLearnMore.label "Learn more">
-<!ENTITY trackingProtectionPBM4.label         "Stop sites from tracking you in Private Windows">
-<!ENTITY trackingProtectionPBM4.accesskey     "y">
+<!ENTITY trackingProtectionPBM5.label         "Use Tracking Protection in Private Windows">
+<!ENTITY trackingProtectionPBM5.accesskey     "y">
 <!ENTITY trackingProtectionPBMLearnMore.label "Learn more">
 
 <!ENTITY  history.label                 "History">
 
 <!ENTITY  locationBar.label             "Location Bar">
 
 <!ENTITY  locbar.suggest.label          "When using the location bar, suggest:">
 <!ENTITY  locbar.history.label          "History">
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -51,19 +51,16 @@ browser.jar:
   skin/classic/browser/identity-mixed-active-blocked.svg    (../shared/identity-block/identity-mixed-active-blocked.svg)
   skin/classic/browser/identity-mixed-passive-loaded.svg    (../shared/identity-block/identity-mixed-passive-loaded.svg)
   skin/classic/browser/identity-mixed-active-loaded.svg     (../shared/identity-block/identity-mixed-active-loaded.svg)
   skin/classic/browser/tracking-protection-16.svg           (../shared/identity-block/tracking-protection-16.svg)
   skin/classic/browser/tracking-protection-disabled-16.svg  (../shared/identity-block/tracking-protection-disabled-16.svg)
   skin/classic/browser/Info.png
   skin/classic/browser/magnifier.png                        (../shared/magnifier.png)
   skin/classic/browser/magnifier@2x.png                     (../shared/magnifier@2x.png)
-  skin/classic/browser/mask.png                             (../shared/mask.png)
-  skin/classic/browser/mask@2x.png                          (../shared/mask@2x.png)
-  skin/classic/browser/mask-and-shield.svg                  (../shared/mask-and-shield.svg)
   skin/classic/browser/menuPanel.png
   skin/classic/browser/menuPanel@2x.png
   skin/classic/browser/menuPanel-customize.png
   skin/classic/browser/menuPanel-customize@2x.png
   skin/classic/browser/menuPanel-exit.png
   skin/classic/browser/menuPanel-exit@2x.png
   skin/classic/browser/menuPanel-help.png
   skin/classic/browser/menuPanel-help@2x.png
@@ -230,16 +227,23 @@ browser.jar:
   skin/classic/browser/fxa/logo@2x.png                        (../shared/fxa/logo@2x.png)
   skin/classic/browser/fxa/sync-illustration.png              (../shared/fxa/sync-illustration.png)
   skin/classic/browser/fxa/sync-illustration@2x.png           (../shared/fxa/sync-illustration@2x.png)
   skin/classic/browser/fxa/android.png                        (../shared/fxa/android.png)
   skin/classic/browser/fxa/android@2x.png                     (../shared/fxa/android@2x.png)
   skin/classic/browser/preferences/applications.css   (preferences/applications.css)
   skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
   skin/classic/browser/preferences/search.css         (preferences/search.css)
+  skin/classic/browser/privatebrowsing/attention.png          (../shared/privatebrowsing/attention.png)
+  skin/classic/browser/privatebrowsing/attention@2x.png       (../shared/privatebrowsing/attention@2x.png)
+  skin/classic/browser/privatebrowsing/check.png              (../shared/privatebrowsing/check.png)
+  skin/classic/browser/privatebrowsing/check@2x.png           (../shared/privatebrowsing/check@2x.png)
+  skin/classic/browser/privatebrowsing/mask.svg               (../shared/privatebrowsing/mask.svg)
+  skin/classic/browser/privatebrowsing/shield-page.png        (../shared/privatebrowsing/shield-page.png)
+  skin/classic/browser/privatebrowsing/shield-page@2x.png     (../shared/privatebrowsing/shield-page@2x.png)
   skin/classic/browser/social/services-16.png         (social/services-16.png)
   skin/classic/browser/social/services-64.png         (social/services-64.png)
   skin/classic/browser/social/share-button.png        (social/share-button.png)
   skin/classic/browser/social/share-button-active.png (social/share-button-active.png)
   skin/classic/browser/social/chat-icons.svg          (../shared/social/chat-icons.svg)
   skin/classic/browser/social/gear_default.png        (../shared/social/gear_default.png)
   skin/classic/browser/social/gear_clicked.png        (../shared/social/gear_clicked.png)
   skin/classic/browser/tabbrowser/alltabs.png         (tabbrowser/alltabs.png)
@@ -384,22 +388,16 @@ browser.jar:
   skin/classic/browser/devtools/debugger-step-out.png  (../shared/devtools/images/debugger-step-out.png)
   skin/classic/browser/devtools/debugger-step-out@2x.png  (../shared/devtools/images/debugger-step-out@2x.png)
   skin/classic/browser/devtools/debugger-step-over.png (../shared/devtools/images/debugger-step-over.png)
   skin/classic/browser/devtools/debugger-step-over@2x.png (../shared/devtools/images/debugger-step-over@2x.png)
   skin/classic/browser/devtools/debugger-blackbox.png  (../shared/devtools/images/debugger-blackbox.png)
   skin/classic/browser/devtools/debugger-blackbox@2x.png  (../shared/devtools/images/debugger-blackbox@2x.png)
   skin/classic/browser/devtools/debugger-prettyprint.png  (../shared/devtools/images/debugger-prettyprint.png)
   skin/classic/browser/devtools/debugger-prettyprint@2x.png (../shared/devtools/images/debugger-prettyprint@2x.png)
-  skin/classic/browser/devtools/debugger-no-pause-exceptions.png  (../shared/devtools/images/debugger-no-pause-exceptions.png)
-  skin/classic/browser/devtools/debugger-no-pause-exceptions@2x.png (../shared/devtools/images/debugger-no-pause-exceptions@2x.png)
-  skin/classic/browser/devtools/debugger-pause-all-exceptions.png  (../shared/devtools/images/debugger-pause-all-exceptions.png)
-  skin/classic/browser/devtools/debugger-pause-all-exceptions@2x.png (../shared/devtools/images/debugger-pause-all-exceptions@2x.png)
-  skin/classic/browser/devtools/debugger-pause-uncaught-exceptions.png  (../shared/devtools/images/debugger-pause-uncaught-exceptions.png)
-  skin/classic/browser/devtools/debugger-pause-uncaught-exceptions@2x.png (../shared/devtools/images/debugger-pause-uncaught-exceptions@2x.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints.png (../shared/devtools/images/debugger-toggleBreakpoints.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
   skin/classic/browser/devtools/tracer-icon.png        (../shared/devtools/images/tracer-icon.png)
   skin/classic/browser/devtools/tracer-icon@2x.png     (../shared/devtools/images/tracer-icon@2x.png)
   skin/classic/browser/devtools/responsive-se-resizer.png          (../shared/devtools/images/responsivemode/responsive-se-resizer.png)
   skin/classic/browser/devtools/responsive-se-resizer@2x.png       (../shared/devtools/images/responsivemode/responsive-se-resizer@2x.png)
   skin/classic/browser/devtools/responsive-vertical-resizer.png    (../shared/devtools/images/responsivemode/responsive-vertical-resizer.png)
   skin/classic/browser/devtools/responsive-vertical-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer@2x.png)
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -65,19 +65,16 @@ browser.jar:
   skin/classic/browser/menu-back.png
   skin/classic/browser/menu-forward.png
   skin/classic/browser/notification-16.png
   skin/classic/browser/notification-16@2x.png
   skin/classic/browser/notification-64.png
   skin/classic/browser/notification-64@2x.png
   skin/classic/browser/magnifier.png                        (../shared/magnifier.png)
   skin/classic/browser/magnifier@2x.png                     (../shared/magnifier@2x.png)
-  skin/classic/browser/mask.png                             (../shared/mask.png)
-  skin/classic/browser/mask@2x.png                          (../shared/mask@2x.png)
-  skin/classic/browser/mask-and-shield.svg                  (../shared/mask-and-shield.svg)
   skin/classic/browser/menuPanel.png
   skin/classic/browser/menuPanel@2x.png
   skin/classic/browser/menuPanel-customize.png
   skin/classic/browser/menuPanel-customize@2x.png
   skin/classic/browser/menuPanel-exit.png
   skin/classic/browser/menuPanel-exit@2x.png
   skin/classic/browser/menuPanel-help.png
   skin/classic/browser/menuPanel-help@2x.png
@@ -310,16 +307,23 @@ browser.jar:
   skin/classic/browser/fxa/sync-illustration@2x.png         (../shared/fxa/sync-illustration@2x.png)
   skin/classic/browser/fxa/android.png                      (../shared/fxa/android.png)
   skin/classic/browser/fxa/android@2x.png                   (../shared/fxa/android@2x.png)
   skin/classic/browser/preferences/applications.css         (preferences/applications.css)
   skin/classic/browser/preferences/aboutPermissions.css     (preferences/aboutPermissions.css)
   skin/classic/browser/preferences/search.css               (preferences/search.css)
   skin/classic/browser/preferences/checkbox.png             (preferences/checkbox.png)
   skin/classic/browser/preferences/checkbox@2x.png          (preferences/checkbox@2x.png)
+  skin/classic/browser/privatebrowsing/attention.png        (../shared/privatebrowsing/attention.png)
+  skin/classic/browser/privatebrowsing/attention@2x.png     (../shared/privatebrowsing/attention@2x.png)
+  skin/classic/browser/privatebrowsing/check.png            (../shared/privatebrowsing/check.png)
+  skin/classic/browser/privatebrowsing/check@2x.png         (../shared/privatebrowsing/check@2x.png)
+  skin/classic/browser/privatebrowsing/mask.svg             (../shared/privatebrowsing/mask.svg)
+  skin/classic/browser/privatebrowsing/shield-page.png      (../shared/privatebrowsing/shield-page.png)
+  skin/classic/browser/privatebrowsing/shield-page@2x.png   (../shared/privatebrowsing/shield-page@2x.png)
   skin/classic/browser/yosemite/preferences/checkbox.png    (preferences/checkbox-yosemite.png)
   skin/classic/browser/yosemite/preferences/checkbox@2x.png (preferences/checkbox-yosemite@2x.png)
   skin/classic/browser/social/services-16.png               (social/services-16.png)
   skin/classic/browser/social/services-16@2x.png            (social/services-16@2x.png)
   skin/classic/browser/social/services-64.png               (social/services-64.png)
   skin/classic/browser/social/services-64@2x.png            (social/services-64@2x.png)
   skin/classic/browser/social/chat-icons.svg                             (../shared/social/chat-icons.svg)
   skin/classic/browser/social/gear_default.png                           (../shared/social/gear_default.png)
@@ -488,22 +492,16 @@ browser.jar:
   skin/classic/browser/devtools/debugger-step-out.png       (../shared/devtools/images/debugger-step-out.png)
   skin/classic/browser/devtools/debugger-step-out@2x.png    (../shared/devtools/images/debugger-step-out@2x.png)
   skin/classic/browser/devtools/debugger-step-over.png      (../shared/devtools/images/debugger-step-over.png)
   skin/classic/browser/devtools/debugger-step-over@2x.png   (../shared/devtools/images/debugger-step-over@2x.png)
   skin/classic/browser/devtools/debugger-blackbox.png       (../shared/devtools/images/debugger-blackbox.png)
   skin/classic/browser/devtools/debugger-blackbox@2x.png    (../shared/devtools/images/debugger-blackbox@2x.png)
   skin/classic/browser/devtools/debugger-prettyprint.png    (../shared/devtools/images/debugger-prettyprint.png)
   skin/classic/browser/devtools/debugger-prettyprint@2x.png (../shared/devtools/images/debugger-prettyprint@2x.png)
-  skin/classic/browser/devtools/debugger-no-pause-exceptions.png  (../shared/devtools/images/debugger-no-pause-exceptions.png)
-  skin/classic/browser/devtools/debugger-no-pause-exceptions@2x.png (../shared/devtools/images/debugger-no-pause-exceptions@2x.png)
-  skin/classic/browser/devtools/debugger-pause-all-exceptions.png  (../shared/devtools/images/debugger-pause-all-exceptions.png)
-  skin/classic/browser/devtools/debugger-pause-all-exceptions@2x.png (../shared/devtools/images/debugger-pause-all-exceptions@2x.png)
-  skin/classic/browser/devtools/debugger-pause-uncaught-exceptions.png  (../shared/devtools/images/debugger-pause-uncaught-exceptions.png)
-  skin/classic/browser/devtools/debugger-pause-uncaught-exceptions@2x.png (../shared/devtools/images/debugger-pause-uncaught-exceptions@2x.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints.png (../shared/devtools/images/debugger-toggleBreakpoints.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
   skin/classic/browser/devtools/tracer-icon.png             (../shared/devtools/images/tracer-icon.png)
   skin/classic/browser/devtools/tracer-icon@2x.png          (../shared/devtools/images/tracer-icon@2x.png)
   skin/classic/browser/devtools/floating-scrollbars.css     (devtools/floating-scrollbars.css)
   skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
   skin/classic/browser/devtools/responsive-se-resizer.png          (../shared/devtools/images/responsivemode/responsive-se-resizer.png)
   skin/classic/browser/devtools/responsive-se-resizer@2x.png       (../shared/devtools/images/responsivemode/responsive-se-resizer@2x.png)
--- a/browser/themes/shared/contextmenu.inc.css
+++ b/browser/themes/shared/contextmenu.inc.css
@@ -90,8 +90,18 @@
   width: 16px;
   height: 16px;
   margin: 7px;
 }
 
 #context-media-eme-learnmore {
   list-style-image: url("chrome://browser/skin/drm-icon.svg#chains");
 }
+
+#fill-login {
+  list-style-image: url("chrome://mozapps/skin/passwordmgr/key-16.png");
+}
+
+@media (min-resolution: 1.1dppx) {
+  #fill-login {
+    list-style-image: url("chrome://mozapps/skin/passwordmgr/key-16@2x.png");
+  }
+}
--- a/browser/themes/shared/devtools/debugger.css
+++ b/browser/themes/shared/devtools/debugger.css
@@ -87,46 +87,16 @@
 }
 
 @media (min-resolution: 1.25dppx) {
   #toggle-breakpoints {
     list-style-image: url(debugger-toggleBreakpoints@2x.png);
   }
 }
 
-#toggle-pause-exceptions[state="0"] {
-  list-style-image: url(debugger-no-pause-exceptions.png);
-}
-
-@media (min-resolution: 1.25dppx) {
-  #toggle-pause-exceptions[state="0"] {
-    list-style-image: url(debugger-no-pause-exceptions@2x.png);
-  }
-}
-
-#toggle-pause-exceptions[state="1"] {
-  list-style-image: url(debugger-pause-all-exceptions.png);
-}
-
-@media (min-resolution: 1.25dppx) {
-  #toggle-pause-exceptions[state="1"] {
-    list-style-image: url(debugger-pause-all-exceptions@2x.png);
-  }
-}
-
-#toggle-pause-exceptions[state="2"] {
-  list-style-image: url(debugger-pause-uncaught-exceptions.png);
-}
-
-@media (min-resolution: 1.25dppx) {
-  #toggle-pause-exceptions[state="2"] {
-    list-style-image: url(debugger-pause-uncaught-exceptions@2x.png);
-  }
-}
-
 #toggle-promise-debugger {
   /* TODO Bug 1186119: Add a toggle promise debugger image */
 }
 
 #sources-toolbar .devtools-toolbarbutton:not([label]) {
   -moz-image-region: rect(0px,16px,16px,0px);
 }
 
deleted file mode 100644
index 5290a474d4b41b7a1867f3c85098b33baaa036c3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index b03aa8dd005ee36e8aaf960d19bb62ed76ef4e82..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 56a05b4298791ddd6e53b7cf9c8943e8f20ce4a8..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 98b566bca496d92dd2fbac7ade1a729bffe7fe9a..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index a996ec72eedc5b57667c1269a192923913268154..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index efd21f7696f9202fad42fdb4c0cf1e536a2915c3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
--- a/browser/themes/shared/mask-and-shield.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
-     width="179" height="88" viewBox="0 0 179 88">
-  <path fill="#fff" d="M8.946,35.096 C8.606,31.547 8.420,23.513 8.426,12.880 L36.504,8.301 L36.504,74.685 C33.361,74.046 24.945,71.679 19.034,64.025 C13.254,56.539 10.426,50.586 8.946,35.096 ZM70.859,17.395 C69.626,17.801 68.460,18.195 67.354,18.580 C67.370,16.177 67.375,13.601 67.367,10.865 C67.366,10.686 67.212,10.536 66.991,10.500 L36.505,5.532 L6.018,10.500 C5.798,10.536 5.643,10.687 5.642,10.866 C5.609,22.579 5.802,31.508 6.170,35.361 C7.705,51.406 10.825,57.918 16.814,65.669 C23.751,74.645 33.895,76.990 36.508,77.458 C38.819,77.044 47.234,75.103 53.958,68.218 C54.688,69.280 55.457,70.380 56.317,71.575 C56.631,71.983 56.954,72.374 57.276,72.765 C47.955,81.768 36.504,83.000 36.504,83.000 C36.504,83.000 21.987,81.447 12.339,68.990 C5.237,59.821 2.096,51.895 0.563,35.900 C0.036,30.405 -0.010,17.912 0.010,10.913 C0.019,8.021 2.164,5.580 5.089,5.105 L36.504,-0.003 L67.919,5.105 C70.844,5.580 72.990,8.021 72.998,10.913 C73.003,12.580 73.003,14.563 72.995,16.684 C72.347,16.902 71.640,17.137 70.859,17.395 Z" />
-  <path fill="#fff" d="M176.593,36.244 C176.057,45.236 178.201,55.977 166.140,71.463 C153.271,87.987 140.491,86.725 138.079,86.974 C123.601,88.466 121.694,75.948 113.238,75.948 C105.835,75.948 99.803,88.386 88.929,86.974 C86.526,86.661 73.738,87.987 60.868,71.463 C48.808,55.977 50.952,45.236 50.416,36.244 C49.880,27.251 48.004,17.510 48.004,17.510 C48.004,17.510 53.816,23.255 61.321,23.755 C68.826,24.254 70.228,21.187 86.063,16.761 C103.186,11.975 113.505,31.587 113.505,31.587 C113.505,31.587 125.132,12.265 140.946,16.761 C156.759,21.257 157.416,24.254 164.920,23.755 C172.425,23.255 179.005,17.510 179.005,17.510 C179.005,17.510 177.129,27.251 176.593,36.244 ZM88.064,40.011 C78.705,37.996 74.778,41.439 70.768,42.908 C67.269,44.189 64.085,44.587 64.085,44.587 C64.085,44.587 64.621,49.832 74.002,54.328 C83.383,58.824 102.627,56.504 102.627,56.504 C102.627,56.504 104.670,43.587 88.064,40.011 ZM156.241,42.908 C152.231,41.439 148.304,37.996 138.944,40.011 C122.338,43.587 124.382,56.504 124.382,56.504 C124.382,56.504 143.626,58.824 153.006,54.328 C162.388,49.832 162.923,44.587 162.923,44.587 C162.923,44.587 159.740,44.189 156.241,42.908 Z" />
-</svg>
deleted file mode 100644
index f48d176ee2826efac48b3119a7e5dd215f113919..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index e284af03309d6994b328f2c410e0c24750a3c760..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8706928ffe851f356e14fcab0c0770222813c757
GIT binary patch
literal 602
zc%17D@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F
z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a><Y92N?Z!?32_C||8Erx8wB*u
zjeWr&Z@ZKP`2{lszFNu1^*prf-+^n)d~YY~$2C++++!8~*sh$>HRTDX<k$H&Mccz(
z^2+}_^rm|5t<)v&1=W7r-)?OVdK&*_*2Sac1)^I`k7NPOV@&dPcVXyYmGuB}I14-?
ziy0WiR6&^0Gf3qFP;jcJi(`ny<=nobLd^~WF4iqA0?O}z;L`v9zBd~eJ(ytW^SwIM
zdh3DzoEeUH&o4B{{NZ|}Cu`%5<DE-dMJ~@fVbCq}nRR-%>a;+`)$3MFEdAQjyX^2<
zvzw07Q_c%cTUE<*MXs;qxNzv%mp-}YTy>V{hG%!46}$0vsq6xIRsRE#lf-|2e<Hf$
n=A(ZVw|)kh_iQ(xuU}_dC-e3CW}yb40~tJB{an^LB{Ts5KhHEA
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5b32888c832901b899f79b4e17fcf2dd644d2ed9
GIT binary patch
literal 902
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50
z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+081EY0-Plzi}!T(zYqli=l
z47ar`NB0A%^pYUIU<TIS4-ev6|GCM2zsxi<TKV^Fmc<L~eNLom|J^I{{t^4y+C1aK
zFSxf)yjWo~=gwRH11p-geE!6E@=%xmxo?t}Zc0sw{KEWG;g;aedCBTIqLcKwo`-EL
zGctd&GW3~13XjD3`5Y5o-_6h~x1I~Mk}=8K-G!lpRn`N@;VkfoEM{O3Qw3p0&mff#
zKn13rE{-7<r`Jxt9>nA*;2Q2ICR%#5r6K9i8i{Kgw79wi&se6v|Np=7vaxjPG4)@m
z{@-mwFPoaK&fL0o*ROyb5A7A19Qs#%KBlI&z;c;L)PdEZQ@2YxW%O&e@GaQ9dN;er
ziO=^`g5FGi=Unfm#lz72#h1}}Q%wZB5{t4!S%^~4#;?aX)g*kvo(FIFZ*q~R`DV;i
z1NTEVfzvV`=F2@b-{6rUq`S2F=O-@lu+F2ok&cPJKG!9mvE)7ZTbUE=vt2@*Wzh@q
zZEqj?b>3}1ySqA0?*8`n4SZbfeDak}lADaQ{N{0bvleQH9DjGhXU-G<(&gUsI{*AR
zB&xSkf7jco0_*NNcI-bU{eD99EAR5Ghx7Kk+>hcvsQkg>@8pNPXP!?F_x}FNeBWW~
oDXRZA^`F<zTvh)+W9y3enOXA=G2XTYh9m=nr>mdKI;Vst09rfS=l}o!
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..59ca51b7bd5bc350644f5b3e436dea16a22d4e98
GIT binary patch
literal 338
zc%17D@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F
z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a><Y92N_YhLgt!9f{C!>&BA_Aq
zm73{5N~|QvFPMR2Q^1a&F6V@OHn2HwV;8-^|Ngwl;!D3Z{DCSMlf2zs7&=&GJ%Aj}
z0*}aIpe|JqX7mhF`2ZAj^>lFzk+__kuz<(F$Z+we$RiOq1AZpGk-70>PRt#R8o4mT
zIJ=auf0&Yz_B5UN<*4MO@vPA$;0${wNAUs+PZyD?{o)J^s~MU1F+9Ea31}dLr>mdK
II;Vst0CDea0{{R3
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..031685cbf43337d21599e8d00b225d7e14f4afdd
GIT binary patch
literal 370
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50
z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10!YRNf#1%;A@AD!X0kz*c
z>IpQNL8K(eFPK5`wDyBnPuL&+^i)40`|K`9K%m$4>!q4NdB!AfcNc~ZR#^`qhqJ&V
zvY3HEOcjI~J%dy}00nbBT^vI!PG7xnTFk+K$Ms^s`bDoM{{J7gC2;byS&=DK-xN46
zu3xUf`%d&aTe+K3$+KlwtHgJ`z5n{~i-P$#tnXNM`pkcPGBD+PbdJ!ef1WG8uT}c;
z+qL2U9jD*-Rj>T-+8`|`v|>KfcW0X~@6YkQS;p&T)Tz1^XfcDQtDnm{r-UW|oPUbN
new file mode 100755
--- /dev/null
+++ b/browser/themes/shared/privatebrowsing/mask.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+     width="47.203" height="26.109" viewBox="0 0 94.407 52.219">
+  <path fill="#fff" d="M92.657,14.670 C92.270,21.197 93.816,28.994 85.124,40.236 C75.849,52.230 66.639,51.314 64.901,51.495 C54.468,52.578 53.093,43.491 46.999,43.491 C41.664,43.491 37.317,52.520 29.481,51.495 C27.749,51.268 18.533,52.230 9.259,40.236 C0.567,28.994 2.112,21.197 1.726,14.670 C1.340,8.142 -0.012,1.071 -0.012,1.071 C-0.012,1.071 4.176,5.241 9.585,5.604 C14.993,5.967 16.004,3.740 27.416,0.527 C39.755,-2.947 47.191,11.290 47.191,11.290 C47.191,11.290 55.571,-2.737 66.967,0.527 C78.363,3.791 78.836,5.967 84.245,5.604 C89.653,5.241 94.395,1.071 94.395,1.071 C94.395,1.071 93.043,8.142 92.657,14.670 ZM28.858,17.405 C22.113,15.942 19.283,18.441 16.393,19.507 C13.872,20.437 11.577,20.726 11.577,20.726 C11.577,20.726 11.963,24.533 18.724,27.797 C25.484,31.061 39.352,29.377 39.352,29.377 C39.352,29.377 40.824,20.000 28.858,17.405 ZM77.990,19.507 C75.100,18.441 72.270,15.942 65.525,17.405 C53.557,20.000 55.030,29.377 55.030,29.377 C55.030,29.377 68.899,31.061 75.659,27.797 C82.419,24.533 82.805,20.726 82.805,20.726 C82.805,20.726 80.511,20.437 77.990,19.507 Z"/>
+</svg>
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2ddcf34e97bd59cd35887b04cd44bc1edb8e3bd0
GIT binary patch
literal 4257
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
D8XNC;
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..72a0b827329d4d7d30746a28d4b46846328ab889
GIT binary patch
literal 9367
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
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -58,19 +58,16 @@ browser.jar:
         skin/classic/browser/tracking-protection-16.svg              (../shared/identity-block/tracking-protection-16.svg)
         skin/classic/browser/tracking-protection-disabled-16.svg     (../shared/identity-block/tracking-protection-disabled-16.svg)
         skin/classic/browser/keyhole-forward-mask.svg
         skin/classic/browser/KUI-background.png
         skin/classic/browser/livemark-folder.png
         skin/classic/browser/livemark-folder-XP.png
         skin/classic/browser/magnifier.png                          (../shared/magnifier.png)
         skin/classic/browser/magnifier@2x.png                       (../shared/magnifier@2x.png)
-        skin/classic/browser/mask.png                               (../shared/mask.png)
-        skin/classic/browser/mask@2x.png                            (../shared/mask@2x.png)
-        skin/classic/browser/mask-and-shield.svg                    (../shared/mask-and-shield.svg)
         skin/classic/browser/menu-back.png
         skin/classic/browser/menu-back-XP.png
         skin/classic/browser/menu-forward.png
         skin/classic/browser/menu-forward-XP.png
         skin/classic/browser/menuPanel.png
         skin/classic/browser/menuPanel@2x.png
         skin/classic/browser/menuPanel-aero.png
         skin/classic/browser/menuPanel-aero@2x.png
@@ -319,16 +316,23 @@ browser.jar:
         skin/classic/browser/fxa/android@2x.png                      (../shared/fxa/android@2x.png)
         skin/classic/browser/preferences/applications.css            (preferences/applications.css)
         skin/classic/browser/preferences/aboutPermissions.css        (preferences/aboutPermissions.css)
         skin/classic/browser/preferences/search.css                  (preferences/search.css)
         skin/classic/browser/preferences/checkbox.png                (preferences/checkbox.png)
         skin/classic/browser/preferences/checkbox-aero.png           (preferences/checkbox-aero.png)
         skin/classic/browser/preferences/checkbox-classic.png        (preferences/checkbox-classic.png)
         skin/classic/browser/preferences/checkbox-xp.png             (preferences/checkbox-xp.png)
+        skin/classic/browser/privatebrowsing/attention.png           (../shared/privatebrowsing/attention.png)
+        skin/classic/browser/privatebrowsing/attention@2x.png        (../shared/privatebrowsing/attention@2x.png)
+        skin/classic/browser/privatebrowsing/check.png               (../shared/privatebrowsing/check.png)
+        skin/classic/browser/privatebrowsing/check@2x.png            (../shared/privatebrowsing/check@2x.png)
+        skin/classic/browser/privatebrowsing/mask.svg                (../shared/privatebrowsing/mask.svg)
+        skin/classic/browser/privatebrowsing/shield-page.png         (../shared/privatebrowsing/shield-page.png)
+        skin/classic/browser/privatebrowsing/shield-page@2x.png      (../shared/privatebrowsing/shield-page@2x.png)
         skin/classic/browser/social/services-16.png                  (social/services-16.png)
         skin/classic/browser/social/services-64.png                  (social/services-64.png)
         skin/classic/browser/social/chat-icons.svg                   (../shared/social/chat-icons.svg)
         skin/classic/browser/social/gear_default.png                 (../shared/social/gear_default.png)
         skin/classic/browser/social/gear_clicked.png                 (../shared/social/gear_clicked.png)
         skin/classic/browser/tabbrowser/newtab.png                   (tabbrowser/newtab.png)
         skin/classic/browser/tabbrowser/newtab@2x.png                (tabbrowser/newtab@2x.png)
         skin/classic/browser/tabbrowser/newtab-XPVista7.png          (tabbrowser/newtab-XPVista7.png)
@@ -499,22 +503,16 @@ browser.jar:
         skin/classic/browser/devtools/debugger-step-out.png         (../shared/devtools/images/debugger-step-out.png)
         skin/classic/browser/devtools/debugger-step-out@2x.png      (../shared/devtools/images/debugger-step-out@2x.png)
         skin/classic/browser/devtools/debugger-step-over.png        (../shared/devtools/images/debugger-step-over.png)
         skin/classic/browser/devtools/debugger-step-over@2x.png     (../shared/devtools/images/debugger-step-over@2x.png)
         skin/classic/browser/devtools/debugger-blackbox.png         (../shared/devtools/images/debugger-blackbox.png)
         skin/classic/browser/devtools/debugger-blackbox@2x.png      (../shared/devtools/images/debugger-blackbox@2x.png)
         skin/classic/browser/devtools/debugger-prettyprint.png      (../shared/devtools/images/debugger-prettyprint.png)
         skin/classic/browser/devtools/debugger-prettyprint@2x.png   (../shared/devtools/images/debugger-prettyprint@2x.png)
-        skin/classic/browser/devtools/debugger-no-pause-exceptions.png  (../shared/devtools/images/debugger-no-pause-exceptions.png)
-        skin/classic/browser/devtools/debugger-no-pause-exceptions@2x.png (../shared/devtools/images/debugger-no-pause-exceptions@2x.png)
-        skin/classic/browser/devtools/debugger-pause-all-exceptions.png  (../shared/devtools/images/debugger-pause-all-exceptions.png)
-        skin/classic/browser/devtools/debugger-pause-all-exceptions@2x.png (../shared/devtools/images/debugger-pause-all-exceptions@2x.png)
-        skin/classic/browser/devtools/debugger-pause-uncaught-exceptions.png  (../shared/devtools/images/debugger-pause-uncaught-exceptions.png)
-        skin/classic/browser/devtools/debugger-pause-uncaught-exceptions@2x.png (../shared/devtools/images/debugger-pause-uncaught-exceptions@2x.png)
         skin/classic/browser/devtools/debugger-toggleBreakpoints.png  (../shared/devtools/images/debugger-toggleBreakpoints.png)
         skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png  (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
         skin/classic/browser/devtools/tracer-icon.png               (../shared/devtools/images/tracer-icon.png)
         skin/classic/browser/devtools/tracer-icon@2x.png            (../shared/devtools/images/tracer-icon@2x.png)
         skin/classic/browser/devtools/responsive-se-resizer.png     (../shared/devtools/images/responsivemode/responsive-se-resizer.png)
         skin/classic/browser/devtools/responsive-se-resizer@2x.png       (../shared/devtools/images/responsivemode/responsive-se-resizer@2x.png)
         skin/classic/browser/devtools/responsive-vertical-resizer.png    (../shared/devtools/images/responsivemode/responsive-vertical-resizer.png)
         skin/classic/browser/devtools/responsive-vertical-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer@2x.png)
--- a/build/pgo/server-locations.txt
+++ b/build/pgo/server-locations.txt
@@ -166,16 +166,18 @@ https://sub.sectest1.example.org:443
 
 #
 # Used while testing the url-classifier
 #
 http://malware.example.com:80
 http://tracking.example.com:80
 http://not-tracking.example.com:80
 http://tracking.example.org:80
+http://itisatracker.org:80
+http://trackertest.org:80
 
 https://malware.example.com:443
 https://tracking.example.com:443
 https://not-tracking.example.com:443
 https://tracking.example.org:443
 
 # Bug 483437, 484111
 https://www.bank1.com:443           privileged,cert=escapeattack1
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -895,16 +895,17 @@ nsDocShell::nsDocShell()
   , mIsActive(true)
   , mIsPrerendered(false)
   , mIsAppTab(false)
   , mUseGlobalHistory(false)
   , mInPrivateBrowsing(false)
   , mUseRemoteTabs(false)
   , mDeviceSizeIsPageSize(false)
   , mWindowDraggingAllowed(false)
+  , mInFrameSwap(false)
   , mCanExecuteScripts(false)
   , mFiredUnloadEvent(false)
   , mEODForCurrentDocument(false)
   , mURIResultedInDocument(false)
   , mIsBeingDestroyed(false)
   , mIsExecutingOnLoadHandler(false)
   , mIsPrintingOrPP(false)
   , mSavingOldViewer(false)
@@ -14069,8 +14070,21 @@ nsDocShell::GetInheritedPaymentRequestId
 }
 
 NS_IMETHODIMP
 nsDocShell::GetPaymentRequestId(nsAString& aPaymentRequestId)
 {
   aPaymentRequestId = GetInheritedPaymentRequestId();
   return NS_OK;
 }
+
+bool
+nsDocShell::InFrameSwap()
+{
+  nsRefPtr<nsDocShell> shell = this;
+  do {
+    if (shell->mInFrameSwap) {
+      return true;
+    }
+    shell = shell->GetParentDocshell();
+  } while (shell);
+  return false;
+}
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -253,16 +253,22 @@ public:
 
   // Notify Scroll observers when an async panning/zooming transform
   // has started being applied
   void NotifyAsyncPanZoomStarted();
   // Notify Scroll observers when an async panning/zooming transform
   // is no longer applied
   void NotifyAsyncPanZoomStopped();
 
+  void SetInFrameSwap(bool aInSwap)
+  {
+    mInFrameSwap = aInSwap;
+  }
+  bool InFrameSwap();
+
 private:
   // An observed docshell wrapper is created when recording markers is enabled.
   mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
   bool IsObserved() const { return !!mObserved; }
 
   // It is necessary to allow adding a timeline marker wherever a docshell
   // instance is available. This operation happens frequently and needs to
   // be very fast, so instead of using a Map or having to search for some
@@ -895,16 +901,17 @@ protected:
   bool mIsActive;
   bool mIsPrerendered;
   bool mIsAppTab;
   bool mUseGlobalHistory;
   bool mInPrivateBrowsing;
   bool mUseRemoteTabs;
   bool mDeviceSizeIsPageSize;
   bool mWindowDraggingAllowed;
+  bool mInFrameSwap;
 
   // Because scriptability depends on the mAllowJavascript values of our
   // ancestors, we cache the effective scriptability and recompute it when
   // it might have changed;
   bool mCanExecuteScripts;
   void RecomputeCanExecuteScripts();
 
   // This boolean is set to true right before we fire pagehide and generally
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -946,16 +946,70 @@ nsFrameLoader::SwapWithOtherRemoteLoader
 
   mInSwap = aOther->mInSwap = false;
 
   unused << mRemoteBrowser->SendSwappedWithOtherRemoteLoader();
   unused << aOther->mRemoteBrowser->SendSwappedWithOtherRemoteLoader();
   return NS_OK;
 }
 
+class MOZ_STACK_CLASS AutoResetInFrameSwap final
+{
+public:
+  AutoResetInFrameSwap(nsFrameLoader* aThisFrameLoader,
+                       nsFrameLoader* aOtherFrameLoader,
+                       nsDocShell* aThisDocShell,
+                       nsDocShell* aOtherDocShell,
+                       EventTarget* aThisEventTarget,
+                       EventTarget* aOtherEventTarget
+                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+    : mThisFrameLoader(aThisFrameLoader)
+    , mOtherFrameLoader(aOtherFrameLoader)
+    , mThisDocShell(aThisDocShell)
+    , mOtherDocShell(aOtherDocShell)
+    , mThisEventTarget(aThisEventTarget)
+    , mOtherEventTarget(aOtherEventTarget)
+  {
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+
+    mThisFrameLoader->mInSwap = true;
+    mOtherFrameLoader->mInSwap = true;
+    mThisDocShell->SetInFrameSwap(true);
+    mOtherDocShell->SetInFrameSwap(true);
+
+    // Fire pageshow events on still-loading pages, and then fire pagehide
+    // events.  Note that we do NOT fire these in the normal way, but just fire
+    // them on the chrome event handlers.
+    nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, false);
+    nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, false);
+    nsContentUtils::FirePageHideEvent(mThisDocShell, mThisEventTarget);
+    nsContentUtils::FirePageHideEvent(mOtherDocShell, mOtherEventTarget);
+  }
+
+  ~AutoResetInFrameSwap()
+  {
+    nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, true);
+    nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, true);
+
+    mThisFrameLoader->mInSwap = false;
+    mOtherFrameLoader->mInSwap = false;
+    mThisDocShell->SetInFrameSwap(false);
+    mOtherDocShell->SetInFrameSwap(false);
+  }
+
+private:
+  nsRefPtr<nsFrameLoader> mThisFrameLoader;
+  nsRefPtr<nsFrameLoader> mOtherFrameLoader;
+  nsRefPtr<nsDocShell> mThisDocShell;
+  nsRefPtr<nsDocShell> mOtherDocShell;
+  nsCOMPtr<EventTarget> mThisEventTarget;
+  nsCOMPtr<EventTarget> mOtherEventTarget;
+  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
 nsresult
 nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
                                    nsRefPtr<nsFrameLoader>& aFirstToSwap,
                                    nsRefPtr<nsFrameLoader>& aSecondToSwap)
 {
   NS_PRECONDITION((aFirstToSwap == this && aSecondToSwap == aOther) ||
                   (aFirstToSwap == aOther && aSecondToSwap == this),
                   "Swapping some sort of random loaders?");
@@ -982,18 +1036,18 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   bool equal;
   nsresult rv =
     ourContent->NodePrincipal()->Equals(otherContent->NodePrincipal(), &equal);
   if (NS_FAILED(rv) || !equal) {
     // Security problems loom.  Just bail on it all
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  nsCOMPtr<nsIDocShell> ourDocshell = GetExistingDocShell();
-  nsCOMPtr<nsIDocShell> otherDocshell = aOther->GetExistingDocShell();
+  nsRefPtr<nsDocShell> ourDocshell = static_cast<nsDocShell*>(GetExistingDocShell());
+  nsRefPtr<nsDocShell> otherDocshell = static_cast<nsDocShell*>(aOther->GetExistingDocShell());
   if (!ourDocshell || !otherDocshell) {
     // How odd
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // To avoid having to mess with session history, avoid swapping
   // frameloaders that don't correspond to root same-type docshells,
   // unless both roots have session history disabled.
@@ -1114,49 +1168,33 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
       otherDocshell->GetIsBrowserElement() ||
       ourDocshell->GetIsApp() != otherDocshell->GetIsApp()) {
       return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   if (mInSwap || aOther->mInSwap) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
-  mInSwap = aOther->mInSwap = true;
-
-  // Fire pageshow events on still-loading pages, and then fire pagehide
-  // events.  Note that we do NOT fire these in the normal way, but just fire
-  // them on the chrome event handlers.
-  nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, false);
-  nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, false);
-  nsContentUtils::FirePageHideEvent(ourDocshell, ourEventTarget);
-  nsContentUtils::FirePageHideEvent(otherDocshell, otherEventTarget);
-  
+  AutoResetInFrameSwap autoFrameSwap(this, aOther, ourDocshell, otherDocshell,
+                                     ourEventTarget, otherEventTarget);
+
   nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
   nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
   if (!ourFrame || !otherFrame) {
-    mInSwap = aOther->mInSwap = false;
-    nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
-    nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
   if (!ourFrameFrame) {
-    mInSwap = aOther->mInSwap = false;
-    nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
-    nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // OK.  First begin to swap the docshells in the two nsIFrames
   rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
   if (NS_FAILED(rv)) {
-    mInSwap = aOther->mInSwap = false;
-    nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
-    nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
     return rv;
   }
 
   // Now move the docshells to the right docshell trees.  Note that this
   // resets their treeowners to null.
   ourParentItem->RemoveChild(ourDocshell);
   otherParentItem->RemoveChild(otherDocshell);
   if (ourType == nsIDocShellTreeItem::typeContent) {
@@ -1249,20 +1287,16 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   // the wrong appUnitsPerDevPixel value. So we tell the PresShells that their
   // backing scale factor may have changed. (Bug 822266)
   ourShell->BackingScaleFactorChanged();
   otherShell->BackingScaleFactorChanged();
 
   ourParentDocument->FlushPendingNotifications(Flush_Layout);
   otherParentDocument->FlushPendingNotifications(Flush_Layout);
 
-  nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
-  nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
-
-  mInSwap = aOther->mInSwap = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameLoader::Destroy()
 {
   StartDestroy();
   return NS_OK;
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -26,16 +26,17 @@
 #include "Units.h"
 #include "nsIWebBrowserPersistable.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
+class AutoResetInFrameSwap;
 class nsITabParent;
 class nsIDocShellTreeItem;
 class nsIDocShellTreeOwner;
 class mozIApplication;
 
 namespace mozilla {
 namespace dom {
 class ContentParent;
@@ -54,16 +55,17 @@ typedef struct _GtkWidget GtkWidget;
 #endif
 
 class nsFrameLoader final : public nsIFrameLoader,
                             public nsIWebBrowserPersistable,
                             public nsStubMutationObserver,
                             public mozilla::dom::ipc::MessageManagerCallback
 {
   friend class AutoResetInShow;
+  friend class AutoResetInFrameSwap;
   typedef mozilla::dom::PBrowserParent PBrowserParent;
   typedef mozilla::dom::TabParent TabParent;
   typedef mozilla::layout::RenderFrameParent RenderFrameParent;
 
 public:
   static nsFrameLoader* Create(mozilla::dom::Element* aOwner,
                                bool aNetworkCreated);
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -98,16 +98,17 @@ static PRLogModuleInfo* gMediaElementEve
 
 #include "nsIContentSecurityPolicy.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/FloatingPoint.h"
 
 #include "nsIPermissionManager.h"
 #include "nsContentTypeParser.h"
+#include "nsDocShell.h"
 
 #include "mozilla/EventStateManager.h"
 
 #if defined(MOZ_B2G) && !defined(MOZ_GRAPHENE)
 // This controls the b2g specific of pausing the media element when the
 // AudioChannel tells us to mute it.
 #define PAUSE_MEDIA_ELEMENT_FROM_AUDIOCHANNEL
 #endif
@@ -4008,17 +4009,24 @@ bool HTMLMediaElement::IsBeingDestroyed(
 }
 
 void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
 {
   bool pauseElement = NotifyOwnerDocumentActivityChangedInternal();
   if (pauseElement && mAudioChannelAgent) {
     // If the element is being paused since we are navigating away from the
     // document, notify the audio channel agent.
-    NotifyAudioChannelAgent(false);
+    // Be careful to ignore this event during a docshell frame swap.
+    auto docShell = static_cast<nsDocShell*>(OwnerDoc()->GetDocShell());
+    if (!docShell) {
+      return;
+    }
+    if (!docShell->InFrameSwap()) {
+      NotifyAudioChannelAgent(false);
+    }
   }
 }
 
 bool
 HTMLMediaElement::NotifyOwnerDocumentActivityChangedInternal()
 {
   nsIDocument* ownerDoc = OwnerDoc();
   if (mDecoder && !IsBeingDestroyed()) {
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2387,21 +2387,28 @@ TabChild::RecvSwappedWithOtherRemoteLoad
     return true;
   }
 
   nsCOMPtr<nsPIDOMWindow> ourWindow = ourDocShell->GetWindow();
   if (NS_WARN_IF(!ourWindow)) {
     return true;
   }
 
+  nsRefPtr<nsDocShell> docShell = static_cast<nsDocShell*>(ourDocShell.get());
+
   nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
 
+  docShell->SetInFrameSwap(true);
+
   nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false);
   nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget);
   nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true);
+
+  docShell->SetInFrameSwap(false);
+
   return true;
 }
 
 bool
 TabChild::RecvDestroy()
 {
   MOZ_ASSERT(mDestroyed == false);
   mDestroyed = true;
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -273,29 +273,29 @@ GLBlitHelper::InitTexQuadProgram(BlitTyp
 
     For [0,1] instead of [0,255], and to 5 places:
     [R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275]
     [G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196]
     [B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
     */
     const char kTexYUVPlanarBlit_FragShaderSource[] = "\
         #ifdef GL_ES                                                        \n\
-        precision mediump float                                             \n\
+        precision mediump float;                                            \n\
         #endif                                                              \n\
         varying vec2 vTexCoord;                                             \n\
         uniform sampler2D uYTexture;                                        \n\
         uniform sampler2D uCbTexture;                                       \n\
         uniform sampler2D uCrTexture;                                       \n\
         uniform vec2 uYTexScale;                                            \n\
         uniform vec2 uCbCrTexScale;                                         \n\
         void main()                                                         \n\
         {                                                                   \n\
-            float y = texture2D(uYTexture, vTexCoord * uYTexScale).r;       \n\
-            float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).r;  \n\
-            float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).r;  \n\
+            float y = texture2D(uYTexture, vTexCoord * uYTexScale).a;       \n\
+            float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).a;  \n\
+            float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).a;  \n\
             y = (y - 0.06275) * 1.16438;                                    \n\
             cb = cb - 0.50196;                                              \n\
             cr = cr - 0.50196;                                              \n\
             gl_FragColor.r = y + cr * 1.59603;                              \n\
             gl_FragColor.g = y - 0.81297 * cr - 0.39176 * cb;               \n\
             gl_FragColor.b = y + cb * 2.01723;                              \n\
             gl_FragColor.a = 1.0;                                           \n\
         }                                                                   \n\
@@ -636,40 +636,40 @@ GLBlitHelper::BindAndUploadYUVTexture(Ch
                                       void* data,
                                       bool needsAllocation)
 {
     MOZ_ASSERT(which < Channel_Max, "Invalid channel!");
     GLuint* srcTexArr[3] = {&mSrcTexY, &mSrcTexCb, &mSrcTexCr};
     GLuint& tex = *srcTexArr[which];
     if (!tex) {
         MOZ_ASSERT(needsAllocation);
-        tex = CreateTexture(mGL, LOCAL_GL_LUMINANCE, LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE,
+        tex = CreateTexture(mGL, LOCAL_GL_ALPHA, LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE,
                             gfx::IntSize(width, height), false);
     }
     mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + which);
 
     mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, tex);
     if (!needsAllocation) {
         mGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
                             0,
                             0,
                             0,
                             width,
                             height,
-                            LOCAL_GL_LUMINANCE,
+                            LOCAL_GL_ALPHA,
                             LOCAL_GL_UNSIGNED_BYTE,
                             data);
     } else {
         mGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
                          0,
-                         LOCAL_GL_LUMINANCE,
+                         LOCAL_GL_ALPHA,
                          width,
                          height,
                          0,
-                         LOCAL_GL_LUMINANCE,
+                         LOCAL_GL_ALPHA,
                          LOCAL_GL_UNSIGNED_BYTE,
                          data);
     }
 }
 
 void
 GLBlitHelper::BindAndUploadEGLImage(EGLImage image, GLuint target)
 {
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -448,30 +448,36 @@ LayerManagerComposite::RenderDebugOverla
       EffectChain effects;
       effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(1, 0, 0, 1));
       mCompositor->DrawQuad(gfx::Rect(aBounds.width - 20, 0, aBounds.width, 20),
                             aBounds, effects, alpha, gfx::Matrix4x4());
 
       mUnusedApzTransformWarning = false;
       SetDebugOverlayWantsNextFrame(true);
     }
+
+    // Each frame is invalidate by the previous frame for simplicity
+    AddInvalidRegion(nsIntRect(0, 0, 256, 256));
   } else {
     mFPS = nullptr;
   }
 
   if (drawFrameColorBars) {
     gfx::Rect sideRect(0, 0, 10, aBounds.height);
 
     EffectChain effects;
     effects.mPrimaryEffect = new EffectSolidColor(gfxUtils::GetColorForFrameNumber(sFrameCount));
     mCompositor->DrawQuad(sideRect,
                           sideRect,
                           effects,
                           1.0,
                           gfx::Matrix4x4());
+
+    // Each frame is invalidate by the previous frame for simplicity
+    AddInvalidRegion(nsIntRect(0, 0, sideRect.width, sideRect.height));
   }
 
 #ifdef MOZ_PROFILING
   if (drawFrameCounter) {
     profiler_set_frame_number(sFrameCount);
     const char* qr = sQRCodeTable[sFrameCount%256];
 
     int size = 21;
@@ -504,16 +510,19 @@ LayerManagerComposite::RenderDebugOverla
                                           bitWidth, bitWidth),
                                 clip,
                                 effects,
                                 opacity,
                                 gfx::Matrix4x4());
         }
       }
     }
+
+    // Each frame is invalidate by the previous frame for simplicity
+    AddInvalidRegion(nsIntRect(0, 0, 256, 256));
   }
 #endif
 
   if (drawFrameColorBars || drawFrameCounter) {
     // We intentionally overflow at 2^16.
     sFrameCount++;
   }
 }
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -92,35 +92,38 @@ ifeq ($(MOZ_DEBUG),1)
 endif
 
 ifdef MOZ_VALGRIND
 ifndef MOZ_ASAN
 JITTEST_VALGRIND_FLAG = --valgrind
 endif
 endif
 
+ifneq ($(LLVM_SYMBOLIZER),)
+# Use the LLVM symbolizer when running jit-tests under ASan and TSan, if available
 ifdef MOZ_ASAN
-ifneq ($(LLVM_SYMBOLIZER),)
-# Use the LLVM symbolizer when running jit-tests under ASan, if available
-JITTEST_ASAN_ENV=ASAN_SYMBOLIZER_PATH='$(LLVM_SYMBOLIZER)'
+JITTEST_SANITIZER_ENV=ASAN_SYMBOLIZER_PATH='$(LLVM_SYMBOLIZER)'
+endif
+ifdef MOZ_TSAN
+JITTEST_SANITIZER_ENV=TSAN_OPTIONS='external_symbolizer_path=$(LLVM_SYMBOLIZER)'
 endif
 endif
 
 check-style::
 	(cd $(srcdir) && $(PYTHON) $(topsrcdir)/config/check_spidermonkey_style.py);
 
 check-masm::
 	(cd $(srcdir) && $(PYTHON) $(topsrcdir)/config/check_macroassembler_style.py);
 
 check-jit-test::
-	$(JITTEST_ASAN_ENV) $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \
+	$(JITTEST_SANITIZER_ENV) $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \
 	        --no-slow --no-progress --format=automation --jitflags=all \
 			$(JITTEST_VALGRIND_FLAG) \
 			$(JITTEST_EXTRA_ARGS) \
-	        $(DIST)/bin/$(JS_SHELL_NAME)$(BIN_SUFFIX)
+	        $(DIST)/bin/$(JS_SHELL_NAME)$(BIN_SUFFIX) $(JITTEST_TEST_ARGS)
 
 check:: check-style check-masm
 
 check-jstests:
 	$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/tests/jstests.py \
 		--no-progress --format=automation --timeout 300 \
 		$(JSTESTS_EXTRA_ARGS) \
 		$(DIST)/bin/$(JS_SHELL_NAME)$(BIN_SUFFIX)
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -262,20 +262,19 @@ const JSPropertySpec MapObject::staticPr
     JS_PS_END
 };
 
 static JSObject*
 InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSProtoKey key, Native construct,
           const JSPropertySpec* properties, const JSFunctionSpec* methods,
           const JSPropertySpec* staticProperties)
 {
-    RootedNativeObject proto(cx, global->createBlankPrototype(cx, clasp));
+    RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
     if (!proto)
         return nullptr;
-    proto->setPrivate(nullptr);
 
     Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0));
     if (!ctor ||
         !JS_DefineProperties(cx, ctor, staticProperties) ||
         !LinkConstructorAndPrototype(cx, ctor, proto) ||
         !DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
         !GlobalObject::initBuiltinConstructor(cx, global, key, ctor, proto))
     {
--- a/js/src/jit-test/tests/collections/Map-surfaces-1.js
+++ b/js/src/jit-test/tests/collections/Map-surfaces-1.js
@@ -8,17 +8,21 @@ assertEq(desc.configurable, true);
 assertEq(desc.writable, true);
 
 assertEq(typeof Map, 'function');
 assertEq(Object.keys(Map).length, 0);
 assertEq(Map.length, 0);
 assertEq(Map.name, "Map");
 
 assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype);
-assertEq(Object.prototype.toString.call(Map.prototype), "[object Map]");
+assertEq("toStringTag" in Symbol, false,
+         "if this fails, congratulations!  implement " +
+         "Map.prototype[Symbol.toStringTag] = 'Map' in SpiderMonkey and make " +
+         "the next test check for '[object Map]' again");
+assertEq(Object.prototype.toString.call(Map.prototype), "[object Object]");
 assertEq(Object.prototype.toString.call(new Map()), "[object Map]");
 assertEq(Object.keys(Map.prototype).join(), "");
 assertEq(Map.prototype.constructor, Map);
 
 function checkMethod(name, arity) { 
     var desc = Object.getOwnPropertyDescriptor(Map.prototype, name);
     assertEq(desc.enumerable, false);
     assertEq(desc.configurable, true);
--- a/js/src/jit-test/tests/collections/Set-surfaces-1.js
+++ b/js/src/jit-test/tests/collections/Set-surfaces-1.js
@@ -8,17 +8,21 @@ assertEq(desc.configurable, true);
 assertEq(desc.writable, true);
 
 assertEq(typeof Set, 'function');
 assertEq(Object.keys(Set).length, 0);
 assertEq(Set.length, 0);
 assertEq(Set.name, "Set");
 
 assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype);
-assertEq(Object.prototype.toString.call(Set.prototype), "[object Set]");
+assertEq("toStringTag" in Symbol, false,
+         "if this fails, congratulations!  implement " +
+         "Set.prototype[Symbol.toStringTag] = 'Set' in SpiderMonkey and make " +
+         "the next test check for '[object Set]' again");
+assertEq(Object.prototype.toString.call(Set.prototype), "[object Object]");
 assertEq(Object.prototype.toString.call(new Set()), "[object Set]");
 assertEq(Object.keys(Set.prototype).join(), "");
 assertEq(Set.prototype.constructor, Set);
 
 function checkMethod(name, arity) { 
     var desc = Object.getOwnPropertyDescriptor(Set.prototype, name);
     assertEq(desc.enumerable, false);
     assertEq(desc.configurable, true);
--- a/layout/base/MobileViewportManager.cpp
+++ b/layout/base/MobileViewportManager.cpp
@@ -185,21 +185,24 @@ MobileViewportManager::UpdateResolution(
 }
 
 void
 MobileViewportManager::UpdateSPCSPS(const ScreenIntSize& aDisplaySize,
                                     const CSSToScreenScale& aZoom)
 {
   ScreenSize compositionSize(aDisplaySize);
   ScreenMargin scrollbars =
-    CSSMargin::FromAppUnits(
+    LayoutDeviceMargin::FromAppUnits(
       nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor(
-        mPresShell->GetRootScrollFrame()))
-    * CSSToScreenScale(1.0f); // Scrollbars are not subject to scaling, so
-                              // CSS pixels = layer pixels for them (modulo bug 1168487).
+        mPresShell->GetRootScrollFrame()),
+      mPresShell->GetPresContext()->AppUnitsPerDevPixel())
+    // Scrollbars are not subject to resolution scaling, so LD pixels =
+    // Screen pixels for them.
+    * LayoutDeviceToScreenScale(1.0f);
+
   compositionSize.width -= scrollbars.LeftRight();
   compositionSize.height -= scrollbars.TopBottom();
   CSSSize compSize = compositionSize / aZoom;
   MVM_LOG("%p: Setting SPCSPS %s\n", this, Stringify(compSize).c_str());
   nsLayoutUtils::SetScrollPositionClampingScrollPortSize(mPresShell, compSize);
 }
 
 void
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1072,16 +1072,20 @@ nsLayoutUtils::SetDisplayPortMargins(nsI
   MOZ_ASSERT(aContent->GetComposedDoc() == aPresShell->GetDocument());
 
   DisplayPortMarginsPropertyData* currentData =
     static_cast<DisplayPortMarginsPropertyData*>(aContent->GetProperty(nsGkAtoms::DisplayPortMargins));
   if (currentData && currentData->mPriority > aPriority) {
     return false;
   }
 
+  if (currentData && currentData->mMargins == aMargins) {
+    return true;
+  }
+
   aContent->SetProperty(nsGkAtoms::DisplayPortMargins,
                         new DisplayPortMarginsPropertyData(
                             aMargins, aPriority),
                         nsINode::DeleteProperty<DisplayPortMarginsPropertyData>);
 
   if (gfxPrefs::LayoutUseContainersForRootFrames()) {
     nsIFrame* rootScrollFrame = aPresShell->GetRootScrollFrame();
     if (rootScrollFrame &&
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2221,17 +2221,17 @@ void ScrollFrameHelper::MarkRecentlyScro
   } else {
     if (!gScrollFrameActivityTracker) {
       gScrollFrameActivityTracker = new ScrollFrameActivityTracker();
     }
     gScrollFrameActivityTracker->AddObject(this);
   }
 }
 
-void ScrollFrameHelper::ScrollVisual(nsPoint aOldScrolledFramePos)
+void ScrollFrameHelper::ScrollVisual()
 {
   // Mark this frame as having been scrolled. If this is the root
   // scroll frame of a content document, then IsAlwaysActive()
   // will return true from now on and MarkNotRecentlyScrolled() won't
   // have any effect.
   mHasBeenScrolled = true;
 
   AdjustViews(mScrolledFrame);
@@ -2240,17 +2240,16 @@ void ScrollFrameHelper::ScrollVisual(nsP
   bool needToInvalidateOnScroll = NeedToInvalidateOnScroll(mOuter);
   mOuter->RemoveStateBits(NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL);
   if (needToInvalidateOnScroll) {
     MarkNotRecentlyScrolled();
   } else {
     MarkRecentlyScrolled();
   }
 
-  mOuter->SchedulePaint();
 }
 
 /**
  * Clamp desired scroll position aDesired and range [aDestLower, aDestUpper]
  * to [aBoundLower, aBoundUpper] and then select the appunit value from among
  * aBoundLower, aBoundUpper and those such that (aDesired - aCurrent) *
  * aRes/aAppUnitsPerPixel is an integer (or as close as we can get
  * modulo rounding to appunits) that is in [aDestLower, aDestUpper] and
@@ -2414,25 +2413,45 @@ ScrollFrameHelper::ScrollToImpl(nsPoint 
     presContext->PresShell()->ScheduleImageVisibilityUpdate();
   }
 
   // notify the listeners.
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->ScrollPositionWillChange(pt.x, pt.y);
   }
 
-  nsPoint oldScrollFramePos = mScrolledFrame->GetPosition();
+  nsRect oldDisplayPort;
+  nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &oldDisplayPort);
+  oldDisplayPort.MoveBy(-mScrolledFrame->GetPosition());
+
   // Update frame position for scrolling
   mScrolledFrame->SetPosition(mScrollPort.TopLeft() - pt);
   mLastScrollOrigin = aOrigin;
   mLastSmoothScrollOrigin = nullptr;
   mScrollGeneration = ++sScrollGenerationCounter;
 
-  // We pass in the amount to move visually
-  ScrollVisual(oldScrollFramePos);
+  ScrollVisual();
+
+  if (LastScrollOrigin() == nsGkAtoms::apz) {
+    // If this was an apz scroll and the displayport (relative to the
+    // scrolled frame) hasn't changed, then this won't trigger
+    // any painting, so no need to schedule one.
+    nsRect displayPort;
+    DebugOnly<bool> usingDisplayPort =
+      nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort);
+    NS_ASSERTION(usingDisplayPort, "Must have a displayport for apz scrolls!");
+
+    displayPort.MoveBy(-mScrolledFrame->GetPosition());
+
+    if (!displayPort.IsEqualEdges(oldDisplayPort)) {
+      mOuter->SchedulePaint();
+    }
+  } else {
+    mOuter->SchedulePaint();
+  }
 
   if (mOuter->ChildrenHavePerspective()) {
     // The overflow areas of descendants may depend on the scroll position,
     // so ensure they get updated.
     mOuter->RecomputePerspectiveChildrenOverflow(mOuter->StyleContext(), nullptr);
   }
 
   ScheduleSyntheticMouseMove();
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -217,17 +217,17 @@ public:
   void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
                                     nsIAtom* aOrigin = nullptr);
 
   CSSIntPoint GetScrollPositionCSSPixels();
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    */
   void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange, nsIAtom* aOrigin = nullptr);
-  void ScrollVisual(nsPoint aOldScrolledFramePosition);
+  void ScrollVisual();
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    */
   void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit,
                 nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow,
                 nsIAtom* aOrigin = nullptr,
                 nsIScrollableFrame::ScrollMomentum aMomentum = nsIScrollableFrame::NOT_MOMENTUM,
                 nsIScrollbarMediator::ScrollSnapMode aSnap
new file mode 100755
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/check-for-references.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+cd "$(dirname "$0")"
+find . -name reftest.list | sed 's,/reftest.list$,,' | while read DIRNAME
+do
+    cat "$DIRNAME/reftest.list" | grep -v "^\(include\|default-preferences\)" | sed 's/ #.*//;s/^#.*//;s/.* == /== /;s/.* != /!= /' | grep -v "^ *$" | while read TYPE TEST REF
+    do
+        REFTYPE=""
+        if [ "$TYPE" == "==" ]
+        then
+            REFTYPE="match"
+        elif [ "$TYPE" == "!=" ]
+        then
+            REFTYPE="mismatch"
+        else
+            echo "Unexpected type $TYPE for $DIRNAME/$TEST"
+        fi
+        if grep "rel=\"$REFTYPE\"" "$DIRNAME/$TEST" | head -1 | grep -q "href=\"$REF\""
+        then
+            #echo "Good link for $DIRNAME/$TEST"
+            echo -n
+        else
+            echo "Missing link for $DIRNAME/$TEST"
+            #echo "<link rel=\"$REFTYPE\" href=\"$REF\">" >> "$DIRNAME/$TEST"
+        fi
+    done
+done
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-1.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; page-break-before:always; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-10.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-10.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-11.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-11.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-12.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-12.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-13.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-13.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-8-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-14.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-14.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-14-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; height:1.5in; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-15.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-15.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-15-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; height:2.5in; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-2.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-2.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-3.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-3.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-4.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-4.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-5.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-5.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-6.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-6.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; overflow:hidden; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-7.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-7.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; overflow:hidden; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-8.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-8.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-8-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; overflow:hidden; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-9.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-9.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-1.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; float:left; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-2.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-2.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-float-page-break-inside-avoid-2-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { float:left; page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-3.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-3.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { float:left; page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-4.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-4.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-block-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { float:left; page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-5.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-5.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-float-page-break-inside-avoid-5-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
         html,body {
             color:black; background-color:white; font-size:16px; padding:0; margin:0;
         }
 p { height: 0.5in; width: 1in; margin:0; background-color:blue; float:left; }
 .test { float:left; clear:left; page-break-inside:avoid; width:3.3in; }
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-6.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-6.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-float-page-break-inside-avoid-6-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 html,body {
     color:black; background-color:white; font-size:16px; padding:0; margin:0; height:100%;
 }
 p { height:60%; width:90%; margin:0; background-color:blue; border:1px solid black; }
 .test { page-break-inside:avoid; float:left; }
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-7.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-7.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-float-page-break-inside-avoid-7-ref.html">
   <meta name="flags" content="paged"><style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 html,body {
     color:black; background-color:white; font-size:16px; padding:0; margin:0; height:100%;
 }
 
 .test { 
   page-break-inside:avoid;
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-8.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-8.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-float-page-break-inside-avoid-8-ref.html">
   <meta name="flags" content="paged"><style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 html,body {
     color:black; background-color:white; font-size:16px; padding:0; margin:0; height:100%;
 }
 
 .test { 
   page-break-inside:avoid;
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-9.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-float-page-break-inside-avoid-9.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-float-page-break-inside-avoid-9-ref.html">
   <meta name="flags" content="paged"><style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 html,body {
     color:black; background-color:white; font-size:16px; padding:0; margin:0; height:100%;
 }
 
 .test { 
   page-break-inside:avoid;
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-inline-page-break-inside-avoid-1.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-inline-page-break-inside-avoid-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-inline-page-break-inside-avoid-1-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-row-page-break-inside-avoid-1.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-row-page-break-inside-avoid-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-rowgroup-page-break-inside-avoid-5-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-row-page-break-inside-avoid-2.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-row-page-break-inside-avoid-2.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-rowgroup-page-break-inside-avoid-5-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-1.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-2.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-2.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-3.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-3.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-4.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-4.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-rowgroup-page-break-inside-avoid-4-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-5.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-5.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-rowgroup-page-break-inside-avoid-5-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-6.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-6.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-rowgroup-page-break-inside-avoid-5-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 .bb { page-break-before:always; }
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-7.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-7.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-rowgroup-page-break-inside-avoid-7-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-8.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-rowgroup-page-break-inside-avoid-8.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-rowgroup-page-break-inside-avoid-8-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 .bb { page-break-before:always; }
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-1.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-2.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-2.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-2-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-3.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-3.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-3-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 table { display:inline-table; }
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-4.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-4.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-4-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 table { display:inline-table; }
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-5.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-5.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-5-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 tr { page-break-before:always; }
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-6.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-6-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-7.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-7-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-8.html
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-table-page-break-inside-avoid-8.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <html lang="en-US" class="reftest-print">
 <head>
   <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-css21-table-page-break-inside-avoid-6-ref.html">
   <meta name="flags" content="paged">
 <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 p { height: 1in; width: 1in; margin:0; background-color:blue; }
 .test { page-break-inside:avoid; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/multicol3/moz-multicol3-column-balancing-break-inside-avoid-1.html
+++ b/layout/reftests/w3c-css/submitted/multicol3/moz-multicol3-column-balancing-break-inside-avoid-1.html
@@ -1,13 +1,14 @@
 <!DOCTYPE HTML>
 <html><head>
   <title>CSS Test: Balancing Overflow, page-break-inside:avoid</title>
   <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <link rel="match" href="moz-multicol3-column-balancing-break-inside-avoid-1-ref.html">
   <meta name="flags" content="paged">
   <meta charset="utf-8">
   <style type="text/css">
 @page { size:5in 3in; margin:0.5in; }
 
         html,body {
             color:black; background-color:white; font-size:16px; padding:0; margin:0;
         }
--- a/layout/reftests/w3c-css/submitted/test-template-001.xht
+++ b/layout/reftests/w3c-css/submitted/test-template-001.xht
@@ -2,17 +2,17 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: {{ brief but unique descriptive title of what's being tested }}</title>
   <link rel="author" title="{{ test author's name }}" href="{{ test author's contact info (mailto or http) }}" />
   <link rel="help" href="http://www.w3.org/TR/{{ URL to specific spec section; for multiple LINKs put primary first }}" />
   <meta name="flags" content="{{ see http://wiki.csswg.org/test/format#requirement-flags }}" />
   <meta name="assert" content="{{ explain precisely what is asserted when the test passes;
                                   optional but helps coordination and review }}" />
-  <link rel="match" href="test-template-001-ref.xht" />
+  <link rel="match" href="references/test-template-001.xht" />
   <style type="text/css"><![CDATA[
    {{ css for the test }}
   ]]></style>
  </head>
  <body>
    <!-- content of test -->
  </body>
 </html>
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht
@@ -1,14 +1,15 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: Box Sizing - Border-Box with specified width</title>
   <link rel="author" title="Scott Johnson" href="mailto:sjohnson@mozilla.com" />
   <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+  <link rel="match" href="box-sizing-border-box-001-ref.xht" />
   <meta name="assert" content="box-sizing: border-box should make the element's (percentage) width be the distance from the left border edge to the right border edge." />
   <style type="text/css"><![CDATA[
     .container {
       width: 300px;
       border: 2px solid black;
       position: absolute;
       left: 25px;
       top: 25px;
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002.xht
@@ -1,14 +1,15 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: Box Sizing - Border-Box with specified width</title>
   <link rel="author" title="Scott Johnson" href="mailto:sjohnson@mozilla.com" />
   <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+  <link rel="match" href="box-sizing-border-box-002-ref.xht" />
   <meta name="assert" content="box-sizing: border-box should make the element's (percentage) width be the distance from the left border edge to the right border edge." />
   <style type="text/css"><![CDATA[
     .container {
       width: 300px;
       border: 2px solid black;
       position: absolute;
       left: 25px;
       top: 25px;
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003.xht
@@ -1,14 +1,15 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: Box Sizing - Border-Box with specified width/height</title>
   <link rel="author" title="Scott Johnson" href="mailto:sjohnson@mozilla.com" />
   <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+  <link rel="match" href="box-sizing-border-box-003-ref.xht" />
   <meta name="assert" content="box-sizing: border-box should make the element's (percentage) width be the distance from the left border edge to the right border edge and the height be the distance from the top border edge to the bottom border edge." />
   <style type="text/css"><![CDATA[
     .container {
       width: 300px;
       height: 400px;
       border: 2px solid black;
       position: absolute;
       left: 25px;
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004.xht
@@ -1,14 +1,15 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: Box Sizing - Border-Box with min/max width/height</title>
   <link rel="author" title="Scott Johnson" href="mailto:sjohnson@mozilla.com" />
   <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+  <link rel="match" href="box-sizing-border-box-004-ref.xht" />
   <meta name="assert" content="box-sizing: border-box should make the element's (length) width be the distance from the left border edge to the right border edge and the height be the distance from the top border edge to the bottom border edge." />
   <style type="text/css"><![CDATA[
     .container {
       min-width: 500px;
       max-width: 700px;
       min-height: 70px;
       max-height: 90px;
       border: 2px solid black;
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001.xht
@@ -1,14 +1,15 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: Box Sizing - Content-Box with specified width/height</title>
   <link rel="author" title="Scott Johnson" href="mailto:sjohnson@mozilla.com" />
   <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+  <link rel="match" href="box-sizing-content-box-001-ref.xht" />
   <meta name="assert" content="box-sizing: content-box should make the element's (percentage) width be the distance from the left content edge to the right content edge and the height be the distance from the top content edge to the bottom content edge."/>
   <style type="text/css"><![CDATA[
     .container {
       width: 300px;
       height: 110px;
       border: 2px solid black;
       position: absolute;
       left: 25px;
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002.xht
@@ -1,14 +1,15 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: Box Sizing - Content-Box with specified width/height</title>
   <link rel="author" title="Scott Johnson" href="mailto:sjohnson@mozilla.com" />
   <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+  <link rel="match" href="box-sizing-content-box-002-ref.xht" />
   <meta name="assert" content="box-sizing: content-box should make the element's (calc) width be the distance from the left content edge to the right content edge and the height be the distance from the top content edge to the bottom content edge."/>
   <style type="text/css"><![CDATA[
     .container {
       width: 300px;
       height: 100px;
       border: 2px solid black;
       position: absolute;
       left: 25px;
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003.xht
@@ -1,14 +1,15 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
   <title>CSS Test: Box Sizing - Content-Box with min/max width/height</title>
   <link rel="author" title="Scott Johnson" href="mailto:sjohnson@mozilla.com" />
   <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+  <link rel="match" href="box-sizing-content-box-003-ref.xht" />
   <meta name="assert" content="box-sizing: content-box should make the element's (percentage) width be the distance from the left content edge to the right content edge and the height be the distance from the top content edge to the bottom content edge."/>
   <style type="text/css"><![CDATA[
     .container {
       min-width: 500px;
       max-width: 700px;
       height: 90px;
       border: 2px solid black;
       position: absolute;
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001.xht
@@ -1,15 +1,16 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>CSS Test: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing</title>
     <link href="http://fantasai.inkedblade.net/contact" title="Elika J. Etemad" rel="author"></link>
     <link href="mailto:sjohnson@mozilla.com" title="Scott Johnson" rel="author"></link>
     <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+    <link rel="match" href="box-sizing-replaced-001-ref.xht" />
     <meta content="image" name="flags"></meta>
     <meta name="assert" content="All images should be sized at 75px x 75px, with 5px of padding around each." />
     <!--
       This test is derived from replaced-min-max-001, part of the W3C CSS 2.1
       test suite.
     -->
     <style type="text/css">
       p {
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002.xht
@@ -1,15 +1,16 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>CSS Test: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing</title>
     <link href="http://fantasai.inkedblade.net/contact" title="Elika J. Etemad" rel="author"></link>
     <link href="mailto:sjohnson@mozilla.com" title="Scott Johnson" rel="author"></link>
     <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+    <link rel="match" href="box-sizing-replaced-002-ref.xht" />
     <meta content="image" name="flags"></meta>
     <meta name="assert" content="All images should be sized at 75px x 75px, with 5px of padding and 5px of blue border around each." />
     <!--
       This test is derived from replaced-min-max-001, part of the W3C CSS 2.1
       test suite.
     -->
     <style type="text/css">
       p {
--- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003.xht
+++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003.xht
@@ -1,15 +1,16 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>CSS Test: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing</title>
     <link href="http://fantasai.inkedblade.net/contact" title="Elika J. Etemad" rel="author"></link>
     <link href="mailto:sjohnson@mozilla.com" title="Scott Johnson" rel="author"></link>
     <link rel="help" href="http://www.w3.org/TR/css3-ui/#box-sizing" />
+    <link rel="match" href="box-sizing-replaced-003-ref.xht" />
     <meta content="image" name="flags"></meta>
     <meta name="assert" content="All images should be sized at 75px x 75px." />
     <!--
       This test is derived from replaced-min-max-001, part of the W3C CSS 2.1
       test suite.
     -->
     <style type="text/css">
       p {
--- a/layout/reftests/w3c-css/submitted/values3/calc-background-image-gradient-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-background-image-gradient-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for calc() on background-image gradients</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-background-image-gradient-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 p {
     height: 50px; width: 200px;
     border: thin solid;
 }
 
--- a/layout/reftests/w3c-css/submitted/values3/calc-background-linear-gradient-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-background-linear-gradient-1.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <head>
   <title>CSS Test: Support calc() on gradient stop positions</title>
   <link rel="author" title="Yu-Sian (Thomasy) Liu" href="https://bugzilla.mozilla.org/show_bug.cgi?id=594935">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-background-linear-gradient-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 div {
  width:100px;
  height:100px;
  background:red;
  margin:5px 0 0 5px;
  float:left;
--- a/layout/reftests/w3c-css/submitted/values3/calc-background-position-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-background-position-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for calc() on background-position</title>
   <link rel="author" title="L. David Baron" href="https://bugzilla.mozilla.org/show_bug.cgi?id=594934">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-background-position-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 p {
     height: 50px; width: 200px;
     border: thin solid;
     background-image: url(../backgrounds/blue-32x32.png);
     background-repeat: no-repeat;
--- a/layout/reftests/w3c-css/submitted/values3/calc-background-size-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-background-size-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for calc() on background-size</title>
   <link rel="author" title="L. David Baron" href="https://bugzilla.mozilla.org/show_bug.cgi?id=594934">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-background-size-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 p {
     height: 50px; width: 200px;
     border: thin solid;
     background-image: url(../backgrounds/blue-32x32.png);
     background-repeat: no-repeat;
--- a/layout/reftests/w3c-css/submitted/values3/calc-border-radius-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-border-radius-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: test for border-radius: calc()</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-border-radius-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 p {
   /* We use powers of two here to avoid floating-point issues.
      See bug 590181. */
 
   height: 256px;
--- a/layout/reftests/w3c-css/submitted/values3/calc-height-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-height-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for height:calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-height-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 }
 body > div { float: left; height: 100px; width: 1px; }
 body > div > div { background: blue }
 
 /* for auto-height tests */
 body > div > div > div > div { height: 10px }
--- a/layout/reftests/w3c-css/submitted/values3/calc-height-table-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-height-table-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test that height:calc() with no percentages has an effect on inner table elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-height-table-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 tbody, tr, td {
   height: calc(500px);
   min-height: calc(700px);
   max-height: calc(2px);
 }
 </style>
--- a/layout/reftests/w3c-css/submitted/values3/calc-margin-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-margin-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test of margin-*: calc()</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-margin-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 div { border: medium solid green; width: 500px }
 p { background: yellow }
 
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/values3/calc-max-height-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-max-height-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for max-height:calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-max-height-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 }
 body > div { float: left; height: 100px; width: 1px; }
 body > div > div { background: blue }
 
 /* to give the max-height something to restrict */
 span { display: block; height: 300px }
--- a/layout/reftests/w3c-css/submitted/values3/calc-max-width-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-max-width-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: max-width: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-width-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { width: 500px }
 p { background: green; color: white; margin: 1px 0; font-size: 10px; width: 1000px; }
 
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/values3/calc-max-width-block-intrinsic-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-max-width-block-intrinsic-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: intrinsic width of max-width: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-max-width-block-intrinsic-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { font-size: 10px }
 body > div { float: left; clear: left;
              margin: 0 0 1px 0; background: blue; color: white; height: 5px }
 body > div > div { width: 400px }
 body > div > div > div { width: 200px }
--- a/layout/reftests/w3c-css/submitted/values3/calc-min-height-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-min-height-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for min-height:calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-height-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 }
 body > div { float: left; height: 100px; width: 1px; }
 body > div > div { background: blue }
 
 /* for auto-height tests */
 body > div > div > div > div { height: 10px }
--- a/layout/reftests/w3c-css/submitted/values3/calc-min-width-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-min-width-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: min-width: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-width-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { width: 500px }
 p { background: green; color: white; margin: 1px 0; font-size: 10px; width: 0 }
 
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/values3/calc-min-width-block-intrinsic-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-min-width-block-intrinsic-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: intrinsic width of min-width: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-min-width-block-intrinsic-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { font-size: 10px }
 body > div { float: left; clear: left;
              margin: 0 0 1px 0; background: blue; color: white; height: 5px }
 body > div > div { width: 1px }
 body > div > div > div { width: 200px }
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-bottom-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-bottom-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for bottom:calc() on absolutely positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-absolute-top-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 }
 body > div { float: left; margin-top: -90px; height: 100px; margin-bottom: 90px; width: 3px; position: relative }
 div[style] { background: blue; position: absolute; height: 10px; width: 3px }
 div.space { height: 100px }
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-left-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-left-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for left:calc() on absolutely positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-relative-left-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 100px; width: 200px }
 body > div { height: 3px; position: relative }
 div[style] { background: blue; position: absolute; height: 3px; width: 100px }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-right-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-right-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for right:calc() on absolutely positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-relative-left-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0; width: 200px }
 body > div { height: 3px; position: relative }
 div[style] { background: blue; position: absolute; height: 3px; width: 100px }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-top-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-absolute-top-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for top:calc() on absolutely positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-absolute-top-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 }
 body > div { float: left; height: 100px; width: 3px; position: relative }
 div[style] { background: blue; position: absolute; height: 10px; width: 3px }
 div.space { height: 100px }
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-bottom-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-bottom-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for bottom:calc() on relatively positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-relative-top-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 }
 body > div { float: left; height: 100px; width: 3px; }
 div[style] { background: blue; position: relative; height: 10px; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-left-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-left-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for left:calc() on relatively positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-relative-left-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 100px; width: 100px }
 div[style] { background: blue; position: relative; height: 3px; }
 </style>
 </head>
 <body>
 
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-right-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-right-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for right:calc() on relatively positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-relative-left-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 100px; width: 100px }
 div[style] { background: blue; position: relative; height: 3px; }
 </style>
 </head>
 <body>
 
--- a/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-top-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-offsets-relative-top-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for top:calc() on relatively positioned elements</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-offsets-relative-top-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 body { margin: 0 }
 body > div { float: left; height: 100px; width: 3px; }
 div[style] { background: blue; position: relative; height: 10px; }
 </style>
 </head>
 <body>
--- a/layout/reftests/w3c-css/submitted/values3/calc-padding-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-padding-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test of padding-*: calc()</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-padding-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { width: 500px }
 div { border: medium solid green }
 p { background: yellow; margin: 0 }
 
 </style>
--- a/layout/reftests/w3c-css/submitted/values3/calc-text-indent-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-text-indent-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: text-indent: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-text-indent-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { width: 500px }
 p { font-size: 10px }
 
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/values3/calc-text-indent-intrinsic-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-text-indent-intrinsic-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: intrinsic width of text-indent: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-text-indent-intrinsic-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { font-size: 10px }
 div { float: left; clear: left;
        margin: 0 0 1px 0; background: blue; color: white; height: 5px }
 span { display: inline-block; width: 10px }
 
--- a/layout/reftests/w3c-css/submitted/values3/calc-transform-origin-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-transform-origin-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for calc() on transform-origin</title>
   <link rel="author" title="L. David Baron" href="https://bugzilla.mozilla.org/show_bug.cgi?id=594934">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-transform-origin-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { margin: 100px }
 
 p {
     height: 50px; width: 200px;
     background: yellow;
--- a/layout/reftests/w3c-css/submitted/values3/calc-vertical-align-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-vertical-align-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: Test for vertical-align:calc()</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-vertical-align-1-ref.html">
   <meta name="flags" content="">
 
 <div style="line-height: 100px; margin-top: 100px">
   <span>x</span>
   <span style="vertical-align: calc(50px)">x</span>
   <span style="vertical-align: calc(50%)">x</span>
   <span style="vertical-align: calc(25px + 50%)">x</span>
   <span style="vertical-align: calc(150% / 2 - 30px)">x</span>
--- a/layout/reftests/w3c-css/submitted/values3/calc-width-block-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-width-block-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: width: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-width-block-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { width: 500px }
 p { background: green; color: white; margin: 1px 0; font-size: 10px }
 
 </style>
 </head>
--- a/layout/reftests/w3c-css/submitted/values3/calc-width-block-intrinsic-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-width-block-intrinsic-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: intrinsic width of width: calc() on blocks</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-width-block-intrinsic-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 
 body { font-size: 10px }
 body > div { float: left; clear: left;
              margin: 0 0 1px 0; background: blue; color: white; height: 5px }
 body > div > div > div { width: 200px }
 
--- a/layout/reftests/w3c-css/submitted/values3/calc-width-table-auto-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-width-table-auto-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: width: calc() on table-layout: auto tables</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-width-table-auto-1-ref.html">
   <meta name="flags" content="">
 <table border>
   <tr>
     <td style="width: calc(500px)">x</td>
     <td style="width: 100px">y</td>
 </table>
 <table border>
   <tr>
--- a/layout/reftests/w3c-css/submitted/values3/calc-width-table-fixed-1.html
+++ b/layout/reftests/w3c-css/submitted/values3/calc-width-table-fixed-1.html
@@ -1,14 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>CSS Test: width: calc() on table-layout: auto tables</title>
   <link rel="author" title="L. David Baron" href="http://dbaron.org/">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
+  <link rel="match" href="calc-width-table-fixed-1-ref.html">
   <meta name="flags" content="">
 <style type="text/css">
 table { table-layout: fixed; width: 500px; border-spacing: 0 }
 </style>
 </head>
 <body>
 <table border>
   <tr>
--- a/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html
+++ b/layout/reftests/w3c-css/submitted/variables/variable-external-font-face-01.html
@@ -1,13 +1,13 @@
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <!DOCTYPE html>
 <title>CSS Test: Test the invalid declaration and use of a variable in an @font-face rule within an external CSS.</title>
 <link rel="author" title="Mihaela Velimiroviciu" href="mailto:mihaela.velimiroviciu@softvisioninc.eu">
 <link rel="help" href="http://www.w3.org/TR/css-variables-1/#defining-variables">
-<link rel="match" href="variable-font-face-01-ref.html">
+<link rel="match" href="variable-external-font-face-01-ref.html">
 <link rel="stylesheet" type="text/css" href="support/external-variable-font-face.css">
 <meta name="flags" content="ahem">
 <p id=a>This text must not be in Ahem.</p>
 <p id=b>But this text must be in Ahem.</p>
--- a/layout/reftests/w3c-css/submitted/variables/variable-reference-38.html
+++ b/layout/reftests/w3c-css/submitted/variables/variable-reference-38.html
@@ -1,16 +1,16 @@
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <!DOCTYPE html>
 <title>CSS Test: Test using variables in overlapping shorthands.</title>
 <link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au">
 <link rel="help" href="http://www.w3.org/TR/css-variables-1/#variables-in-shorthands">
-<link rel="match" href="variable-declaration-59-ref.html">
+<link rel="match" href="variable-reference-38-ref.html">
 <style>
 p { padding-left: 1em; }
 #a { --style: solid; --left: black dotted; border-style: var(--style); border-left: var(--left); border-top: none; border-right: none; border-bottom: none; }
 #b { --style: solid; --left: black dotted; border-left: var(--left); border-style: var(--style); border-top: none; border-right: none; border-bottom: none; }
 </style>
 <p id=a>The left border must be dotted.</p>
 <p id=b>The left border must be solid.</p>
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -735,17 +735,20 @@ nsSliderFrame::CurrentPositionChanged()
   } else {
     newThumbRect.y = snappedThumbLocation.y;
   }
 
   // set the rect
   thumbFrame->SetRect(newThumbRect);
 
   // Request a repaint of the scrollbar
-  SchedulePaint();
+  nsIScrollableFrame* scrollableFrame = do_QueryFrame(GetScrollbar()->GetParent());
+  if (!scrollableFrame || scrollableFrame->LastScrollOrigin() != nsGkAtoms::apz) {
+    SchedulePaint();
+  }
 
   mCurPos = curPos;
 
   // inform the parent <scale> if it exists that the value changed
   nsIFrame* parent = GetParent();
   if (parent) {
     nsCOMPtr<nsISliderListener> sliderListener = do_QueryInterface(parent->GetContent());
     if (sliderListener) {
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -2630,20 +2630,16 @@ public class BrowserApp extends GeckoApp
                 break;
 
             default:
                 super.onActivityResult(requestCode, resultCode, data);
         }
     }
 
     private void showFirstrunPager() {
-        // Do not show first run if we're in an Android Restricted Profile
-        if (RestrictedProfiles.isUserRestricted(this)) {
-            return;
-        }
         if (mFirstrunPane == null) {
             final ViewStub firstrunPagerStub = (ViewStub) findViewById(R.id.firstrun_pager_stub);
             mFirstrunPane = (FirstrunPane) firstrunPagerStub.inflate();
             mFirstrunPane.load(getSupportFragmentManager());
             mFirstrunPane.registerOnFinishListener(new FirstrunPane.OnFinishListener() {
                 @Override
                 public void onFinish() {
                     BrowserApp.this.mFirstrunPane = null;
@@ -2849,18 +2845,20 @@ public class BrowserApp extends GeckoApp
      * user touches the main layout.
      */
     private class HideOnTouchListener implements TouchEventInterceptor {
         private boolean mIsHidingTabs;
         private final Rect mTempRect = new Rect();
 
         @Override
         public boolean onInterceptTouchEvent(View view, MotionEvent event) {
-            // Only try to hide the button toast if it's already inflated.
-            if (mToast != null) {
+            // Only try to hide the button toast if it's already inflated and if we are starting a tap action.
+            // By only hiding a toast at the start of a tap action, a button toast opened in response to a tap
+            // action is not immediately hidden as the tap action continues.
+            if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mToast != null) {
                 mToast.hide(false, ButtonToast.ReasonHidden.TOUCH_OUTSIDE);
             }
 
             // We need to account for scroll state for the touched view otherwise
             // tapping on an "empty" part of the view will still be considered a
             // valid touch event.
             if (view.getScrollX() != 0 || view.getScrollY() != 0) {
                 view.getHitRect(mTempRect);
--- a/mobile/android/base/firstrun/FirstrunPager.java
+++ b/mobile/android/base/firstrun/FirstrunPager.java
@@ -10,16 +10,18 @@ import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentPagerAdapter;
 import android.support.v4.view.ViewPager;
 import android.util.AttributeSet;
 import com.nineoldandroids.animation.Animator;
 import com.nineoldandroids.animation.AnimatorSet;
 import com.nineoldandroids.animation.ObjectAnimator;
 import com.nineoldandroids.view.ViewHelper;
+
+import org.mozilla.gecko.RestrictedProfiles;
 import org.mozilla.gecko.animation.TransitionsTracker;
 
 import java.util.List;
 
 public class FirstrunPager extends ViewPager {
     private Context context;
     protected FirstrunPane.OnFinishListener listener;
 
@@ -28,17 +30,25 @@ public class FirstrunPager extends ViewP
     }
 
     public FirstrunPager(Context context, AttributeSet attrs) {
         super(context, attrs);
         this.context = context;
     }
 
     public void load(FragmentManager fm, FirstrunPane.OnFinishListener listener) {
-        setAdapter(new ViewPagerAdapter(fm, FirstrunPagerConfig.getDefault()));
+        final List<FirstrunPagerConfig.FirstrunPanel> panels;
+
+        if (RestrictedProfiles.isUserRestricted(context)) {
+            panels = FirstrunPagerConfig.getRestricted();
+        } else {
+            panels = FirstrunPagerConfig.getDefault();
+        }
+
+        setAdapter(new ViewPagerAdapter(fm, panels));
         this.listener = listener;
 
         animateLoad();
     }
 
     public void hide() {
         setAdapter(null);
     }
--- a/mobile/android/base/firstrun/FirstrunPagerConfig.java
+++ b/mobile/android/base/firstrun/FirstrunPagerConfig.java
@@ -10,16 +10,22 @@ import java.util.List;
 
 public class FirstrunPagerConfig {
     public static List<FirstrunPanel> getDefault() {
         final List<FirstrunPanel> panels = new LinkedList<>();
         panels.add(new FirstrunPanel(WelcomePanel.class.getName(), WelcomePanel.TITLE_RES));
         return panels;
     }
 
+    public static List<FirstrunPanel> getRestricted() {
+        final List<FirstrunPanel> panels = new LinkedList<>();
+        panels.add(new FirstrunPanel(RestrictedWelcomePanel.class.getName(), RestrictedWelcomePanel.TITLE_RES));
+        return panels;
+    }
+
     public static class FirstrunPanel {
         private String classname;
         private int titleRes;
 
         public FirstrunPanel(String resource, int titleRes) {
             this.classname= resource;
             this.titleRes = titleRes;
         }
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/firstrun/RestrictedWelcomePanel.java
@@ -0,0 +1,61 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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/. */
+
+package org.mozilla.gecko.firstrun;
+
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract;
+import org.mozilla.gecko.home.HomePager;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.EnumSet;
+
+public class RestrictedWelcomePanel extends FirstrunPanel {
+    public static final int TITLE_RES = R.string.firstrun_panel_title_welcome;
+
+    private static final String LEARN_MORE_URL = "https://support.mozilla.org/kb/kids";
+
+    private HomePager.OnUrlOpenListener onUrlOpenListener;
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+
+        try {
+            onUrlOpenListener = (HomePager.OnUrlOpenListener) activity;
+        } catch (ClassCastException e) {
+            throw new ClassCastException(activity.toString() + " must implement HomePager.OnUrlOpenListener");
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
+        final ViewGroup root = (ViewGroup) inflater.inflate(R.layout.restricted_firstrun_welcome_fragment, container, false);
+
+        root.findViewById(R.id.welcome_browse).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                close();
+            }
+        });
+
+        root.findViewById(R.id.learn_more_link).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                onUrlOpenListener.onUrlOpen(LEARN_MORE_URL, EnumSet.of(HomePager.OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
+
+                close();
+            }
+        });
+
+        return root;
+    }
+}
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -5,16 +5,17 @@
 
 <!ENTITY  no_space_to_start_error "There is not enough space available for &brandShortName; to start.">
 <!ENTITY  error_loading_file "An error occurred when trying to load files required to run &brandShortName;">
 
 <!ENTITY  onboard_start_message3 "Browse with &brandShortName;">
 <!ENTITY  onboard_start_subtext3 "Make your mobile Web browsing experience truly your own.">
 <!ENTITY  onboard_start_button_account "Sign in to &brandShortName;">
 <!ENTITY  onboard_start_button_browser "Start Browsing">
+<!ENTITY  onboard_start_restricted "Stay safe and in control with this simplified version of Firefox.">
 
 <!-- Localization note: These are used as the titles of different pages on the home screen.
      They are automatically converted to all caps by the Android platform. -->
 <!ENTITY  bookmarks_title "Bookmarks">
 <!ENTITY  history_title "History">
 <!ENTITY  reading_list_title "Reading List">
 <!ENTITY  recent_tabs_title "Recent Tabs">
 
@@ -572,17 +573,17 @@ just addresses the organization to follo
 <!ENTITY blocked_mixed_content_message_top "&brandShortName; has blocked content that isn\'t secure.">
 <!ENTITY blocked_mixed_content_message_bottom "Most websites will still work properly even when this content is blocked.">
 
 <!-- Tracking content notifications in site identity popup -->
 <!ENTITY doorhanger_tracking_title "Tracking protection">
 <!ENTITY doorhanger_tracking_state_enabled "Enabled">
 <!ENTITY doorhanger_tracking_state_disabled "Disabled">
 <!ENTITY doorhanger_tracking_message_enabled1 "Attempts to track your online behavior have been blocked.">
-<!ENTITY doorhanger_tracking_message_disabled1 "This site includes content that tracks your browsing.">
+<!ENTITY doorhanger_tracking_message_disabled2 "This page includes elements that may track your browsing.">
 
 <!-- Common mixed and tracking content strings in site identity popup -->
 <!ENTITY learn_more "Learn More">
 <!ENTITY enable_protection "Enable protection">
 <!ENTITY disable_protection "Disable protection">
 <!ENTITY keep_blocking "Keep blocking">
 
 <!ENTITY private_data_success "Private data cleared">
@@ -687,31 +688,19 @@ just addresses the organization to follo
      code has already been displayed by the client trying to connect (such as
      desktop Firefox via WebIDE), so you just need to aim this device at the QR
      code. -->
 <!ENTITY devtools_auth_scan_header "Scanning for the QR code displayed on your other device">
 
 <!-- Restrictions -->
 <!-- Localization note: These are restrictions the device owner (e.g. parent) can enable for
      a restricted profile (e.g. child). Used inside the Android settings UI. -->
-<!ENTITY restriction_disallow_tools_menu_title "Disallow Tools menu">
-<!ENTITY restriction_disallow_tools_menu_description "Hide Tools menu from UI.">
-<!ENTITY restriction_disallow_import_settings_title "Disallow importing settings">
-<!ENTITY restriction_disallow_import_settings_description "Do not allow to import settings from other system browsers.">
-<!ENTITY restriction_disallow_addons_title "Disallow add-ons">
-<!ENTITY restriction_disallow_addons_description "Disallow installation of add-ons.">
-<!ENTITY restriction_disallow_devtools_title "Disallow developer tools">
-<!ENTITY restriction_disallow_devtools_description "Disallow usage of developer tools.">
-<!ENTITY restriction_disallow_customize_home_title "Disallow customizing home">
-<!ENTITY restriction_disallow_customize_home_description "Disallow customizing home panels.">
-<!ENTITY restriction_disallow_private_browsing_title "Disallow private browsing">
-<!ENTITY restriction_disallow_private_browsing_description "Disallow private browsing mode.">
-<!ENTITY restriction_disallow_location_services_title "Disallow location services">
-<!ENTITY restriction_disallow_location_services_description "Disallow sharing of location data to improve geolocation service.">
-<!ENTITY restriction_disallow_display_settings_title "Disallow display settings">
-<!ENTITY restriction_disallow_display_settings_description "Disallow changing of advanced display settings.">
-<!ENTITY restriction_disallow_clear_history_title "Disallow clearing history">
-<!ENTITY restriction_disallow_clear_history_description "Disallow clearing of browser history.">
-<!ENTITY restriction_disallow_master_password_title "Disallow master password">
-<!ENTITY restriction_disallow_master_password_description "Disallow setting a master password for logins.">
-<!ENTITY restriction_disallow_guest_browsing_title "Disallow guest browsing">
-<!ENTITY restriction_disallow_guest_browsing_description "Disallow guest browsing mode.">
+<!ENTITY restriction_disallow_import_settings_title2 "Disable \'Import from Android\'">
+<!ENTITY restriction_disallow_addons_title2 "Disable add-on installation">
+<!ENTITY restriction_disallow_devtools_title2 "Disable developer tools">
+<!ENTITY restriction_disallow_customize_home_title2 "Disable Home customization">
+<!ENTITY restriction_disallow_private_browsing_title2 "Disable Private Browsing">
+<!ENTITY restriction_disallow_location_services_title2 "Disable Location Services">
+<!ENTITY restriction_disallow_display_settings_title2 "Disable Display settings">
+<!ENTITY restriction_disallow_clear_history_title2 "Disable \'Clear browsing history\'">
+<!ENTITY restriction_disallow_master_password_title2 "Disable master password">
+<!ENTITY restriction_disallow_guest_browsing_title2 "Disable Guest Browsing">
 
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -224,16 +224,17 @@ gbjar.sources += [
     'favicons/RemoteFavicon.java',
     'FilePicker.java',
     'FilePickerResultHandler.java',
     'FindInPageBar.java',
     'firstrun/FirstrunPager.java',
     'firstrun/FirstrunPagerConfig.java',
     'firstrun/FirstrunPane.java',
     'firstrun/FirstrunPanel.java',
+    'firstrun/RestrictedWelcomePanel.java',
     'firstrun/WelcomePanel.java',
     'FormAssistPopup.java',
     'GeckoAccessibility.java',
     'GeckoActivity.java',
     'GeckoActivityStatus.java',
     'GeckoApp.java',
     'GeckoApplication.java',
     'GeckoAppShell.java',
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/button_background_action_blue_round.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/.  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+          android:drawable="@drawable/button_pressed_action_blue_round" />
+    <item android:state_enabled="true"
+          android:drawable="@drawable/button_enabled_action_blue_round" />
+</selector>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/button_enabled_action_blue_round.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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/. -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle" >
+  <solid android:color="@color/link_blue_pressed" />
+  <corners
+      android:radius="@dimen/button_corner_radius" />
+</shape>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/button_pressed_action_blue_round.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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/. -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle" >
+  <solid android:color="@color/link_blue" />
+  <corners
+      android:radius="@dimen/button_corner_radius" />
+</shape>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/restricted_firstrun_welcome_fragment.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:fillViewport="true"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/restricted_profile_background_gold"
+        android:minHeight="@dimen/firstrun_min_height"
+        android:orientation="vertical"
+        android:weightSum="50">
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="21"
+            android:padding="30dp">
+
+            <TextView
+                android:layout_width="320dp"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:background="@color/restricted_profile_background_green"
+                android:gravity="center"
+                android:paddingBottom="40dp"
+                android:paddingLeft="30dp"
+                android:paddingRight="30dp"
+                android:paddingTop="40dp"
+                android:text="@string/firstrun_welcome_restricted"
+                android:textColor="#ffffff"
+                android:textSize="22sp" />
+
+        </FrameLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="29"
+            android:background="@color/android:white"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:padding="40dp">
+
+            <Button
+                android:id="@+id/welcome_browse"
+                style="@style/Widget.Firstrun.Button"
+                android:layout_gravity="center"
+                android:layout_marginBottom="20dp"
+                android:background="@drawable/button_background_action_blue_round"
+                android:text="@string/firstrun_welcome_button_browser" />
+
+            <TextView
+                android:id="@+id/learn_more_link"
+                android:layout_width="@dimen/firstrun_content_width"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:padding="20dp"
+                android:text="@string/pref_learn_more"
+                android:textAppearance="@style/TextAppearance.FirstrunRegular.Link" />
+
+        </LinearLayout>
+    </LinearLayout>
+
+</ScrollView>
--- a/mobile/android/base/resources/values/colors.xml
+++ b/mobile/android/base/resources/values/colors.xml
@@ -25,16 +25,21 @@
   <color name="disabled_grey">#BFBFBF</color>
   <color name="toolbar_grey_pressed">#D7D7DC</color>
   <color name="toolbar_menu_dark_grey">#E1E1E6</color>
   <color name="toolbar_grey">#EBEBF0</color>
   <color name="about_page_header_grey">#F5F5F5</color>
 
   <color name="url_bar_shadow_private">#7878A5</color>
 
+  <!-- Restricted profiles palette -->
+
+  <color name="restricted_profile_background_gold">#ffffcb51</color>
+  <color name="restricted_profile_background_green">#1aaa86</color>
+
   <!-- Non-palette colors -->
 
   <!-- Synced w/ toolbar_grey -->
   <color name="background_normal_lwt">#DDEBEBF0</color>
 
   <color name="background_tabs">#FF363B40</color>
   <color name="highlight">#33000000</color>
   <color name="highlight_focused">#1A000000</color>
--- a/mobile/android/base/restrictions/Restriction.java
+++ b/mobile/android/base/restrictions/Restriction.java
@@ -3,129 +3,76 @@
  * 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/. */
 
 package org.mozilla.gecko.restrictions;
 
 import org.mozilla.gecko.R;
 
 import android.content.Context;
+import android.support.annotation.StringRes;
 
 /**
  * This is a list of things we can restrict you from doing. Some of these are reflected in Android UserManager constants.
  * Others are specific to us.
  * These constants should be in sync with the ones from toolkit/components/parentalcontrols/nsIParentalControlsService.idl
  */
 public enum Restriction {
-    DISALLOW_DOWNLOADS(
-            1, "no_download_files", 0, 0),
+    DISALLOW_DOWNLOADS(1, "no_download_files", 0),
 
-    DISALLOW_INSTALL_EXTENSION(
-            2, "no_install_extensions",
-            R.string.restriction_disallow_addons_title,
-            R.string.restriction_disallow_addons_description),
+    DISALLOW_INSTALL_EXTENSION(2, "no_install_extensions", R.string.restriction_disallow_addons_title),
 
     // UserManager.DISALLOW_INSTALL_APPS
-    DISALLOW_INSTALL_APPS(
-            3, "no_install_apps", 0, 0),
+    DISALLOW_INSTALL_APPS(3, "no_install_apps", 0),
 
-    DISALLOW_BROWSE_FILES(
-            4, "no_browse_files", 0, 0),
+    DISALLOW_BROWSE_FILES(4, "no_browse_files", 0),
 
-    DISALLOW_SHARE(
-            5, "no_share", 0, 0),
+    DISALLOW_SHARE(5, "no_share", 0),
 
-    DISALLOW_BOOKMARK(
-            6, "no_bookmark", 0, 0),
+    DISALLOW_BOOKMARK(6, "no_bookmark", 0),
 
-    DISALLOW_ADD_CONTACTS(
-            7, "no_add_contacts", 0, 0),
+    DISALLOW_ADD_CONTACTS(7, "no_add_contacts", 0),
 
-    DISALLOW_SET_IMAGE(
-            8, "no_set_image", 0, 0),
+    DISALLOW_SET_IMAGE(8, "no_set_image", 0),
 
     // UserManager.DISALLOW_MODIFY_ACCOUNTS
-    DISALLOW_MODIFY_ACCOUNTS(
-            9, "no_modify_accounts", 0, 0),
+    DISALLOW_MODIFY_ACCOUNTS(9, "no_modify_accounts", 0),
 
-    DISALLOW_REMOTE_DEBUGGING(
-            10, "no_remote_debugging", 0, 0),
-
-    DISALLOW_IMPORT_SETTINGS(
-            11, "no_import_settings",
-            R.string.restriction_disallow_import_settings_title,
-            R.string.restriction_disallow_import_settings_description),
+    DISALLOW_REMOTE_DEBUGGING(10, "no_remote_debugging", 0),
 
-    DISALLOW_DEVELOPER_TOOLS(
-            12, "no_developer_tools",
-            R.string.restriction_disallow_devtools_title,
-            R.string.restriction_disallow_devtools_description
-    ),
+    DISALLOW_IMPORT_SETTINGS(11, "no_import_settings", R.string.restriction_disallow_import_settings_title),
 
-    DISALLOW_CUSTOMIZE_HOME(
-            13, "no_customize_home",
-            R.string.restriction_disallow_customize_home_title,
-            R.string.restriction_disallow_customize_home_description
-    ),
+    DISALLOW_DEVELOPER_TOOLS(12, "no_developer_tools", R.string.restriction_disallow_devtools_title),
 
-    DISALLOW_PRIVATE_BROWSING(
-            14, "no_private_browsing",
-            R.string.restriction_disallow_private_browsing_title,
-            R.string.restriction_disallow_private_browsing_description
-    ),
+    DISALLOW_CUSTOMIZE_HOME(13, "no_customize_home", R.string.restriction_disallow_customize_home_title),
 
-    DISALLOW_LOCATION_SERVICE(
-            15, "no_location_service",
-            R.string.restriction_disallow_location_services_title,
-            R.string.restriction_disallow_location_services_description
-    ),
+    DISALLOW_PRIVATE_BROWSING(14, "no_private_browsing", R.string.restriction_disallow_private_browsing_title),
 
-    DISALLOW_DISPLAY_SETTINGS(
-            16, "no_display_settings",
-            R.string.restriction_disallow_display_settings_title,
-            R.string.restriction_disallow_display_settings_description
-    ),
+    DISALLOW_LOCATION_SERVICE(15, "no_location_service", R.string.restriction_disallow_location_services_title),
+
+    DISALLOW_DISPLAY_SETTINGS(16, "no_display_settings", R.string.restriction_disallow_display_settings_title),
 
-    DISALLOW_CLEAR_HISTORY(
-            17, "no_clear_history",
-            R.string.restriction_disallow_clear_history_title,
-            R.string.restriction_disallow_clear_history_description
-    ),
+    DISALLOW_CLEAR_HISTORY(17, "no_clear_history", R.string.restriction_disallow_clear_history_title),
 
-    DISALLOW_MASTER_PASSWORD(
-            18, "no_master_password",
-            R.string.restriction_disallow_master_password_title,
-            R.string.restriction_disallow_master_password_description
-    ),
+    DISALLOW_MASTER_PASSWORD(18, "no_master_password", R.string.restriction_disallow_master_password_title),
 
-    DISALLOW_GUEST_BROWSING(
-            19, "no_guest_browsing",
-            R.string.restriction_disallow_guest_browsing_title,
-            R.string.restriction_disallow_guest_browsing_description
-    );
+    DISALLOW_GUEST_BROWSING(19, "no_guest_browsing",  R.string.restriction_disallow_guest_browsing_title);
 
 
     public final int id;
     public final String name;
-    public final int titleResource;
-    public final int descriptionResource;
 
-    Restriction(final int id, final String name, int titleResource, int descriptionResource) {
+    @StringRes
+    public final int title;
+
+    Restriction(final int id, final String name, @StringRes int title) {
         this.id = id;
         this.name = name;
-        this.titleResource = titleResource;
-        this.descriptionResource = descriptionResource;
+        this.title = title;
     }
 
     public String getTitle(Context context) {
-        if (titleResource == 0) {
+        if (title == 0) {
             return toString();
         }
-        return context.getResources().getString(titleResource);
-    }
-
-    public String getDescription(Context context) {
-        if (descriptionResource == 0) {
-            return name;
-        }
-        return context.getResources().getString(descriptionResource);
+        return context.getResources().getString(title);
     }
 }
--- a/mobile/android/base/restrictions/RestrictionProvider.java
+++ b/mobile/android/base/restrictions/RestrictionProvider.java
@@ -60,13 +60,12 @@ public class RestrictionProvider extends
 
         return entries;
     }
 
     private RestrictionEntry createRestrictionEntryWithDefaultValue(Context context, Restriction restriction, boolean defaultValue) {
         RestrictionEntry entry = new RestrictionEntry(restriction.name, defaultValue);
 
         entry.setTitle(restriction.getTitle(context));
-        entry.setDescription(restriction.getDescription(context));
 
         return entry;
     }
 }
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -38,16 +38,17 @@
   <string name="no_space_to_start_error">&no_space_to_start_error;</string>
   <string name="error_loading_file">&error_loading_file;</string>
 
   <string name="firstrun_welcome_message">&onboard_start_message3;</string>
   <string name="firstrun_welcome_subtext">&onboard_start_subtext3;</string>
   <string name="firstrun_welcome_button_account">&onboard_start_button_account;</string>
   <string name="firstrun_welcome_button_browser">&onboard_start_button_browser;</string>
   <string name="firstrun_empty_contentDescription"></string>
+  <string name="firstrun_welcome_restricted">&onboard_start_restricted;</string>
 
   <string name="bookmarks_title">&bookmarks_title;</string>
   <string name="history_title">&history_title;</string>
   <string name="reading_list_title">&reading_list_title;</string>
   <string name="recent_tabs_title">&recent_tabs_title;</string>
 
   <string name="switch_to_tab">&switch_to_tab;</string>
 
@@ -472,17 +473,17 @@
   <string name="mixed_content_blocked_some">&mixed_content_blocked_some;</string>
   <string name="mixed_content_display_loaded">&mixed_content_display_loaded;</string>
   <string name="mixed_content_protection_disabled">&mixed_content_protection_disabled;</string>
 
   <string name="doorhanger_tracking_title">&doorhanger_tracking_title;</string>
   <string name="doorhanger_tracking_state_enabled">&doorhanger_tracking_state_enabled;</string>
   <string name="doorhanger_tracking_state_disabled">&doorhanger_tracking_state_disabled;</string>
   <string name="doorhanger_tracking_message_enabled">&doorhanger_tracking_message_enabled1;</string>
-  <string name="doorhanger_tracking_message_disabled">&doorhanger_tracking_message_disabled1;</string>
+  <string name="doorhanger_tracking_message_disabled">&doorhanger_tracking_message_disabled2;</string>
 
   <string name="learn_more">&learn_more;</string>
   <string name="enable_protection">&enable_protection;</string>
   <string name="disable_protection">&disable_protection;</string>
   <string name="keep_blocking">&keep_blocking;</string>
 
   <!-- Clear private data -->
   <string name="private_data_success">&private_data_success;</string>
@@ -541,38 +542,26 @@
 
   <string name="actionbar_menu">&actionbar_menu;</string>
   <string name="actionbar_done">&actionbar_done;</string>
 
   <!-- Voice search from the Awesome Bar -->
   <string name="voicesearch_prompt">&voicesearch_prompt;</string>
 
   <!-- Restrictions -->
-  <string name="restriction_disallow_tools_menu_title">&restriction_disallow_tools_menu_title;</string>
-  <string name="restriction_disallow_tools_menu_description">&restriction_disallow_tools_menu_description;</string>
-  <string name="restriction_disallow_import_settings_title">&restriction_disallow_import_settings_title;</string>
-  <string name="restriction_disallow_import_settings_description">&restriction_disallow_import_settings_description;</string>
-  <string name="restriction_disallow_addons_title">&restriction_disallow_addons_title;</string>
-  <string name="restriction_disallow_addons_description">&restriction_disallow_addons_description;</string>
-  <string name="restriction_disallow_devtools_title">&restriction_disallow_devtools_title;</string>
-  <string name="restriction_disallow_devtools_description">&restriction_disallow_devtools_description;</string>
-  <string name="restriction_disallow_customize_home_title">&restriction_disallow_customize_home_title;</string>
-  <string name="restriction_disallow_customize_home_description">&restriction_disallow_customize_home_description;</string>
-  <string name="restriction_disallow_private_browsing_title">&restriction_disallow_private_browsing_title;</string>
-  <string name="restriction_disallow_private_browsing_description">&restriction_disallow_private_browsing_description;</string>
-  <string name="restriction_disallow_location_services_title">&restriction_disallow_location_services_title;</string>
-  <string name="restriction_disallow_location_services_description">&restriction_disallow_location_services_description;</string>
-  <string name="restriction_disallow_display_settings_title">&restriction_disallow_display_settings_title;</string>
-  <string name="restriction_disallow_display_settings_description">&restriction_disallow_display_settings_description;</string>
-  <string name="restriction_disallow_clear_history_title">&restriction_disallow_clear_history_title;</string>
-  <string name="restriction_disallow_clear_history_description">&restriction_disallow_clear_history_description;</string>
-  <string name="restriction_disallow_master_password_title">&restriction_disallow_master_password_title;</string>
-  <string name="restriction_disallow_master_password_description">&restriction_disallow_master_password_description;</string>
-  <string name="restriction_disallow_guest_browsing_title">&restriction_disallow_guest_browsing_title;</string>
-  <string name="restriction_disallow_guest_browsing_description">&restriction_disallow_guest_browsing_description;</string>
+  <string name="restriction_disallow_import_settings_title">&restriction_disallow_import_settings_title2;</string>
+  <string name="restriction_disallow_addons_title">&restriction_disallow_addons_title2;</string>
+  <string name="restriction_disallow_devtools_title">&restriction_disallow_devtools_title2;</string>
+  <string name="restriction_disallow_customize_home_title">&restriction_disallow_customize_home_title2;</string>
+  <string name="restriction_disallow_private_browsing_title">&restriction_disallow_private_browsing_title2;</string>
+  <string name="restriction_disallow_location_services_title">&restriction_disallow_location_services_title2;</string>
+  <string name="restriction_disallow_display_settings_title">&restriction_disallow_display_settings_title2;</string>
+  <string name="restriction_disallow_clear_history_title">&restriction_disallow_clear_history_title2;</string>
+  <string name="restriction_disallow_master_password_title">&restriction_disallow_master_password_title2;</string>
+  <string name="restriction_disallow_guest_browsing_title">&restriction_disallow_guest_browsing_title2;</string>
 
   <!-- Miscellaneous -->
   <string name="ellipsis">&ellipsis;</string>
 
   <string name="colon">&colon;</string>
 
   <string name="percent">&percent;</string>
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4776,21 +4776,22 @@ pref("dom.inter-app-communication-api.en
 // Disable mapped array buffer by default.
 pref("dom.mapped_arraybuffer.enabled", false);
 
 // The tables used for Safebrowsing phishing and malware checks.
 pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,test-malware-simple,test-unwanted-simple");
 pref("urlclassifier.phishTable", "goog-phish-shavar,test-phish-simple");
 pref("urlclassifier.downloadBlockTable", "");
 pref("urlclassifier.downloadAllowTable", "");
-pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple,goog-downloadwhite-digest256,mozpub-track-digest256");
+pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple,goog-downloadwhite-digest256,mozpub-track-digest256,mozpub-trackwhite-digest256");
 
 // The table and update/gethash URLs for Safebrowsing phishing and malware
 // checks.
 pref("urlclassifier.trackingTable", "test-track-simple,mozpub-track-digest256");
+pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozpub-trackwhite-digest256");
 pref("browser.trackingprotection.updateURL", "https://tracking.services.mozilla.com/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
 pref("browser.trackingprotection.gethashURL", "https://tracking.services.mozilla.com/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
 
 // Turn off Spatial navigation by default.
 pref("snav.enabled", false);
 
 // Original caret implementation on collapsed selection.
 pref("touchcaret.enabled", false);
--- a/netwerk/base/nsChannelClassifier.cpp
+++ b/netwerk/base/nsChannelClassifier.cpp
@@ -507,22 +507,93 @@ nsChannelClassifier::SetBlockedTrackingC
                                   doc,
                                   nsContentUtils::eNECKO_PROPERTIES,
                                   "TrackingUriBlocked",
                                   params, ArrayLength(params));
 
   return NS_OK;
 }
 
+nsresult
+nsChannelClassifier::IsTrackerWhitelisted()
+{
+  nsresult rv;
+  nsCOMPtr<nsIURIClassifier> uriClassifier =
+    do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString tables;
+  Preferences::GetCString("urlclassifier.trackingWhitelistTable", &tables);
+
+  if (tables.IsEmpty()) {
+    LOG(("nsChannelClassifier[%p]:IsTrackerWhitelisted whitelist disabled",
+         this));
+    return NS_ERROR_TRACKING_URI;
+  }
+
+  nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(mChannel, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURI> topWinURI;
+  rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!topWinURI) {
+    LOG(("nsChannelClassifier[%p]: No window URI", this));
+    return NS_ERROR_TRACKING_URI;
+  }
+
+  nsCOMPtr<nsIScriptSecurityManager> securityManager =
+    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIPrincipal> chanPrincipal;
+  rv = securityManager->GetChannelURIPrincipal(mChannel,
+                                               getter_AddRefs(chanPrincipal));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Craft a whitelist URL like "toplevel.page/?resource=third.party.domain"
+  nsAutoCString pageHostname, resourceDomain;
+  rv = topWinURI->GetHost(pageHostname);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = chanPrincipal->GetBaseDomain(resourceDomain);
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsAutoCString whitelistEntry = NS_LITERAL_CSTRING("http://") +
+    pageHostname + NS_LITERAL_CSTRING("/?resource=") + resourceDomain;
+  LOG(("nsChannelClassifier[%p]: Looking for %s in the whitelist",
+       this, whitelistEntry.get()));
+
+  nsCOMPtr<nsIURI> whitelistURI;
+  rv = NS_NewURI(getter_AddRefs(whitelistURI), whitelistEntry);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check whether or not the tracker is in the entity whitelist
+  nsAutoCString results;
+  rv = uriClassifier->ClassifyLocalWithTables(whitelistURI, tables, results);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!results.IsEmpty()) {
+    return NS_OK; // found it on the whitelist, must not be blocked
+  }
+
+  LOG(("nsChannelClassifier[%p]: %s is not in the whitelist",
+       this, whitelistEntry.get()));
+  return NS_ERROR_TRACKING_URI;
+}
+
 NS_IMETHODIMP
 nsChannelClassifier::OnClassifyComplete(nsresult aErrorCode)
 {
     // Should only be called in the parent process.
     MOZ_ASSERT(XRE_IsParentProcess());
 
+    if (aErrorCode == NS_ERROR_TRACKING_URI &&
+        NS_SUCCEEDED(IsTrackerWhitelisted())) {
+      LOG(("nsChannelClassifier[%p]:OnClassifyComplete tracker found "
+           "in whitelist so we won't block it)", this));
+      aErrorCode = NS_OK;
+    }
+
     LOG(("nsChannelClassifier[%p]:OnClassifyComplete %d", this, aErrorCode));
     if (mSuspendedChannel) {
         MarkEntryClassified(aErrorCode);
 
         if (NS_FAILED(aErrorCode)) {
 #ifdef DEBUG
             nsCOMPtr<nsIURI> uri;
             mChannel->GetURI(getter_AddRefs(uri));
--- a/netwerk/base/nsChannelClassifier.h
+++ b/netwerk/base/nsChannelClassifier.h
@@ -36,16 +36,18 @@ private:
     ~nsChannelClassifier() {}
     // Caches good classifications for the channel principal.
     void MarkEntryClassified(nsresult status);
     bool HasBeenClassified(nsIChannel *aChannel);
     // Helper function so that we ensure we call ContinueBeginConnect once
     // Start is called. Returns NS_OK if and only if we will get a callback
     // from the classifier service.
     nsresult StartInternal();
+    // Helper function to check a tracking URI against the whitelist
+    nsresult IsTrackerWhitelisted();
 
 public:
     // If we are blocking tracking content, update the corresponding flag in
     // the respective docshell and call nsISecurityEventSink::onSecurityChange.
     static nsresult SetBlockedTrackingContent(nsIChannel *channel);
     static nsresult NotifyTrackingProtectionDisabled(nsIChannel *aChannel);
 };
 
--- a/netwerk/base/nsIURIClassifier.idl
+++ b/netwerk/base/nsIURIClassifier.idl
@@ -1,16 +1,17 @@
 /* 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 "nsISupports.idl"
 
+interface nsIChannel;
 interface nsIPrincipal;
-interface nsIChannel;
+interface nsIURI;
 
 /**
  * Callback function for nsIURIClassifier lookups.
  */
 [scriptable, function, uuid(8face46e-0c96-470f-af40-0037dcd797bd)]
 interface nsIURIClassifierCallback : nsISupports
 {
   /**
@@ -25,17 +26,17 @@ interface nsIURIClassifierCallback : nsI
    */
   void onClassifyComplete(in nsresult aErrorCode);
 };
 
 /**
  * The URI classifier service checks a URI against lists of phishing
  * and malware sites.
  */
-[scriptable, uuid(9168a330-7fba-40e8-9c47-4ce8f15a57fd)]
+[scriptable, uuid(596620cc-76e3-4133-9d90-360e59a794cf)]
 interface nsIURIClassifier : nsISupports
 {
   /**
    * Classify a Principal using its URI.
    *
    * @param aPrincipal
    *        The principal that should be checked by the URI classifier.
    * @param aTrackingProtectionEnabled
@@ -51,15 +52,14 @@ interface nsIURIClassifier : nsISupports
    *         <code>true</code> if classification will be performed.  The
    *         callback will be called.
    */
   boolean classify(in nsIPrincipal aPrincipal,
                    in boolean aTrackingProtectionEnabled,
                    in nsIURIClassifierCallback aCallback);
 
   /**
-   * Synchronously classify a Principal locally using its URI with a
-   * comma-separated string containing the given tables. This does not make
-   * network requests. The result is a comma-separated string of tables that match.
+   * Synchronously classify a URI with a comma-separated string
+   * containing the given tables. This does not make network requests.
+   * The result is a comma-separated string of tables that match.
    */
-  ACString classifyLocalWithTables(in nsIPrincipal aPrincipal,
-                                   in ACString aTables);
+  ACString classifyLocalWithTables(in nsIURI aURI, in ACString aTables);
 };
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -5155,33 +5155,34 @@ nsHttpChannel::BeginConnect()
     // nsIHttpChannel.redirectTo API request
     if (mAPIRedirectToURI) {
         return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
     }
     // Check to see if this principal exists on local blocklists.
     nsRefPtr<nsChannelClassifier> channelClassifier = new nsChannelClassifier();
     if (mLoadFlags & LOAD_CLASSIFY_URI) {
         nsCOMPtr<nsIURIClassifier> classifier = do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID);
-        if (classifier) {
-            bool tpEnabled = false;
-            channelClassifier->ShouldEnableTrackingProtection(this, &tpEnabled);
+        bool tpEnabled = false;
+        channelClassifier->ShouldEnableTrackingProtection(this, &tpEnabled);
+        if (classifier && tpEnabled) {
             // We skip speculative connections by setting mLocalBlocklist only
             // when tracking protection is enabled. Though we could do this for
             // both phishing and malware, it is not necessary for correctness,
             // since no network events will be received while the
             // nsChannelClassifier is in progress. See bug 1122691.
-            if (tpEnabled) {
-                nsCOMPtr<nsIPrincipal> principal = GetURIPrincipal();
+            nsCOMPtr<nsIURI> uri;
+            rv = GetURI(getter_AddRefs(uri));
+            if (NS_SUCCEEDED(rv) && uri) {
                 nsAutoCString tables;
                 Preferences::GetCString("urlclassifier.trackingTable", &tables);
                 nsAutoCString results;
-                rv = classifier->ClassifyLocalWithTables(principal, tables, results);
+                rv = classifier->ClassifyLocalWithTables(uri, tables, results);
                 if (NS_SUCCEEDED(rv) && !results.IsEmpty()) {
                     LOG(("nsHttpChannel::ClassifyLocalWithTables found "
-                         "principal on local tracking blocklist [this=%p]",
+                         "uri on local tracking blocklist [this=%p]",
                          this));
                     mLocalBlocklist = true;
                 } else {
                     LOG(("nsHttpChannel::ClassifyLocalWithTables no result "
                          "found [this=%p]", this));
                 }
             }
         }
--- a/security/manager/ssl/tests/unit/moz.build
+++ b/security/manager/ssl/tests/unit/moz.build
@@ -10,14 +10,15 @@ TEST_DIRS += [
     'test_cert_embedded_null',
     'test_cert_keyUsage',
     'test_cert_trust',
     'test_cert_version',
     'test_ev_certs',
     'test_intermediate_basic_usage_constraints',
     'test_keysize_ev',
     'test_pinning_dynamic',
+    'test_ocsp_fetch_method',
     'test_ocsp_url',
     'test_validity',
 ]
 
 if not CONFIG['MOZ_NO_SMART_CARDS']:
     DIRS += ['pkcs11testmodule']
--- a/security/manager/ssl/tests/unit/test_ocsp_fetch_method.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_fetch_method.js
@@ -18,24 +18,24 @@ const SERVER_PORT = 8888;
 function start_ocsp_responder(expectedCertNames, expectedPaths,
                               expectedMethods) {
   return startOCSPResponder(SERVER_PORT, "www.example.com", [],
                             "test_ocsp_fetch_method", expectedCertNames,
                             expectedPaths, expectedMethods);
 }
 
 function check_cert_err(cert_name, expected_error) {
-  let cert = constructCertFromFile("test_ocsp_fetch_method/" + cert_name + ".der");
+  let cert = constructCertFromFile("test_ocsp_fetch_method/" + cert_name + ".pem");
   return checkCertErrorGeneric(certdb, cert, expected_error,
                                certificateUsageSSLServer);
 }
 
 function run_test() {
-  addCertFromFile(certdb, "test_ocsp_fetch_method/ca.der", 'CTu,CTu,CTu');
-  addCertFromFile(certdb, "test_ocsp_fetch_method/int.der", ',,');
+  addCertFromFile(certdb, "test_ocsp_fetch_method/ca.pem", 'CTu,CTu,CTu');
+  addCertFromFile(certdb, "test_ocsp_fetch_method/int.pem", ',,');
 
   // Enabled so that we can force ocsp failure responses.
   Services.prefs.setBoolPref("security.OCSP.require", true);
 
   Services.prefs.setCharPref("network.dns.localDomains",
                              "www.example.com");
   Services.prefs.setIntPref("security.OCSP.enabled", 1);
 
@@ -50,21 +50,10 @@ function run_test() {
   add_test(function() {
     clearOCSPCache();
     Services.prefs.setBoolPref("security.OCSP.GET.enabled", true);
     let ocspResponder = start_ocsp_responder(["a"], [], ["GET"]);
     check_cert_err("a", PRErrorCodeSuccess);
     ocspResponder.stop(run_next_test);
   });
 
-  // GET does fallback on bad entry
-  add_test(function() {
-    clearOCSPCache();
-    Services.prefs.setBoolPref("security.OCSP.GET.enabled", true);
-    // Bug 1016681 mozilla::pkix does not support fallback yet.
-    // let ocspResponder = start_ocsp_responder(["b", "a"], [], ["GET", "POST"]);
-    // check_cert_err("a", PRErrorCodeSuccess);
-    // ocspResponder.stop(run_next_test);
-    run_next_test();
-  });
-
   run_next_test();
 }
deleted file mode 100644
index 48b71256a6befd2675b22410362d6bc5d6160464..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_ocsp_fetch_method/a.pem.certspec
@@ -0,0 +1,3 @@
+issuer:int
+subject:a
+extension:authorityInformationAccess:http://www.example.com:8888/
deleted file mode 100644
index b7a751f540da98e11903956f1413ed14611a5701..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 20e8db54b0893a46b85356ab5c59bdd83cdd4e9f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_ocsp_fetch_method/ca.pem.certspec
@@ -0,0 +1,4 @@
+issuer:ca
+subject:ca
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
deleted file mode 100644
index e54db78087a5091c79ff2756a5bbabbbb2577001..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
--- a/security/manager/ssl/tests/unit/test_ocsp_fetch_method/generate.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/python
-
-import tempfile, os, sys
-
-libpath = os.path.abspath('../psm_common_py')
-sys.path.append(libpath)
-import CertUtils
-
-srcdir = os.getcwd()
-db = tempfile.mkdtemp()
-
-def generate_ca_cert(db_dir, dest_dir, noise_file, name):
-    return CertUtils.generate_ca_cert(db_dir, dest_dir, noise_file, name,
-                                      3, True)
-
-def generate_child_cert(db_dir, dest_dir, noise_file, name, ca_nick, is_ee,
-                        ocsp_url):
-    return CertUtils.generate_child_cert(db_dir, dest_dir, noise_file, name,
-                                         ca_nick, 3, True, is_ee, ocsp_url)
-
-def generate_certs():
-    [noise_file, pwd_file] = CertUtils.init_nss_db(srcdir)
-    generate_ca_cert(srcdir, srcdir, noise_file, 'ca')
-    generate_child_cert(srcdir, srcdir, noise_file, 'int', 'ca', False, '')
-    ocsp_url = "http://www.example.com:8888/"
-    generate_child_cert(srcdir, srcdir, noise_file, "a", 'int', True, ocsp_url)
-    generate_child_cert(srcdir, srcdir, noise_file, "b", 'int', True, ocsp_url)
-
-generate_certs()
deleted file mode 100644
index 661e814efaa9f67bc37bcef536b7f358ee34a666..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_ocsp_fetch_method/int.pem.certspec
@@ -0,0 +1,4 @@
+issuer:ca
+subject:int
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
deleted file mode 100644
index ada3335ecf24660ab3a4e0979a133ed8df901389..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_ocsp_fetch_method/moz.build
@@ -0,0 +1,31 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+test_certificates = (
+    'a.pem',
+    'ca.pem',
+    'int.pem',
+)
+
+for test_certificate in test_certificates:
+    input_file = test_certificate + '.certspec'
+    GENERATED_FILES += [test_certificate]
+    props = GENERATED_FILES[test_certificate]
+    props.script = '../pycert.py'
+    props.inputs = [input_file]
+    TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.test_ocsp_fetch_method += ['!%s' % test_certificate]
+
+test_keys = (
+    'int.key',
+)
+
+for test_key in test_keys:
+    input_file = test_key + '.keyspec'
+    GENERATED_FILES += [test_key]
+    props = GENERATED_FILES[test_key]
+    props.script = '../pykey.py'
+    props.inputs = [input_file]
+    TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.test_ocsp_fetch_method += ['!%s' % test_key]
deleted file mode 100644
--- a/security/manager/ssl/tests/unit/test_ocsp_fetch_method/pkcs11.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-library=
-name=NSS Internal PKCS #11 Module
-parameters=configdir='sql:/home/cviecco/hg/mozilla-central-unified/security/manager/ssl/tests/unit/test_ocsp_fetch_method' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' 
-NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30})
-
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_19_3_RC0
+NSS_3_19_3_RTM
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/services/healthreport/healthreport-prefs.js
+++ b/services/healthreport/healthreport-prefs.js
@@ -30,9 +30,9 @@ pref("datareporting.healthreport.service
 #elif MOZ_UPDATE_CHANNEL == default
     "healthreport-js-provider-default"
 #else
     "healthreport-js-provider-default,healthreport-js-provider-@MOZ_UPDATE_CHANNEL@"
 #endif
     );
 
 pref("datareporting.healthreport.about.reportUrl", "https://fhr.cdn.mozilla.net/%LOCALE%/");
-pref("datareporting.healthreport.about.reportUrlUnified", "https://fhr.cdn.mozilla.net/%LOCALE%/");
+pref("datareporting.healthreport.about.reportUrlUnified", "https://fhr.cdn.mozilla.net/%LOCALE%/v4/");
--- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini
@@ -142,17 +142,16 @@ browser = false
 b2g = false
 [test_set_window_size.py]
 b2g = false
 skip-if = os == "linux" # Bug 1085717
 [test_with_using_context.py]
 
 [test_modal_dialogs.py]
 b2g = false
-skip-if = true # Disabled so bug 959567 can land
 [test_key_actions.py]
 [test_mouse_action.py]
 b2g = false
 [test_teardown_context_preserved.py]
 b2g = false
 [test_file_upload.py]
 b2g = false
 skip-if = os == "win" # http://bugs.python.org/issue14574
--- a/testing/marionette/driver/marionette_driver/geckoinstance.py
+++ b/testing/marionette/driver/marionette_driver/geckoinstance.py
@@ -22,16 +22,17 @@ class GeckoInstance(object):
                       "browser.displayedE10SPrompt.2": 5,
                       "browser.displayedE10SPrompt.3": 5,
                       "browser.displayedE10SPrompt.4": 5,
                       "browser.sessionstore.resume_from_crash": False,
                       "browser.shell.checkDefaultBrowser": False,
                       "browser.startup.page": 0,
                       "browser.tabs.remote.autostart.1": False,
                       "browser.tabs.remote.autostart.2": False,
+                      "browser.urlbar.userMadeSearchSuggestionsChoice": True,
                       "browser.warnOnQuit": False,
                       "dom.ipc.reportProcessHangs": False,
                       "focusmanager.testmode": True,
                       "startup.homepage_welcome_url": "about:blank"}
 
     def __init__(self, host, port, bin, profile=None, addons=None,
                  app_args=None, symbols_path=None, gecko_log=None, prefs=None):
         self.marionette_host = host
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -1123,24 +1123,17 @@ class AndroidArguments(ArgumentContainer
 container_map = {
     'generic': [MochitestArguments],
     'b2g': [MochitestArguments, B2GArguments],
     'android': [MochitestArguments, AndroidArguments],
 }
 
 
 class MochitestArgumentParser(ArgumentParser):
-    """
-    Usage instructions for Mochitest.
-
-    All arguments are optional.
-    If --chrome is specified, chrome tests will be run instead of web content tests.
-    If --browser-chrome is specified, browser-chrome tests will be run instead of web content tests.
-    See <http://mochikit.com/doc/html/MochiKit/Logging.html> for details on the logging levels.
-    """
+    """%(prog)s [options] [test paths]"""
 
     _containers = None
     context = {}
 
     def __init__(self, app=None, **kwargs):
         ArgumentParser.__init__(self, usage=self.__doc__, conflict_handler='resolve', **kwargs)
 
         self.oldcwd = os.getcwd()
--- a/testing/taskcluster/mach_commands.py
+++ b/testing/taskcluster/mach_commands.py
@@ -107,16 +107,36 @@ def decorate_task_treeherder_routes(task
     if 'routes' not in task:
         task['routes'] = []
 
     treeheder_env = task['extra'].get('treeherderEnv', ['staging'])
 
     for env in treeheder_env:
         task['routes'].append('{}.{}'.format(TREEHERDER_ROUTES[env], suffix))
 
+def decorate_task_json_routes(build, task, json_routes, parameters):
+    """
+    Decorate the given task with routes.json routes.
+
+    :param dict task: task definition.
+    :param json_routes: the list of routes to use from routes.json
+    :param parameters: dictionary of parameters to use in route templates
+    """
+    fmt = parameters.copy()
+    fmt.update({
+        'build_product': task['extra']['build_product'],
+        'build_name': build['build_name'],
+        'build_type': build['build_type'],
+    })
+    routes = task.get('routes', [])
+    for route in json_routes:
+        routes.append(route.format(**fmt))
+
+    task['routes'] = routes
+
 def configure_dependent_task(task_path, parameters, taskid, templates, build_treeherder_config):
     """
     Configure a build dependent task. This is shared between post-build and test tasks.
 
     :param task_path: location to the task yaml
     :param parameters: parameters to load the template
     :param taskid: taskid of the dependent task
     :param templates: reference to the template builder
@@ -262,16 +282,17 @@ class Graph(object):
 
         jobs = templates.load(job_path, {})
 
         job_graph = parse_commit(message, jobs)
         mozharness = load_mozharness_info()
 
         # Template parameters used when expanding the graph
         parameters = dict(gaia_info().items() + {
+            'index': 'index.garbage.staging.mshal-testing', #TODO
             'project': project,
             'pushlog_id': params.get('pushlog_id', 0),
             'docker_image': docker_image,
             'base_repository': params['base_repository'] or \
                 params['head_repository'],
             'head_repository': params['head_repository'],
             'head_ref': params['head_ref'] or params['head_rev'],
             'head_rev': params['head_rev'],
@@ -284,16 +305,22 @@ class Graph(object):
             'revision_hash': params['revision_hash']
         }.items())
 
         treeherder_route = '{}.{}'.format(
             params['project'],
             params.get('revision_hash', '')
         )
 
+        routes_file = os.path.join(ROOT, 'routes.json')
+        with open(routes_file) as f:
+            contents = json.load(f)
+            json_routes = contents['routes']
+            # TODO: Nightly and/or l10n routes
+
         # Task graph we are generating for taskcluster...
         graph = {
             'tasks': [],
             'scopes': []
         }
 
         if params['revision_hash']:
             for env in TREEHERDER_ROUTES:
@@ -307,22 +334,23 @@ class Graph(object):
             'name': 'task graph local'
         }
 
         for build in job_graph:
             build_parameters = dict(parameters)
             build_parameters['build_slugid'] = slugid()
             build_task = templates.load(build['task'], build_parameters)
 
-            if 'routes' not in build_task['task']:
-                build_task['task']['routes'] = []
-
             if params['revision_hash']:
                 decorate_task_treeherder_routes(build_task['task'],
                                                 treeherder_route)
+                decorate_task_json_routes(build,
+                                          build_task['task'],
+                                          json_routes,
+                                          build_parameters)
 
             # Ensure each build graph is valid after construction.
             taskcluster_graph.build_task.validate(build_task)
             graph['tasks'].append(build_task)
 
             test_packages_url, tests_url = None, None
 
             if 'test_packages' in build_task['task']['extra']['locations']:
--- a/testing/taskcluster/taskcluster_graph/commit_parser.py
+++ b/testing/taskcluster/taskcluster_graph/commit_parser.py
@@ -270,12 +270,14 @@ def parse_commit(message, jobs):
 
             # Node for this particular build type
             result.append({
                 'task': build_task,
                 'post-build': post_build_jobs,
                 'dependents': extract_tests_from_platform(
                     jobs['tests'], platform_builds, build_task, tests
                 ),
-                'additional-parameters': additional_parameters
+                'additional-parameters': additional_parameters,
+                'build_name': platform,
+                'build_type': build_type,
             })
 
     return result
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -183,16 +183,17 @@ var LoginManagerContent = {
     }
 
     if (msg.name == "RemoteLogins:fillForm") {
       this.fillForm({
         topDocument: window.document,
         loginFormOrigin: msg.data.loginFormOrigin,
         loginsFound: jsLoginsToXPCOM(msg.data.logins),
         recipes: msg.data.recipes,
+        inputElement: msg.objects.inputElement,
       });
       return;
     }
 
     let request = this._takeRequest(msg);
     switch (msg.name) {
       case "RemoteLogins:loginsFound": {
         let loginsFound = jsLoginsToXPCOM(msg.data.logins);
@@ -440,35 +441,49 @@ var LoginManagerContent = {
    *            This must match the origin of the form used for the fill.
    *          loginsFound:
    *            Array containing the login to fill. While other messages may
    *            have more logins, for this use case this is expected to have
    *            exactly one element. The origin of the login may be different
    *            from the origin of the form used for the fill.
    *          recipes:
    *            Fill recipes transmitted together with the original message.
+   *          inputElement:
+   *            Optional input password element from the form we want to fill.
    *        }
    */
-  fillForm({ topDocument, loginFormOrigin, loginsFound, recipes }) {
+  fillForm({ topDocument, loginFormOrigin, loginsFound, recipes, inputElement }) {
     let topState = this.stateForDocument(topDocument);
     if (!topState.loginFormForFill) {
       log("fillForm: There is no login form anymore. The form may have been",
           "removed or the document may have changed.");
       return;
     }
-    if (LoginUtils._getPasswordOrigin(topDocument.documentURI) !=
-        loginFormOrigin) {
-      log("fillForm: The requested origin doesn't match the one form the",
-          "document. This may mean we navigated to a document from a different",
-          "site before we had a chance to indicate this change in the user",
-          "interface.");
-      return;
+    if (LoginUtils._getPasswordOrigin(topDocument.documentURI) != loginFormOrigin) {
+      if (!inputElement ||
+          LoginUtils._getPasswordOrigin(inputElement.ownerDocument.documentURI) != loginFormOrigin) {
+        log("fillForm: The requested origin doesn't match the one form the",
+            "document. This may mean we navigated to a document from a different",
+            "site before we had a chance to indicate this change in the user",
+            "interface.");
+        return;
+      }
     }
-    this._fillForm(topState.loginFormForFill, true, true, true, true,
-                   loginsFound, recipes);
+    let form = topState.loginFormForFill;
+    let clobberUsername = true;
+    let options = {
+      inputElement,
+    };
+
+    // If we have a target input, fills it's form.
+    if (inputElement) {
+      form = FormLikeFactory.createFromPasswordField(inputElement);
+      clobberUsername = false;
+    }
+    this._fillForm(form, true, clobberUsername, true, true, loginsFound, recipes, options);
   },
 
   loginsFound: function({ form, loginsFound, recipes }) {
     let doc = form.ownerDocument;
     let autofillForm = gAutofillForms && !PrivateBrowsingUtils.isContentWindowPrivate(doc.defaultView);
 
     this._fillForm(form, autofillForm, false, false, false, loginsFound, recipes);
   },
@@ -809,19 +824,21 @@ var LoginManagerContent = {
    * @param {bool} clobberUsername controls if an existing username can be
    *                               overwritten
    * @param {bool} clobberPassword controls if an existing password value can be
    *                               overwritten
    * @param {bool} userTriggered is an indication of whether this filling was triggered by
    *                             the user
    * @param {nsILoginInfo[]} foundLogins is an array of nsILoginInfo that could be used for the form
    * @param {Set} recipes that could be used to affect how the form is filled
+   * @param {Object} [options = {}] is a list of options for this method.
+            - [inputElement] is an optional target input element we want to fill
    */
   _fillForm : function (form, autofillForm, clobberUsername, clobberPassword,
-                        userTriggered, foundLogins, recipes) {
+                        userTriggered, foundLogins, recipes, {inputElement} = {}) {
     let ignoreAutocomplete = true;
     const AUTOFILL_RESULT = {
       FILLED: 0,
       NO_PASSWORD_FIELD: 1,
       PASSWORD_DISABLED_READONLY: 2,
       NO_LOGINS_FIT: 3,
       NO_SAVED_LOGINS: 4,
       EXISTING_PASSWORD: 5,
@@ -850,16 +867,27 @@ var LoginManagerContent = {
 
       // Heuristically determine what the user/pass fields are
       // We do this before checking to see if logins are stored,
       // so that the user isn't prompted for a master password
       // without need.
       var [usernameField, passwordField, ignored] =
             this._getFormFields(form, false, recipes);
 
+      // If we have a password inputElement parameter and it's not
+      // the same as the one heuristically found, use the parameter
+      // one instead.
+      if (inputElement) {
+        if (inputElement.type != "password") {
+          throw new Error("Unexpected input element type.");
+        }
+        passwordField = inputElement;
+        usernameField = null;
+      }
+
       // Need a valid password field to do anything.
       if (passwordField == null) {
         log("not filling form, no password field found");
         recordAutofillResult(AUTOFILL_RESULT.NO_PASSWORD_FIELD);
         return;
       }
 
       // If the password field is disabled or read-only, there's nothing to do.
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/LoginManagerContextMenu.jsm
@@ -0,0 +1,183 @@
+/* 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";
+
+this.EXPORTED_SYMBOLS = ["LoginManagerContextMenu"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
+                                  "resource://gre/modules/LoginManagerParent.jsm");
+
+/*
+ * Password manager object for the browser contextual menu.
+ */
+let LoginManagerContextMenu = {
+  dateAndTimeFormatter: new Intl.DateTimeFormat(undefined,
+                        { day: "numeric", month: "short", year: "numeric" }),
+  /**
+   * Look for login items and add them to the contextual menu.
+   *
+   * @param {HTMLInputElement} inputElement
+   *        The target input element of the context menu click.
+   * @param {xul:browser} browser
+   *        The browser for the document the context menu was open on.
+   * @param {nsIURI} documentURI
+   *        The URI of the document that the context menu was activated from.
+   *        This isn't the same as the browser's top-level document URI
+   *        when subframes are involved.
+   * @returns {DocumentFragment} a document fragment with all the login items.
+   */
+  addLoginsToMenu(inputElement, browser, documentURI) {
+
+    let foundLogins = this._findLogins(documentURI);
+
+    if (!foundLogins.length) {
+      return null;
+    }
+
+    let fragment = browser.ownerDocument.createDocumentFragment();
+    let duplicateUsernames = this._findDuplicates(foundLogins);
+    for (let login of foundLogins) {
+        let item = fragment.ownerDocument.createElement("menuitem");
+
+        let username = login.username;
+        // If login is empty or duplicated we want to append a modification date to it.
+        if (!username || duplicateUsernames.has(username)){
+          if (!username) {
+            username = this._getLocalizedString("noUsername");
+          }
+          let meta = login.QueryInterface(Ci.nsILoginMetaInfo);
+          let time = this.dateAndTimeFormatter.format(new Date(meta.timePasswordChanged));
+          username = this._getLocalizedString("loginHostAge", [username, time]);
+        }
+        item.setAttribute("label", username);
+        item.setAttribute("class", "context-login-item");
+
+        // login is bound so we can keep the reference to each object.
+        item.addEventListener("command", function(login, event) {
+          this._fillPassword(login, inputElement, browser, documentURI);
+        }.bind(this, login));
+
+        fragment.appendChild(item);
+    }
+
+    return fragment;
+  },
+
+  /**
+   * Undoes the work of addLoginsToMenu for the same menu.
+   *
+   * @param {Document}
+   *        The context menu owner document.
+   */
+  clearLoginsFromMenu(document) {
+    let loginItems = document.getElementsByClassName("context-login-item");
+    while (loginItems.item(0)) {
+      loginItems.item(0).remove();
+    }
+  },
+
+  /**
+   * Find logins for the current URI.
+   *
+   * @param {nsIURI} documentURI
+   *        URI object with the hostname of the logins we want to find.
+   *        This isn't the same as the browser's top-level document URI
+   *        when subframes are involved.
+   *
+   * @returns {nsILoginInfo[]} a login list
+   */
+  _findLogins(documentURI) {
+    let logins = Services.logins.findLogins({}, documentURI.prePath, "", "");
+
+    // Sort logins in alphabetical order and by date.
+    logins.sort((loginA, loginB) => {
+      // Sort alphabetically
+      let result = loginA.username.localeCompare(loginB.username);
+      if (result) {
+        // Forces empty logins to be at the end
+        if (!loginA.username) {
+          return 1;
+        }
+        if (!loginB.username) {
+          return -1;
+        }
+        return result;
+      }
+
+      // Same username logins are sorted by last change date
+      let metaA = loginA.QueryInterface(Ci.nsILoginMetaInfo);
+      let metaB = loginB.QueryInterface(Ci.nsILoginMetaInfo);
+      return metaB.timePasswordChanged - metaA.timePasswordChanged;
+    });
+
+    return logins;
+  },
+
+  /**
+   * Find duplicate usernames in a login list.
+   *
+   * @param {nsILoginInfo[]} loginList
+   *        A list of logins we want to look for duplicate usernames.
+   *
+   * @returns {Set} a set with the duplicate usernames.
+   */
+  _findDuplicates(loginList) {
+    let seen = new Set();
+    let duplicates = new Set();
+    for (let login of loginList) {
+      if (seen.has(login.username)) {
+        duplicates.add(login.username);
+      }
+      seen.add(login.username);
+    }
+    return duplicates;
+  },
+
+  /**
+   * @param {nsILoginInfo} login
+   *        The login we want to fill the form with.
+   * @param {Element} inputElement
+   *        The target input element we want to fill.
+   * @param {xul:browser} browser
+   *        The target tab browser.
+   * @param {nsIURI} documentURI
+   *        URI of the document owning the form we want to fill.
+   *        This isn't the same as the browser's top-level
+   *        document URI when subframes are involved.
+   */
+  _fillPassword(login, inputElement, browser, documentURI) {
+    LoginManagerParent.fillForm({
+      browser: browser,
+      loginFormOrigin: documentURI.prePath,
+      login: login,
+      inputElement: inputElement,
+    }).catch(Cu.reportError);
+  },
+
+  /**
+   * @param {string} key
+   *        The localized string key
+   * @param {string[]} formatArgs
+   *        An array of formatting argument string
+   *
+   * @returns {string} the localized string for the specified key,
+   *          formatted with arguments if required.
+   */
+  _getLocalizedString(key, formatArgs) {
+    if (formatArgs) {
+      return this._stringBundle.formatStringFromName(key, formatArgs, formatArgs.length);
+    }
+    return this._stringBundle.GetStringFromName(key);
+  },
+};
+
+XPCOMUtils.defineLazyGetter(LoginManagerContextMenu, "_stringBundle", function() {
+  return Services.strings.
+         createBundle("chrome://passwordmgr/locale/passwordmgr.properties");
+});
--- a/toolkit/components/passwordmgr/LoginManagerParent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerParent.jsm
@@ -230,37 +230,39 @@ var LoginManagerParent = {
       }
     }
   },
 
   /**
    * Trigger a login form fill and send relevant data (e.g. logins and recipes)
    * to the child process (LoginManagerContent).
    */
-  fillForm: Task.async(function* ({ browser, loginFormOrigin, login }) {
+  fillForm: Task.async(function* ({ browser, loginFormOrigin, login, inputElement }) {
     let recipes = [];
     if (loginFormOrigin) {
       let formHost;
       try {
         formHost = (new URL(loginFormOrigin)).host;
         let recipeManager = yield this.recipeParentPromise;
         recipes = recipeManager.getRecipesForHost(formHost);
       } catch (ex) {
         // Some schemes e.g. chrome aren't supported by URL
       }
     }
 
     // Convert the array of nsILoginInfo to vanilla JS objects since nsILoginInfo
     // doesn't support structured cloning.
     let jsLogins = JSON.parse(JSON.stringify([login]));
+
+    let objects = inputElement ? {inputElement} : null;
     browser.messageManager.sendAsyncMessage("RemoteLogins:fillForm", {
       loginFormOrigin,
       logins: jsLogins,
       recipes,
-    });
+    }, objects);
   }),
 
   /**
    * Send relevant data (e.g. logins and recipes) to the child process (LoginManagerContent).
    */
   sendLoginDataToChild: Task.async(function*(showMasterPassword, formOrigin, actionOrigin,
                                              requestId, target) {
     let recipes = [];
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -449,8 +449,13 @@ function masterPasswordLogin(noPasswordC
 
 function escapeKeyHandler() {
   // If editing is currently performed, don't do anything.
   if (signonsTree.getAttribute("editing")) {
     return;
   }
   window.close();
 }
+
+function OpenMigrator() {
+  const { MigrationUtils } = Cu.import("resource:///modules/MigrationUtils.jsm", {});
+  MigrationUtils.showMigrationWizard(window);
+}
--- a/toolkit/components/passwordmgr/content/passwordManager.xul
+++ b/toolkit/components/passwordmgr/content/passwordManager.xul
@@ -98,16 +98,21 @@
     <hbox id="SignonViewerButtons">
       <button id="removeSignon" disabled="true" icon="remove"
               label="&remove.label;" accesskey="&remove.accesskey;"
               oncommand="DeleteSignon();"/>
       <button id="removeAllSignons" icon="clear"
               label="&removeall.label;" accesskey="&removeall.accesskey;"
               oncommand="DeleteAllSignons();"/>
       <spacer flex="1"/>
+#if defined(MOZ_BUILD_APP_IS_BROWSER) && defined(XP_WIN)
+      <button accesskey="&import.accesskey;"
+              label="&import.label;"
+              oncommand="OpenMigrator();"/>
+#endif
       <button id="togglePasswords"
               oncommand="TogglePasswordVisible();"/>
     </hbox>
   </vbox>
   <hbox align="end">
     <hbox class="actionButtons" flex="1">
       <spacer flex="1"/>
 #ifndef XP_MACOSX
--- a/toolkit/components/passwordmgr/content/passwordManagerCommon.js
+++ b/toolkit/components/passwordmgr/content/passwordManagerCommon.js
@@ -1,14 +1,16 @@
 /* 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/. */
 
 /*** =================== INITIALISATION CODE =================== ***/
 
+const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
+
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 var kObserverService;
 
 // interface variables
 var passwordmanager     = null;
 
 // password-manager lists
--- a/toolkit/components/passwordmgr/moz.build
+++ b/toolkit/components/passwordmgr/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+if CONFIG['MOZ_BUILD_APP'] == 'browser':
+    DEFINES['MOZ_BUILD_APP_IS_BROWSER'] = True
+
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
 TESTING_JS_MODULES += [
     'test/LoginTestUtils.jsm',
 ]
@@ -51,22 +54,27 @@ if CONFIG['OS_TARGET'] == 'Android':
     EXTRA_COMPONENTS += [
         'storage-mozStorage.js',
     ]
 else:
     EXTRA_COMPONENTS += [
         'storage-json.js',
     ]
     EXTRA_JS_MODULES += [
-        'LoginDoorhangers.jsm',
         'LoginImport.jsm',
         'LoginStore.jsm',
     ]
 
 if CONFIG['OS_TARGET'] == 'WINNT':
     EXTRA_JS_MODULES += [
         'OSCrypto_win.js',
     ]
 
+if CONFIG['MOZ_BUILD_APP'] == 'browser':
+    EXTRA_JS_MODULES += [
+        'LoginDoorhangers.jsm',
+        'LoginManagerContextMenu.jsm',
+    ]
+
 JAR_MANIFESTS += ['jar.mn']
 
 with Files('**'):
     BUG_COMPONENT = ('Toolkit', 'Password Manager')
--- a/toolkit/components/passwordmgr/test/browser/browser.ini
+++ b/toolkit/components/passwordmgr/test/browser/browser.ini
@@ -1,18 +1,20 @@
 [DEFAULT]
 support-files =
   authenticate.sjs
   form_basic.html
+  multiple_forms.html
 
 [browser_DOMFormHasPassword.js]
 [browser_DOMInputPasswordAdded.js]
 [browser_filldoorhanger.js]
 [browser_notifications.js]
 skip-if = true # Intermittent failures: Bug 1182296, bug 1148771
 [browser_passwordmgr_editing.js]
 skip-if = os == "linux"
+[browser_context_menu.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_context_menu.js
@@ -0,0 +1,270 @@
+/*
+ * Test the password manager context menu.
+ */
+
+"use strict";
+
+Cu.import("resource://testing-common/LoginTestUtils.jsm", this);
+
+// The hostname for the test URIs.
+const TEST_HOSTNAME = "https://example.com";
+
+/**
+ * Initialize logins needed for the tests and disable autofill
+ * for login forms for easier testing of manual fill.
+ */
+add_task(function* test_initialize() {
+  Services.prefs.setBoolPref("signon.autofillForms", false);
+  registerCleanupFunction(() => {
+    Services.prefs.clearUserPref("signon.autofillForms");
+    Services.logins.removeAllLogins();
+  });
+  for (let login of loginList()) {
+    Services.logins.addLogin(login);
+  }
+});
+
+/**
+ * Check if the context menu is populated with the right
+ * menuitems for the target password input field.
+ */
+add_task(function* test_context_menu_populate() {
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: TEST_HOSTNAME + "/browser/toolkit/components/" +
+         "passwordmgr/test/browser/multiple_forms.html",
+  }, function* (browser) {
+    let passwordInput = browser.contentWindow.document.getElementById("test-password-1");
+
+    yield openPasswordContextMenu(browser, passwordInput);
+
+    // Check the content of the password manager popup
+    let popupMenu = document.getElementById("fill-login-popup");
+    checkMenu(popupMenu);
+
+    let contextMenu = document.getElementById("contentAreaContextMenu");
+    contextMenu.hidePopup();
+  });
+});
+
+/**
+ * Check if the password field is correctly filled when one
+ * login menuitem is clicked.
+ */
+add_task(function* test_context_menu_password_fill() {
+  // Set of element ids to check.
+  let testSet = [
+    {
+      passwordInput: "test-password-1",
+      unchangedFields: null,
+    },
+    {
+      passwordInput: "test-password-2",
+      unchangedFields: ["test-username-2"],
+    },
+    {
+      passwordInput: "test-password-3",
+      unchangedFields: ["test-username-3"],
+    },
+    {
+      passwordInput: "test-password-4",
+      unchangedFields: ["test-username-4"],
+    },
+    {
+      passwordInput: "test-password-5",
+      unchangedFields: ["test-username-5", "test-password2-5"],
+    },
+    {
+      passwordInput: "test-password2-5",
+      unchangedFields: ["test-username-5", "test-password-5"],
+    },
+    {
+      passwordInput: "test-password-6",
+      unchangedFields: ["test-username-6", "test-password2-6"],
+    },
+    {
+      passwordInput: "test-password2-6",
+      unchangedFields: ["test-username-6", "test-password-6"],
+    },
+    {
+      passwordInput: "test-password-7",
+      unchangedFields: null,
+    },
+  ];
+
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: TEST_HOSTNAME + "/browser/toolkit/components/" +
+         "passwordmgr/test/browser/multiple_forms.html",
+  }, function* (browser) {
+    for (let testCase of testSet) {
+      let passwordInput = browser.contentWindow.document.getElementById(testCase.passwordInput);
+
+      yield openPasswordContextMenu(browser, passwordInput);
+
+      let popupMenu = document.getElementById("fill-login-popup");
+
+      // Store the values of fields that should remain unchanged.
+      let unchangedFieldsValues = null;
+      if (testCase.unchangedFields) {
+        unchangedFieldsValues = [];
+        for (let fieldId of testCase.unchangedFields) {
+          unchangedFieldsValues[fieldId] = browser.contentWindow.document.getElementById(fieldId).value;
+        }
+      }
+
+      // Execute the default command of the first login menuitem found at the context menu.
+      let firstLoginItem = popupMenu.getElementsByClassName("context-login-item")[0];
+      firstLoginItem.doCommand();
+
+      yield BrowserTestUtils.waitForEvent(passwordInput, "input", "Password input value changed");
+
+      // Find the used login by it's username (Use only unique usernames in this test).
+      let login = getLoginFromUsername(firstLoginItem.label);
+
+      Assert.equal(login.password, passwordInput.value, "Password filled and correct.");
+
+      // Check that the fields that should remain unchanged didn't got modified.
+      if (testCase.unchangedFields) {
+        Assert.ok(testCase.unchangedFields.every(fieldId => {
+          return unchangedFieldsValues[fieldId] == browser.contentWindow.document.getElementById(fieldId).value;
+        }), "Other fields were not changed.");
+      }
+
+      let contextMenu = document.getElementById("contentAreaContextMenu");
+      contextMenu.hidePopup();
+    }
+  });
+});
+
+/**
+ * Check if the password field is correctly filled when it's in an iframe.
+ */
+add_task(function* test_context_menu_iframe_fill() {
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: TEST_HOSTNAME + "/browser/toolkit/components/" +
+         "passwordmgr/test/browser/multiple_forms.html",
+  }, function* (browser) {
+    let iframe = browser.contentWindow.document.getElementById("test-iframe");
+    let passwordInput = iframe.contentDocument.getElementById("form-basic-password");
+
+    let contextMenuShownPromise = BrowserTestUtils.waitForEvent(window, "popupshown");
+    let eventDetails = {type: "contextmenu", button: 2};
+
+    // To click at the right point we have to take into account the iframe offset.
+    let iframeRect = iframe.getBoundingClientRect();
+    let inputRect = passwordInput.getBoundingClientRect();
+    let clickPos = {
+      offsetX: iframeRect.left + inputRect.width / 2,
+      offsetY: iframeRect.top  + inputRect.height / 2,
+    };
+
+    // Synthesize a right mouse click over the password input element.
+    BrowserTestUtils.synthesizeMouse(passwordInput, clickPos.offsetX, clickPos.offsetY, eventDetails, browser);
+    yield contextMenuShownPromise;
+
+    // Synthesize a mouse click over the fill login menu header.
+    let popupHeader = document.getElementById("fill-login");
+    let popupShownPromise = BrowserTestUtils.waitForEvent(popupHeader, "popupshown");
+    EventUtils.synthesizeMouseAtCenter(popupHeader, {});
+    yield popupShownPromise;
+
+    let popupMenu = document.getElementById("fill-login-popup");
+
+    // Stores the original value of username
+    let usernameInput = iframe.contentDocument.getElementById("form-basic-username");
+    let usernameOriginalValue = usernameInput.value;
+
+    // Execute the command of the first login menuitem found at the context menu.
+    let firstLoginItem = popupMenu.getElementsByClassName("context-login-item")[0];
+    firstLoginItem.doCommand();
+
+    yield BrowserTestUtils.waitForEvent(passwordInput, "input", "Password input value changed");
+
+    // Find the used login by it's username.
+    let login = getLoginFromUsername(firstLoginItem.label);
+
+    Assert.equal(login.password, passwordInput.value, "Password filled and correct.");
+
+    Assert.equal(usernameOriginalValue,
+                 usernameInput.value,
+                 "Username value was not changed.");
+
+    let contextMenu = document.getElementById("contentAreaContextMenu");
+    contextMenu.hidePopup();
+  });
+});
+
+/**
+ * Synthesize mouse clicks to open the password manager context menu popup
+ * for a target password input element.
+ */
+function* openPasswordContextMenu(browser, passwordInput) {
+  // Synthesize a right mouse click over the password input element.
+  let contextMenuShownPromise = BrowserTestUtils.waitForEvent(window, "popupshown");
+  let eventDetails = {type: "contextmenu", button: 2};
+  BrowserTestUtils.synthesizeMouseAtCenter(passwordInput, eventDetails, browser);
+  yield contextMenuShownPromise;
+
+  // Synthesize a mouse click over the fill login menu header.
+  let popupHeader = document.getElementById("fill-login");
+  let popupShownPromise = BrowserTestUtils.waitForEvent(popupHeader, "popupshown");
+  EventUtils.synthesizeMouseAtCenter(popupHeader, {});
+  yield popupShownPromise;
+}
+
+/**
+ * Check if every login that matches the page hostname are available at the context menu.
+ */
+function checkMenu(contextMenu) {
+  let logins = loginList().filter(login => login.hostname == TEST_HOSTNAME);
+  // Make an array of menuitems for easier comparison.
+  let menuitems = [...contextMenu.getElementsByClassName("context-login-item")];
+  Assert.equal(menuitems.length, logins.length, "Same amount of menu items and expected logins.");
+  Assert.ok(logins.every(l => menuitems.some(m => l.username == m.label)), "Every login have an item at the menu.");
+}
+
+/**
+ * Search for a login by it's username.
+ *
+ * Only unique login/hostname combinations should be used at this test.
+ */
+function getLoginFromUsername(username) {
+  return loginList().find(login => login.username == username);
+}
+
+/**
+ * List of logins used for the test.
+ *
+ * We should only use unique usernames in this test,
+ * because we need to search logins by username.
+ */
+function loginList() {
+  return [
+    LoginTestUtils.testData.formLogin({
+      hostname: "https://example.com",
+      formSubmitURL: "https://example.com",
+      username: "username",
+      password: "password",
+    }),
+    LoginTestUtils.testData.formLogin({
+      hostname: "http://example.com",
+      formSubmitURL: "http://example.com",
+      username: "username1",
+      password: "password1",
+    }),
+    LoginTestUtils.testData.formLogin({
+      hostname: "https://example.com",
+      formSubmitURL: "https://example.com",
+      username: "username2",
+      password: "password2",
+    }),
+    LoginTestUtils.testData.formLogin({
+      hostname: "https://example.org",
+      formSubmitURL: "https://example.org",
+      username: "username-cross-origin",
+      password: "password-cross-origin",
+    }),
+  ];
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/browser/multiple_forms.html
@@ -0,0 +1,57 @@
+<!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/ -->
+
+<!-- Password only form -->
+<form id='form-1'>
+    <input id='test-password-1' type='password' name='pname' value=''>
+    <input type='submit'>Submit</input>
+</form>
+
+<!-- Simple username and password blank form -->
+<form id='form-2'>
+    <input id='test-username-2' type='text'     name='uname' value=''>
+    <input id='test-password-2' type='password' name='pname' value=''>
+    <button type='submit'>Submit</button>
+</form>
+
+<!-- Simple username and password form, prefilled username -->
+<form id='form-3'>
+    <input id='test-username-3' type='text'     name='uname' value='testuser'>
+    <input id='test-password-3' type='password' name='pname' value=''>
+    <button type='submit'>Submit</button>
+</form>
+
+<!-- Simple username and password form, prefilled username and password -->
+<form id='form-4'>
+    <input id='test-username-4' type='text'     name='uname' value='testuser'>
+    <input id='test-password-4' type='password' name='pname' value='testpass'>
+    <button type='submit'>Submit</button>
+</form>
+
+<!-- One username and two passwords empty form -->
+<form id='form-5'>
+    <input id='test-username-5'  type='text'     name='uname'>
+    <input id='test-password-5'  type='password' name='pname'>
+    <input id='test-password2-5' type='password' name='pname2'>
+    <button type='submit'>Submit</button>
+</form>
+
+<!-- One username and two passwords form, fields prefiled -->
+<form id='form-6'>
+    <input id='test-username-6'  type='text'     name='uname' value="testuser">
+    <input id='test-password-6'  type='password' name='pname' value="testpass">
+    <input id='test-password2-6' type='password' name='pname2' value="testpass">
+    <button type='submit'>Submit</button>
+</form>
+
+<!-- Password field with no form -->
+<div id='form-7'>
+    <input id='test-password-7' type='password' name='pname' value="testpass">
+</div>
+
+<!-- Form in an iframe -->
+<iframe src="https://example.org/browser/toolkit/components/passwordmgr/test/browser/form_basic.html" id="test-iframe"></iframe>
+
+</body>
+</html>
--- a/toolkit/components/passwordmgr/test/unit/head.js
+++ b/toolkit/components/passwordmgr/test/unit/head.js
@@ -124,21 +124,21 @@ const RecipeHelpers = {
     return (new LoginRecipesParent({ defaults: null })).initializationPromise;
   },
 };
 
 const MockDocument = {
   /**
    * Create a document for the given URL containing the given HTML with the ownerDocument of all <form>s having a mocked location.
    */
-  createTestDocument(aDocumentURL, aHTML = "<form>") {
+  createTestDocument(aDocumentURL, aContent = "<form>", aType = "text/html") {
     let parser = Cc["@mozilla.org/xmlextras/domparser;1"].
                  createInstance(Ci.nsIDOMParser);
     parser.init();
-    let parsedDoc = parser.parseFromString(aHTML, "text/html");
+    let parsedDoc = parser.parseFromString(aContent, aType);
 
     for (let element of parsedDoc.forms) {
       this.mockOwnerDocumentProperty(element, parsedDoc, aDocumentURL);
     }
     return parsedDoc;
   },
 
   mockOwnerDocumentProperty(aElement, aDoc, aURL) {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/unit/test_context_menu.js
@@ -0,0 +1,165 @@
+/*
+ * Test the password manager context menu.
+ */
+
+"use strict";
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/LoginManagerContextMenu.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "_stringBundle", function() {
+  return Services.strings.
+         createBundle("chrome://passwordmgr/locale/passwordmgr.properties");
+});
+
+/**
+ * Prepare data for the following tests.
+ */
+add_task(function* test_initialize() {
+  for (let login of loginList()) {
+    Services.logins.addLogin(login);
+  }
+});
+
+/**
+ * Tests if the LoginManagerContextMenu returns the correct login items.
+ */
+add_task(function* test_contextMenuAddAndRemoveLogins() {
+  const DOCUMENT_CONTENT = "<form><input id='pw' type=password></form>";
+  const INPUT_QUERY = "input[type='password']";
+
+  let testHostnames = [
+    "http://www.example.com",
+    "http://www2.example.com",
+    "http://www3.example.com",
+    "http://empty.example.com",
+  ];
+
+  for (let hostname of testHostnames) {
+    do_print("test for hostname: " + hostname);
+    // Get expected logins for this test.
+    let logins = getExpectedLogins(hostname);
+
+    // Create the logins menuitems fragment.
+    let {fragment, document} = createLoginsFragment(hostname, DOCUMENT_CONTENT, INPUT_QUERY);
+
+    if (!logins.length) {
+      Assert.ok(fragment === null, "Null returned. No logins where found.");
+      continue;
+    }
+    let items = [...fragment.querySelectorAll("menuitem")];
+
+    // Check if the items are those expected to be listed.
+    Assert.ok(checkLoginItems(logins, items), "All expected logins found.");
+    document.body.appendChild(fragment);
+
+    // Try to clear the fragment.
+    LoginManagerContextMenu.clearLoginsFromMenu(document);
+    Assert.equal(fragment.querySelectorAll("menuitem").length, 0, "All items correctly cleared.");
+  }
+
+  Services.logins.removeAllLogins();
+});
+
+/**
+ * Create a fragment with a menuitem for each login.
+ */
+function createLoginsFragment(url, content, elementQuery) {
+  const CHROME_URL = "chrome://mock-chrome";
+
+  // Create a mock document.
+  let document = MockDocument.createTestDocument(CHROME_URL, content);
+  let inputElement = document.querySelector(elementQuery);
+  MockDocument.mockOwnerDocumentProperty(inputElement, document, url);
+
+  // We also need a simple mock Browser object for this test.
+  let browser = {
+    ownerDocument: document
+  };
+
+  let URI = Services.io.newURI(url, null, null);
+  return {
+    document,
+    fragment: LoginManagerContextMenu.addLoginsToMenu(inputElement, browser, URI),
+  };
+}
+
+/**
+ * Check if every login have it's corresponding menuitem.
+ * Duplicates and empty usernames have a date appended.
+ */
+function checkLoginItems(logins, items) {
+  function findDuplicates(loginList) {
+    var seen = new Set();
+    var duplicates = new Set();
+    for (let login of loginList) {
+      if (seen.has(login.username)) {
+        duplicates.add(login.username);
+      }
+      seen.add(login.username);
+    }
+    return duplicates;
+  }
+  let duplicates = findDuplicates(logins);
+
+  let dateAndTimeFormatter = new Intl.DateTimeFormat(undefined,
+                             { day: "numeric", month: "short", year: "numeric" });
+  for (let login of logins) {
+    if (login.username && !duplicates.has(login.username)) {
+      // If login is not duplicate and we can't find an item for it, fail.
+      if (!items.find(item => item.label == login.username)) {
+        return false;
+      }
+      continue;
+    }
+
+    let meta = login.QueryInterface(Ci.nsILoginMetaInfo);
+    let time = dateAndTimeFormatter.format(new Date(meta.timePasswordChanged));
+    // If login is duplicate, check if we have a login item with appended date.
+    if (login.username && !items.find(item => item.label == login.username + " (" + time + ")")) {
+      return false;
+    }
+    // If login is empty, check if we have a login item with appended date.
+    if (!login.username &&
+        !items.find(item => item.label == _stringBundle.GetStringFromName("noUsername") + " (" + time + ")")) {
+      return false;
+    }
+  }
+  return true;
+}
+
+/**
+ * Gets the list of expected logins for a hostname.
+ */
+function getExpectedLogins(hostname) {
+  return Services.logins.getAllLogins().filter(entry => entry["hostname"] === hostname);
+}
+
+function loginList() {
+  return [
+      new LoginInfo("http://www.example.com", "http://www.example.com", null,
+                    "username1", "password",
+                    "form_field_username", "form_field_password"),
+
+      new LoginInfo("http://www.example.com", "http://www.example.com", null,
+                    "username2", "password",
+                    "form_field_username", "form_field_password"),
+
+      new LoginInfo("http://www2.example.com", "http://www.example.com", null,
+                    "username", "password",
+                    "form_field_username", "form_field_password"),
+      new LoginInfo("http://www2.example.com", "http://www2.example.com", null,
+                    "username", "password2",
+                    "form_field_username", "form_field_password"),
+      new LoginInfo("http://www2.example.com", "http://www2.example.com", null,
+                    "username2", "password2",
+                    "form_field_username", "form_field_password"),
+
+      new LoginInfo("http://www3.example.com", "http://www.example.com", null,
+                    "", "password",
+                    "form_field_username", "form_field_password"),
+      new LoginInfo("http://www3.example.com", "http://www3.example.com", null,
+                    "", "password2",
+                    "form_field_username", "form_field_password"),
+  ];
+}
--- a/toolkit/components/passwordmgr/test/unit/xpcshell.ini
+++ b/toolkit/components/passwordmgr/test/unit/xpcshell.ini
@@ -10,16 +10,18 @@ skip-if = os == "android"
 [test_module_LoginStore.js]
 skip-if = os == "android"
 
 # Test SQLite database backup and migration, applicable to Android only.
 [test_storage_mozStorage.js]
 skip-if = true || os != "android" # Bug 1171687: Needs fixing on Android
 
 # The following tests apply to any storage back-end.
+[test_context_menu.js]
+skip-if = os == "android" # The context menu isn't used on Android.
 [test_disabled_hosts.js]
 [test_getFormFields.js]
 [test_getPasswordFields.js]
 [test_legacy_empty_formSubmitURL.js]
 [test_legacy_validation.js]
 [test_logins_change.js]
 [test_logins_decrypt_failure.js]
 skip-if = os == "android" # Bug 1171687: Needs fixing on Android
--- a/toolkit/components/url-classifier/SafeBrowsing.jsm
+++ b/toolkit/components/url-classifier/SafeBrowsing.jsm
@@ -24,16 +24,17 @@ function getLists(prefName) {
 }
 
 // These may be a comma-separated lists of tables.
 const phishingLists = getLists("urlclassifier.phishTable");
 const malwareLists = getLists("urlclassifier.malwareTable");
 const downloadBlockLists = getLists("urlclassifier.downloadBlockTable");
 const downloadAllowLists = getLists("urlclassifier.downloadAllowTable");
 const trackingProtectionLists = getLists("urlclassifier.trackingTable");
+const trackingProtectionWhitelists = getLists("urlclassifier.trackingWhitelistTable");
 
 var debug = false;
 function log(...stuff) {
   if (!debug)
     return;
 
   var d = new Date();
   let msg = "SafeBrowsing: " + d.toTimeString() + ": " + stuff.join(" ");
@@ -68,16 +69,21 @@ this.SafeBrowsing = {
     for (let i = 0; i < downloadAllowLists.length; ++i) {
       listManager.registerTable(downloadAllowLists[i], this.updateURL, this.gethashURL);
     }
     for (let i = 0; i < trackingProtectionLists.length; ++i) {
       listManager.registerTable(trackingProtectionLists[i],
                                 this.trackingUpdateURL,
                                 this.trackingGethashURL);
     }
+    for (let i = 0; i < trackingProtectionWhitelists.length; ++i) {
+      listManager.registerTable(trackingProtectionWhitelists[i],
+                                this.trackingUpdateURL,
+                                this.trackingGethashURL);
+    }
     this.addMozEntries();
 
     this.controlUpdateChecking();
     this.initialized = true;
 
     log("init() finished");
   },
 
@@ -195,64 +201,71 @@ this.SafeBrowsing = {
         listManager.enableUpdate(downloadAllowLists[i]);
       } else {
         listManager.disableUpdate(downloadAllowLists[i]);
       }
     }
     for (let i = 0; i < trackingProtectionLists.length; ++i) {
       if (this.trackingEnabled) {
         listManager.enableUpdate(trackingProtectionLists[i]);
+        listManager.enableUpdate(trackingProtectionWhitelists[i]);
       } else {
         listManager.disableUpdate(trackingProtectionLists[i]);
+        listManager.disableUpdate(trackingProtectionWhitelists[i]);
       }
     }
     listManager.maybeToggleUpdateChecking();
   },
 
 
   addMozEntries: function() {
     // Add test entries to the DB.
     // XXX bug 779008 - this could be done by DB itself?
     const phishURL    = "itisatrap.org/firefox/its-a-trap.html";
     const malwareURL  = "itisatrap.org/firefox/its-an-attack.html";
     const unwantedURL = "itisatrap.org/firefox/unwanted.html";
-    const trackerURLs  = [
+    const trackerURLs = [
       "trackertest.org/",
       "itisatracker.org/",
     ];
+    const whitelistURL = "itisatrap.org/?resource=itisatracker.org";
 
     let update = "n:1000\ni:test-malware-simple\nad:1\n" +
                  "a:1:32:" + malwareURL.length + "\n" +
-                 malwareURL;
+                 malwareURL + "\n";
     update += "n:1000\ni:test-phish-simple\nad:1\n" +
               "a:1:32:" + phishURL.length + "\n" +
-              phishURL;
+              phishURL  + "\n";
     update += "n:1000\ni:test-unwanted-simple\nad:1\n" +
               "a:1:32:" + unwantedURL.length + "\n" +
-              unwantedURL;
+              unwantedURL + "\n";
+    update += "n:1000\ni:test-track-simple\n" +
+              "ad:" + trackerURLs.length + "\n";
     trackerURLs.forEach((trackerURL, i) => {
-      update += "n:1000\ni:test-track-simple\nad:1\n" +
-                "a:" + (i + 1) + ":32:" + trackerURL.length + "\n" +
-                trackerURL;
+      update += "a:" + (i + 1) + ":32:" + trackerURL.length + "\n" +
+                trackerURL + "\n";
     });
+    update += "n:1000\ni:test-trackwhite-simple\nad:1\n" +
+              "a:1:32:" + whitelistURL.length + "\n" +
+              whitelistURL;
     log("addMozEntries:", update);
 
     let db = Cc["@mozilla.org/url-classifier/dbservice;1"].
              getService(Ci.nsIUrlClassifierDBService);
 
     // nsIUrlClassifierUpdateObserver
     let dummyListener = {
       updateUrlRequested: function() { },
       streamFinished:     function() { },
       updateError:        function() { },
       updateSuccess:      function() { }
     };
 
     try {
-      let tables = "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple";
+      let tables = "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple";
       db.beginUpdate(dummyListener, tables, "");
       db.beginStream("", "");
       db.updateStream(update);
       db.finishStream();
       db.finishUpdate();
     } catch(ex) {
       // beginUpdate will throw harmlessly if there's an existing update in progress, ignore failures.
       log("addMozEntries failed!", ex);
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -73,16 +73,17 @@ PRLogModuleInfo *gUrlClassifierDbService
 
 #define GETHASH_NOISE_PREF      "urlclassifier.gethashnoise"
 #define GETHASH_NOISE_DEFAULT   4
 
 // Comma-separated lists
 #define MALWARE_TABLE_PREF      "urlclassifier.malwareTable"
 #define PHISH_TABLE_PREF        "urlclassifier.phishTable"
 #define TRACKING_TABLE_PREF     "urlclassifier.trackingTable"
+#define TRACKING_WHITELIST_TABLE_PREF "urlclassifier.trackingWhitelistTable"
 #define DOWNLOAD_BLOCK_TABLE_PREF "urlclassifier.downloadBlockTable"
 #define DOWNLOAD_ALLOW_TABLE_PREF "urlclassifier.downloadAllowTable"
 #define DISALLOW_COMPLETION_TABLE_PREF "urlclassifier.disallow_completions"
 
 #define CONFIRM_AGE_PREF        "urlclassifier.max-complete-age"
 #define CONFIRM_AGE_DEFAULT_SEC (45 * 60)
 
 class nsUrlClassifierDBServiceWorker;
@@ -1063,16 +1064,22 @@ nsUrlClassifierDBService::ReadTablesFrom
   }
 
   Preferences::GetCString(TRACKING_TABLE_PREF, &tables);
   if (!tables.IsEmpty()) {
     allTables.Append(',');
     allTables.Append(tables);
   }
 
+  Preferences::GetCString(TRACKING_WHITELIST_TABLE_PREF, &tables);
+  if (!tables.IsEmpty()) {
+    allTables.Append(',');
+    allTables.Append(tables);
+  }
+
   Classifier::SplitTables(allTables, mGethashTables);
 
   Preferences::GetCString(DISALLOW_COMPLETION_TABLE_PREF, &tables);
   Classifier::SplitTables(tables, mDisallowCompletionsTables);
 
   return NS_OK;
 }
 
@@ -1110,16 +1117,17 @@ nsUrlClassifierDBService::Init()
   Preferences::AddStrongObserver(this, CHECK_PHISHING_PREF);
   Preferences::AddStrongObserver(this, CHECK_TRACKING_PREF);
   Preferences::AddStrongObserver(this, CHECK_TRACKING_PB_PREF);
   Preferences::AddStrongObserver(this, GETHASH_NOISE_PREF);
   Preferences::AddStrongObserver(this, CONFIRM_AGE_PREF);
   Preferences::AddStrongObserver(this, PHISH_TABLE_PREF);
   Preferences::AddStrongObserver(this, MALWARE_TABLE_PREF);
   Preferences::AddStrongObserver(this, TRACKING_TABLE_PREF);
+  Preferences::AddStrongObserver(this, TRACKING_WHITELIST_TABLE_PREF);
   Preferences::AddStrongObserver(this, DOWNLOAD_BLOCK_TABLE_PREF);
   Preferences::AddStrongObserver(this, DOWNLOAD_ALLOW_TABLE_PREF);
   Preferences::AddStrongObserver(this, DISALLOW_COMPLETION_TABLE_PREF);
 
   // Force PSM loading on main thread
   nsresult rv;
   nsCOMPtr<nsICryptoHash> dummy = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1181,21 +1189,32 @@ nsUrlClassifierDBService::BuildTables(bo
     tables.Append(malware);
   }
   nsAutoCString phishing;
   Preferences::GetCString(PHISH_TABLE_PREF, &phishing);
   if (mCheckPhishing && !phishing.IsEmpty()) {
     tables.Append(',');
     tables.Append(phishing);
   }
-  nsAutoCString tracking;
-  Preferences::GetCString(TRACKING_TABLE_PREF, &tracking);
-  if (aTrackingProtectionEnabled && !tracking.IsEmpty()) {
-    tables.Append(',');
-    tables.Append(tracking);
+  if (aTrackingProtectionEnabled) {
+    nsAutoCString tracking, trackingWhitelist;
+    Preferences::GetCString(TRACKING_TABLE_PREF, &tracking);
+    if (!tracking.IsEmpty()) {
+      tables.Append(',');
+      tables.Append(tracking);
+    }
+    Preferences::GetCString(TRACKING_WHITELIST_TABLE_PREF, &trackingWhitelist);
+    if (!trackingWhitelist.IsEmpty()) {
+      tables.Append(',');
+      tables.Append(trackingWhitelist);
+    }
+  }
+
+  if (StringBeginsWith(tables, NS_LITERAL_CSTRING(","))) {
+    tables.Cut(0, 1);
   }
 }
 
 // nsChannelClassifier is the only consumer of this interface.
 NS_IMETHODIMP
 nsUrlClassifierDBService::Classify(nsIPrincipal* aPrincipal,
                                    bool aTrackingProtectionEnabled,
                                    nsIURIClassifierCallback* c,
@@ -1224,35 +1243,30 @@ nsUrlClassifierDBService::Classify(nsIPr
     return NS_OK;
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsUrlClassifierDBService::ClassifyLocalWithTables(nsIPrincipal *aPrincipal,
+nsUrlClassifierDBService::ClassifyLocalWithTables(nsIURI *aURI,
                                                   const nsACString & aTables,
                                                   nsACString & aTableResults)
 {
   MOZ_ASSERT(NS_IsMainThread(), "ClassifyLocalWithTables must be on main thread");
 
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
-
-  uri = NS_GetInnermostURI(uri);
+  nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
   NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
 
   nsAutoCString key;
   // Canonicalize the url
   nsCOMPtr<nsIUrlClassifierUtils> utilsService =
     do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
-  rv = utilsService->GetKeyForURI(uri, key);
+  nsresult rv = utilsService->GetKeyForURI(uri, key);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoPtr<LookupResultArray> results(new LookupResultArray());
   if (!results) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // In unittests, we may not have been initalized, so don't crash.
@@ -1508,16 +1522,17 @@ nsUrlClassifierDBService::Observe(nsISup
                NS_LITERAL_STRING(CHECK_TRACKING_PB_PREF).Equals(aData)) {
       mCheckTracking =
         Preferences::GetBool(CHECK_TRACKING_PREF, CHECK_TRACKING_DEFAULT) ||
         Preferences::GetBool(CHECK_TRACKING_PB_PREF, CHECK_TRACKING_PB_DEFAULT);
     } else if (
       NS_LITERAL_STRING(PHISH_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(MALWARE_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(TRACKING_TABLE_PREF).Equals(aData) ||
+      NS_LITERAL_STRING(TRACKING_WHITELIST_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(DOWNLOAD_BLOCK_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(DOWNLOAD_ALLOW_TABLE_PREF).Equals(aData) ||
       NS_LITERAL_STRING(DISALLOW_COMPLETION_TABLE_PREF).Equals(aData)) {
       // Just read everything again.
       ReadTablesFromPrefs();
     } else if (NS_LITERAL_STRING(CONFIRM_AGE_PREF).Equals(aData)) {
       gFreshnessGuarantee = Preferences::GetInt(CONFIRM_AGE_PREF,
         CONFIRM_AGE_DEFAULT_SEC);
@@ -1547,16 +1562,17 @@ nsUrlClassifierDBService::Shutdown()
   if (prefs) {
     prefs->RemoveObserver(CHECK_MALWARE_PREF, this);
     prefs->RemoveObserver(CHECK_PHISHING_PREF, this);
     prefs->RemoveObserver(CHECK_TRACKING_PREF, this);
     prefs->RemoveObserver(CHECK_TRACKING_PB_PREF, this);
     prefs->RemoveObserver(PHISH_TABLE_PREF, this);
     prefs->RemoveObserver(MALWARE_TABLE_PREF, this);
     prefs->RemoveObserver(TRACKING_TABLE_PREF, this);
+    prefs->RemoveObserver(TRACKING_WHITELIST_TABLE_PREF, this);
     prefs->RemoveObserver(DOWNLOAD_BLOCK_TABLE_PREF, this);
     prefs->RemoveObserver(DOWNLOAD_ALLOW_TABLE_PREF, this);
     prefs->RemoveObserver(DISALLOW_COMPLETION_TABLE_PREF, this);
     prefs->RemoveObserver(CONFIRM_AGE_PREF, this);
   }
 
   DebugOnly<nsresult> rv;
   // First close the db connection.
--- a/toolkit/components/url-classifier/tests/UrlClassifierTestUtils.jsm
+++ b/toolkit/components/url-classifier/tests/UrlClassifierTestUtils.jsm
@@ -1,45 +1,74 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["UrlClassifierTestUtils"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
+const TRACKING_TABLE_NAME = "mochitest-track-simple";
+const TRACKING_TABLE_PREF = "urlclassifier.trackingTable";
+const WHITELIST_TABLE_NAME = "mochitest-trackwhite-simple";
+const WHITELIST_TABLE_PREF = "urlclassifier.trackingWhitelistTable";
+
 Cu.import("resource://gre/modules/Services.jsm");
 
 this.UrlClassifierTestUtils = {
 
   addTestTrackers() {
-    const TABLE_PREF = "urlclassifier.trackingTable";
-    const TABLE_NAME = "test-track-simple";
+    // Add some URLs to the tracking databases
+    let trackingURL1 = "tracking.example.com/";
+    let trackingURL2 = "itisatracker.org/";
+    let trackingURL3 = "trackertest.org/";
+    let whitelistedURL = "itisatrap.org/?resource=itisatracker.org";
 
-    // Add some URLs to the tracking database (to be blocked)
-    let testData = "tracking.example.com/";
-    let testUpdate =
-          "n:1000\ni:test-track-simple\nad:1\n" +
-          "a:524:32:" + testData.length + "\n" +
-          testData;
+    let trackingUpdate =
+          "n:1000\ni:" + TRACKING_TABLE_NAME + "\nad:3\n" +
+          "a:1:32:" + trackingURL1.length + "\n" +
+          trackingURL1 + "\n" +
+          "a:2:32:" + trackingURL2.length + "\n" +
+          trackingURL2 + "\n" +
+          "a:3:32:" + trackingURL3.length + "\n" +
+          trackingURL3 + "\n";
+    let whitelistUpdate =
+          "n:1000\ni:" + WHITELIST_TABLE_NAME + "\nad:1\n" +
+          "a:1:32:" + whitelistedURL.length + "\n" +
+          whitelistedURL + "\n";
 
-    return this.useTestDatabase(TABLE_PREF, TABLE_NAME, testUpdate);
+    var tables = [
+      {
+        pref: TRACKING_TABLE_PREF,
+        name: TRACKING_TABLE_NAME,
+        update: trackingUpdate
+      },
+      {
+        pref: WHITELIST_TABLE_PREF,
+        name: WHITELIST_TABLE_NAME,
+        update: whitelistUpdate
+      }
+    ];
+
+    return this.useTestDatabase(tables);
   },
 
   cleanupTestTrackers() {
-    const TABLE_PREF = "urlclassifier.trackingTable";
-    Services.prefs.clearUserPref(TABLE_PREF);
+    Services.prefs.clearUserPref(TRACKING_TABLE_PREF);
+    Services.prefs.clearUserPref(WHITELIST_TABLE_PREF);
   },
 
   /**
    * Add some entries to a test tracking protection database, and resets
    * back to the default database after the test ends.
    *
    * @return {Promise}
    */
-  useTestDatabase(tablePref, tableName, update) {
-    Services.prefs.setCharPref(tablePref, tableName);
+  useTestDatabase(tables) {
+    for (var table of tables) {
+      Services.prefs.setCharPref(table.pref, table.name);
+    }
 
     return new Promise((resolve, reject) => {
       let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"].
                       getService(Ci.nsIUrlClassifierDBService);
       let listener = {
         QueryInterface: iid => {
           if (iid.equals(Ci.nsISupports) ||
               iid.equals(Ci.nsIUrlClassifierUpdateObserver))
@@ -52,16 +81,18 @@ this.UrlClassifierTestUtils = {
         updateError: errorCode => {
           reject("Couldn't update classifier.");
         },
         updateSuccess: requestedTimeout => {
           resolve();
         }
       };
 
-      dbService.beginUpdate(listener, tableName, "");
-      dbService.beginStream("", "");
-      dbService.updateStream(update);
-      dbService.finishStream();
-      dbService.finishUpdate();
+      for (var table of tables) {
+        dbService.beginUpdate(listener, table.name, "");
+        dbService.beginStream("", "");
+        dbService.updateStream(table.update);
+        dbService.finishStream();
+        dbService.finishUpdate();
+      }
     });
   },
 };
--- a/toolkit/components/url-classifier/tests/mochitest/chrome.ini
+++ b/toolkit/components/url-classifier/tests/mochitest/chrome.ini
@@ -9,8 +9,10 @@ support-files =
 [test_classified_annotations.html]
 tags = trackingprotection
 [test_allowlisted_annotations.html]
 tags = trackingprotection
 [test_privatebrowsing_trackingprotection.html]
 tags = trackingprotection
 [test_trackingprotection_bug1157081.html]
 tags = trackingprotection
+[test_trackingprotection_whitelist.html]
+tags = trackingprotection
--- a/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html
+++ b/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html
@@ -7,16 +7,18 @@
 
 <link id="badcss" rel="stylesheet" type="text/css" href="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.css"></link>
 
 </head>
 <body>
 
 <script id="badscript" data-touched="not sure" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
 
+<script id="goodscript" data-touched="not sure" src="http://itisatracker.org/tests/toolkit/components/url-classifier/tests/mochitest/good.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
+
 <!-- The image cache can cache JS handlers, so make sure we use a different URL for raptor.jpg each time -->
 <img id="badimage" data-touched="not sure" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg?pbmode=test" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"/>
 
 The following should not be hidden:
 <div id="styleCheck">STYLE TEST</div>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/url-classifier/tests/mochitest/good.js
@@ -0,0 +1,1 @@
+scriptItem = "loaded whitelisted javascript!";
--- a/toolkit/components/url-classifier/tests/mochitest/mochitest.ini
+++ b/toolkit/components/url-classifier/tests/mochitest/mochitest.ini
@@ -1,16 +1,19 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g' || e10s
 support-files =
+  classifiedAnnotatedPBFrame.html
   classifierFrame.html
   cleanWorker.js
+  good.js
   evil.css
   evil.js
   evilWorker.js
   import.css
   raptor.jpg
   track.html
   unwantedWorker.js
+  whitelistFrame.html
   workerFrame.html
 
 [test_classifier.html]
 [test_classifier_worker.html]
--- a/toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
@@ -20,17 +20,17 @@ var Cc = SpecialPowers.Cc;
 var Ci = SpecialPowers.Ci;
 
 var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIDOMWindow);
-var contentPage = "chrome://mochitests/content/chrome/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html"
+var contentPage = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html";
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
 
 function whenDelayedStartupFinished(aWindow, aCallback) {
   Services.obs.addObserver(function observer(aSubject, aTopic) {
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
@@ -66,16 +66,17 @@ var badids = [
   "badimage",
   "badcss"
 ];
 
 function checkLoads(aWindow, aBlocked) {
   var win = aWindow.content;
   is(win.document.getElementById("badscript").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking javascript");
   is(win.document.getElementById("badimage").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking images");
+  is(win.document.getElementById("goodscript").dataset.touched, "yes", "Should load whitelisted tracking javascript");
 
   var elt = win.document.getElementById("styleCheck");
   var style = win.document.defaultView.getComputedStyle(elt, "");
   isnot(style.visibility, aBlocked ? "hidden" : "", "Should not load tracking css");
 
   is(win.document.blockedTrackingNodeCount, aBlocked ? badids.length : 0, "Should identify all tracking elements");
 
   var blockedTrackingNodes = win.document.blockedTrackingNodes;
copy from toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
copy to toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
--- a/toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
@@ -20,32 +20,33 @@ var Cc = SpecialPowers.Cc;
 var Ci = SpecialPowers.Ci;
 
 var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIDOMWindow);
-var contentPage = "chrome://mochitests/content/chrome/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html"
+var contentPage1 = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html";
+var contentPage2 = "http://example.com/tests/toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html";
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
 
 function whenDelayedStartupFinished(aWindow, aCallback) {
   Services.obs.addObserver(function observer(aSubject, aTopic) {
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
       setTimeout(aCallback, 0);
     }
   }, "browser-delayed-startup-finished", false);
 }
 
-function testOnWindow(aPrivate, aCallback) {
-  var win = mainWindow.OpenBrowserWindow({private: aPrivate});
+function testOnWindow(contentPage, aCallback) {
+  var win = mainWindow.OpenBrowserWindow();
   win.addEventListener("load", function onLoad() {
     win.removeEventListener("load", onLoad, false);
     whenDelayedStartupFinished(win, function() {
       win.addEventListener("DOMContentLoaded", function onInnerLoad() {
         if (win.content.location.href != contentPage) {
           win.gBrowser.loadURI(contentPage);
           return;
         }
@@ -56,32 +57,30 @@ function testOnWindow(aPrivate, aCallbac
           SimpleTest.executeSoon(function() { aCallback(win); });
         }, false, true);
       }, true);
       SimpleTest.executeSoon(function() { win.gBrowser.loadURI(contentPage); });
     });
   }, true);
 }
 
-var badids = [
+var alwaysbadids = [
   "badscript",
-  "badimage",
-  "badcss"
 ];
 
-function checkLoads(aWindow, aBlocked) {
+function checkLoads(aWindow, aWhitelisted) {
   var win = aWindow.content;
-  is(win.document.getElementById("badscript").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking javascript");
-  is(win.document.getElementById("badimage").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking images");
+  is(win.document.getElementById("badscript").dataset.touched, "no", "Should not load tracking javascript");
+  is(win.document.getElementById("goodscript").dataset.touched, aWhitelisted ? "yes" : "no", "Should load whitelisted tracking javascript");
 
-  var elt = win.document.getElementById("styleCheck");
-  var style = win.document.defaultView.getComputedStyle(elt, "");
-  isnot(style.visibility, aBlocked ? "hidden" : "", "Should not load tracking css");
-
-  is(win.document.blockedTrackingNodeCount, aBlocked ? badids.length : 0, "Should identify all tracking elements");
+  var badids = alwaysbadids.slice();
+  if (!aWhitelisted) {
+    badids.push("goodscript");
+  }
+  is(win.document.blockedTrackingNodeCount, badids.length, "Should identify all tracking elements");
 
   var blockedTrackingNodes = win.document.blockedTrackingNodes;
 
   // Make sure that every node in blockedTrackingNodes exists in the tree
   // (that may not always be the case but do not expect any nodes to disappear
   // from the tree here)
   var allNodeMatch = true;
   for (var i = 0; i < blockedTrackingNodes.length; i++) {
@@ -103,43 +102,41 @@ function checkLoads(aWindow, aBlocked) {
     var nodeMatch = false;
     for (var i = 0; i < blockedTrackingNodes.length && !nodeMatch; i++) {
       nodeMatch = nodeMatch ||
         (blockedTrackingNodes[i] == win.document.getElementById(badids[j]));
     }
 
     allNodeMatch = allNodeMatch && nodeMatch;
   }
-  is(allNodeMatch, aBlocked, "All tracking nodes are expected to be annotated as such");
+  is(allNodeMatch, true, "All tracking nodes are expected to be annotated as such");
 }
 
 SpecialPowers.pushPrefEnv(
-  {"set" : [["urlclassifier.trackingTable", "test-track-simple"],
-            ["privacy.trackingprotection.enabled", false],
-            ["privacy.trackingprotection.pbmode.enabled", true],
+  {"set" : [["privacy.trackingprotection.enabled", true],
             ["channelclassifier.allowlist_example", true]]},
   test);
 
 function test() {
   SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
   UrlClassifierTestUtils.addTestTrackers().then(() => {
-    // Normal mode, with the pref (trackers should be loaded)
-    testOnWindow(false, function(aWindow) {
-      checkLoads(aWindow, false);
+    // Load the test from a URL on the whitelist
+    testOnWindow(contentPage1, function(aWindow) {
+      checkLoads(aWindow, true);
       aWindow.close();
 
-      // Private Browsing, with the pref (trackers should be blocked)
-      testOnWindow(true, function(aWindow) {
-        checkLoads(aWindow, true);
+      // Load the test from a URL that's NOT on the whitelist
+      testOnWindow(contentPage2, function(aWindow) {
+        checkLoads(aWindow, false);
         aWindow.close();
 
-        // Private Browsing, without the pref (trackers should be loaded)
-        SpecialPowers.setBoolPref("privacy.trackingprotection.pbmode.enabled", false);
-        testOnWindow(true, function(aWindow) {
-          checkLoads(aWindow, false);
+        // Load the test from a URL on the whitelist but without the whitelist
+        SpecialPowers.setCharPref("urlclassifier.trackingWhitelistTable", "");
+        testOnWindow(contentPage1, function(aWindow) {
+        checkLoads(aWindow, false);
           aWindow.close();
           SimpleTest.finish();
         });
       });
     });
   });
 }
 
copy from toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html
copy to toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html
--- a/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html
+++ b/toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html
@@ -1,22 +1,15 @@
 <!DOCTYPE HTML>
 <!-- Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/ -->
 <html>
 <head>
 <title></title>
-
-<link id="badcss" rel="stylesheet" type="text/css" href="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.css"></link>
-
 </head>
 <body>
 
-<script id="badscript" data-touched="not sure" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
+<script id="badscript" data-touched="not sure" src="http://trackertest.org/tests/toolkit/components/url-classifier/tests/mochitest/evil.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
 
-<!-- The image cache can cache JS handlers, so make sure we use a different URL for raptor.jpg each time -->
-<img id="badimage" data-touched="not sure" src="http://tracking.example.com/tests/toolkit/components/url-classifier/tests/mochitest/raptor.jpg?pbmode=test" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"/>
-
-The following should not be hidden:
-<div id="styleCheck">STYLE TEST</div>
+<script id="goodscript" data-touched="not sure" src="http://itisatracker.org/tests/toolkit/components/url-classifier/tests/mochitest/good.js" onload="this.dataset.touched = 'yes';" onerror="this.dataset.touched = 'no';"></script>
 
 </body>
 </html>
--- a/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
+++ b/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
@@ -50,29 +50,32 @@ function delFile(name) {
 
 function cleanUp() {
   delFile("urlclassifier3.sqlite");
   delFile("safebrowsing/classifier.hashkey");
   delFile("safebrowsing/test-phish-simple.sbstore");
   delFile("safebrowsing/test-malware-simple.sbstore");
   delFile("safebrowsing/test-unwanted-simple.sbstore");
   delFile("safebrowsing/test-track-simple.sbstore");
+  delFile("safebrowsing/test-trackwhite-simple.sbstore");
   delFile("safebrowsing/test-phish-simple.cache");
   delFile("safebrowsing/test-malware-simple.cache");
   delFile("safebrowsing/test-unwanted-simple.cache");
   delFile("safebrowsing/test-track-simple.cache");
+  delFile("safebrowsing/test-trackwhite-simple.cache");
   delFile("safebrowsing/test-phish-simple.pset");
   delFile("safebrowsing/test-malware-simple.pset");
   delFile("safebrowsing/test-unwanted-simple.pset");
   delFile("safebrowsing/test-track-simple.pset");
+  delFile("safebrowsing/test-trackwhite-simple.pset");
   delFile("testLarge.pset");
   delFile("testNoDelta.pset");
 }
 
-var allTables = "test-phish-simple,test-malware-simple,test-unwanted-simple,test-track-simple";
+var allTables = "test-phish-simple,test-malware-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple";
 
 var dbservice = Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIUrlClassifierDBService);
 var streamUpdater = Cc["@mozilla.org/url-classifier/streamupdater;1"]
                     .getService(Ci.nsIUrlClassifierStreamUpdater);
 
 
 /*
  * Builds an update from an object that looks like:
--- a/toolkit/devtools/server/actors/utils/stack.js
+++ b/toolkit/devtools/server/actors/utils/stack.js
@@ -12,85 +12,77 @@ let {Class} = require("sdk/core/heritage
  * index is used.  Users of the class can get an array of all frames
  * that have been added.
  */
 let StackFrameCache = Class({
   /**
    * Initialize this object.
    */
   initialize: function() {
-    this._framesToCounts = null;
     this._framesToIndices = null;
     this._framesToForms = null;
     this._lastEventSize = 0;
   },
 
   /**
    * Prepare to accept frames.
    */
   initFrames: function() {
-    if (this._framesToCounts) {
+    if (this._framesToIndices) {
       // The maps are already initialized.
       return;
     }
 
-    this._framesToCounts = new Map();
     this._framesToIndices = new Map();
     this._framesToForms = new Map();
     this._lastEventSize = 0;
   },
 
   /**
    * Forget all stored frames and reset to the initialized state.
    */
   clearFrames: function() {
-    this._framesToCounts.clear();
-    this._framesToCounts = null;
     this._framesToIndices.clear();
     this._framesToIndices = null;
     this._framesToForms.clear();
     this._framesToForms = null;
     this._lastEventSize = 0;
   },
 
   /**
    * Add a frame to this stack frame cache, and return the index of
    * the frame.
    */
   addFrame: function(frame) {
     this._assignFrameIndices(frame);
     this._createFrameForms(frame);
-    this._countFrame(frame);
     return this._framesToIndices.get(frame);
   },
 
   /**
    * A helper method for the memory actor.  This populates the packet
-   * object with "frames" and "counts" properties.  Each of these
+   * object with "frames" property. Each of these
    * properties will be an array indexed by frame ID.  "frames" will
-   * contain frame objects (see makeEvent) and "counts" will hold
-   * allocation counts for each frame.
+   * contain frame objects (see makeEvent).
    *
    * @param packet
    *        The packet to update.
    *
    * @returns packet
    */
   updateFramePacket: function(packet) {
     // Now that we are guaranteed to have a form for every frame, we know the
     // size the "frames" property's array must be. We use that information to
     // create dense arrays even though we populate them out of order.
     const size = this._framesToForms.size;
     packet.frames = Array(size).fill(null);
-    packet.counts = Array(size).fill(0);
 
-    // Populate the "frames" and "counts" properties.
+    // Populate the "frames" properties.
     for (let [stack, index] of this._framesToIndices) {
       packet.frames[index] = this._framesToForms.get(stack);
-      packet.counts[index] = this._framesToCounts.get(stack) || 0;
     }
 
     return packet;
   },
 
   /**
    * If any new stack frames have been added to this cache since the
    * last call to makeEvent (clearing the cache also resets the "last
@@ -183,26 +175,11 @@ let StackFrameCache = Class({
         asyncCause: frame.asyncCause
       };
       this._createFrameForms(frame.parent);
       this._createFrameForms(frame.asyncParent);
     }
 
     this._framesToForms.set(frame, form);
   },
-
-  /**
-   * Increment the allocation count for the provided frame.
-   *
-   * @param SavedFrame frame
-   *        The frame whose allocation count should be incremented.
-   */
-  _countFrame: function(frame) {
-    if (!this._framesToCounts.has(frame)) {
-      this._framesToCounts.set(frame, 1);
-    } else {
-      let count = this._framesToCounts.get(frame);
-      this._framesToCounts.set(frame, count + 1);
-    }
-  }
 });
 
 exports.StackFrameCache = StackFrameCache;
--- a/toolkit/devtools/server/tests/mochitest/chrome.ini
+++ b/toolkit/devtools/server/tests/mochitest/chrome.ini
@@ -73,17 +73,16 @@ skip-if = buildapp == 'mulet'
 [test_makeGlobalObjectReference.html]
 [test_memory.html]
 [test_memory_allocations_01.html]
 [test_memory_allocations_02.html]
 [test_memory_allocations_03.html]
 [test_memory_allocations_04.html]
 [test_memory_allocations_05.html]
 [test_memory_allocations_06.html]
-[test_memory_allocations_07.html]
 [test_memory_attach_01.html]
 [test_memory_attach_02.html]
 [test_memory_census.html]
 [test_memory_gc_01.html]
 [test_memory_gc_events.html]
 [test_preference.html]
 [test_registerActor.html]
 [test_SaveHeapSnapshot.html]
--- a/toolkit/devtools/server/tests/mochitest/test_memory_allocations_02.html
+++ b/toolkit/devtools/server/tests/mochitest/test_memory_allocations_02.html
@@ -1,12 +1,12 @@
 <!DOCTYPE HTML>
 <html>
 <!--
-Bug 1067491 - Test aggregating allocation counts.
+Bug 1132764 - Test controlling the maximum allocations log length over the RDP.
 -->
 <head>
   <meta charset="utf-8">
   <title>Memory monitoring actor test</title>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
 </head>
 <body>
@@ -15,50 +15,62 @@ Bug 1067491 - Test aggregating allocatio
 <script>
 window.onload = function() {
   SimpleTest.waitForExplicitFinish();
 
   Task.spawn(function* () {
     var { memory, client } = yield startServerAndGetSelectedTabMemory();
     yield memory.attach();
 
-    yield memory.startRecordingAllocations();
-    ok(true, "Can start recording allocations");
-
-    // Allocate some objects.
-
     var allocs = [];
-    (function allocator() {
-      for (var i = 0; i < 10; i++) {
-        allocs.push({});
-      }
-    }());
-
-    var response = yield memory.getAllocations();
-
-    yield memory.stopRecordingAllocations();
-    ok(true, "Can stop recording allocations");
-
-    // Assert that we have the 10 allocations in the `allocator` frame.
-
-    var index = 0;
-    var found = false;
-
-    for (var count of response.counts) {
-      if (count >= 10
-          && response.frames[index]
-          && response.frames[index].functionDisplayName == "allocator") {
-        found = true;
-        break;
-      }
-      index++;
+    var eventsFired = 0;
+    var intervalId = null;
+    function onAlloc () {
+      eventsFired++;
+    }
+    function startAllocating () {
+      intervalId = setInterval(() => {
+        for (var i = 100000; --i;) {
+          allocs.push(new Object());
+        }
+      }, 1);
+    }
+    function stopAllocating () {
+      clearInterval(intervalId);
     }
 
-    ok(found, "Should find the 10 allocations in the allocator frame.");
+    memory.on("allocations", onAlloc);
+
+    yield memory.startRecordingAllocations({
+      drainAllocationsTimeout: 10
+    });
+
+    yield waitUntil(() => eventsFired > 5);
+    ok(eventsFired > 5, "Some allocation events fired without allocating much via auto drain");
+    yield memory.stopRecordingAllocations();
 
+    // Set a really high auto drain timer so we can test if
+    // it fires on GC
+    eventsFired = 0;
+    var startTime = performance.now();
+    var drainTimer = 1000000;
+    yield memory.startRecordingAllocations({
+      drainAllocationsTimeout: drainTimer
+    });
+
+    startAllocating();
+    yield waitUntil(() => {
+      Cu.forceGC();
+      return eventsFired > 1;
+    });
+    stopAllocating();
+    ok(performance.now() - drainTimer < startTime, "Allocation events fired on GC before timer");
+    yield memory.stopRecordingAllocations();
+
+    memory.off("allocations", onAlloc);
     yield memory.detach();
     destroyServerAndFinish(client);
   });
 };
 </script>
 </pre>
 </body>
 </html>
deleted file mode 100644
--- a/toolkit/devtools/server/tests/mochitest/test_memory_allocations_07.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-Bug 1132764 - Test controlling the maximum allocations log length over the RDP.
--->
-<head>
-  <meta charset="utf-8">
-  <title>Memory monitoring actor test</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
-</head>
-<body>
-<pre id="test">
-<script src="memory-helpers.js" type="application/javascript;version=1.8"></script>
-<script>
-window.onload = function() {
-  SimpleTest.waitForExplicitFinish();
-
-  Task.spawn(function* () {
-    var { memory, client } = yield startServerAndGetSelectedTabMemory();
-    yield memory.attach();
-
-    var allocs = [];
-    var eventsFired = 0;
-    var intervalId = null;
-    function onAlloc () {
-      eventsFired++;
-    }
-    function startAllocating () {
-      intervalId = setInterval(() => {
-        for (var i = 100000; --i;) {
-          allocs.push(new Object());
-        }
-      }, 1);
-    }
-    function stopAllocating () {
-      clearInterval(intervalId);
-    }
-
-    memory.on("allocations", onAlloc);
-
-    yield memory.startRecordingAllocations({
-      drainAllocationsTimeout: 10
-    });
-
-    yield waitUntil(() => eventsFired > 5);
-    ok(eventsFired > 5, "Some allocation events fired without allocating much via auto drain");
-    yield memory.stopRecordingAllocations();
-
-    // Set a really high auto drain timer so we can test if
-    // it fires on GC
-    eventsFired = 0;
-    var startTime = performance.now();
-    var drainTimer = 1000000;
-    yield memory.startRecordingAllocations({
-      drainAllocationsTimeout: drainTimer
-    });
-
-    startAllocating();
-    yield waitUntil(() => {
-      Cu.forceGC();
-      return eventsFired > 1;
-    });
-    stopAllocating();
-    ok(performance.now() - drainTimer < startTime, "Allocation events fired on GC before timer");
-    yield memory.stopRecordingAllocations();
-
-    memory.off("allocations", onAlloc);
-    yield memory.detach();
-    destroyServerAndFinish(client);
-  });
-};
-</script>
-</pre>
-</body>
-</html>
--- a/toolkit/devtools/shared/memory.js
+++ b/toolkit/devtools/shared/memory.js
@@ -231,37 +231,28 @@ let Memory = exports.Memory = Class({
    *                  line: <line number for this frame>,
    *                  column: <column number for this frame>,
    *                  source: <filename string for this frame>,
    *                  functionDisplayName: <this frame's inferred function name function or null>,
    *                  parent: <index into "frames">
    *                },
    *                ...
    *              ],
-   *              counts: [
-   *                <number of allocations in frames[0]>,
-   *                <number of allocations in frames[1]>,
-   *                <number of allocations in frames[2]>,
-   *                ...
-   *              ]
    *            }
    *
    *          The timestamps' unit is microseconds since the epoch.
    *
    *          Subsequent `getAllocations` request within the same recording and
    *          tab navigation will always place the same stack frames at the same
    *          indices as previous `getAllocations` requests in the same
    *          recording. In other words, it is safe to use the index as a
    *          unique, persistent id for its frame.
    *
    *          Additionally, the root node (null) is always at index 0.
    *
-   *          Note that the allocation counts include "self" allocations only,
-   *          and don't account for allocations in child frames.
-   *
    *          We use the indices into the "frames" array to avoid repeating the
    *          description of duplicate stack frames both when listing
    *          allocations, and when many stacks share the same tail of older
    *          frames. There shouldn't be any duplicates in the "frames" array,
    *          as that would defeat the purpose of this compression trick.
    *
    *          In the future, we might want to split out a frame's "source" and
    *          "functionDisplayName" properties out the same way we have split
@@ -278,19 +269,18 @@ let Memory = exports.Memory = Class({
       // the browser console so we at least know that it occurred.
       reportException("MemoryBridge.prototype.getAllocations",
                       "Warning: allocations log overflowed and lost some data.");
     }
 
     const allocations = this.dbg.memory.drainAllocationsLog()
     const packet = {
       allocations: [],
-      allocationsTimestamps: []
+      allocationsTimestamps: [],
     };
-
     for (let { frame: stack, timestamp } of allocations) {
       if (stack && Cu.isDeadWrapper(stack)) {
         continue;
       }
 
       // Safe because SavedFrames are frozen/immutable.
       let waived = Cu.waiveXrays(stack);
 
--- a/toolkit/locales/en-US/chrome/global/textcontext.dtd
+++ b/toolkit/locales/en-US/chrome/global/textcontext.dtd
@@ -21,8 +21,17 @@
 <!ENTITY spellUndoAddToDictionary.accesskey "n">
 <!ENTITY spellCheckToggle.label "Check Spelling">
 <!ENTITY spellCheckToggle.accesskey "g">
 <!ENTITY spellNoSuggestions.label "(No Spelling Suggestions)">
 <!ENTITY spellDictionaries.label "Languages">
 <!ENTITY spellDictionaries.accesskey "l">
 
 <!ENTITY searchTextBox.clear.label "Clear">
+
+<!ENTITY fillLoginMenu.label          "Fill Login">
+<!ENTITY fillLoginMenu.accesskey      "F">
+<!ENTITY fillPasswordMenu.label       "Fill Password">
+<!ENTITY fillPasswordMenu.accesskey   "F">
+<!ENTITY fillUsernameMenu.label       "Fill Username">
+<!ENTITY fillUsernameMenu.accesskey   "F">
+<!ENTITY noLoginSuggestions.label     "(No Login Suggestions)">
+<!ENTITY viewSavedLogins.label        "View Saved Logins">
--- a/toolkit/locales/en-US/chrome/passwordmgr/passwordManager.dtd
+++ b/toolkit/locales/en-US/chrome/passwordmgr/passwordManager.dtd
@@ -17,16 +17,19 @@
 <!ENTITY      treehead.timePasswordChanged.label "Last Changed">
 <!ENTITY      treehead.timesUsed.label           "Times Used">
 
 <!ENTITY      remove.label                    "Remove">
 <!ENTITY      remove.accesskey                "R">
 <!ENTITY      removeall.label                 "Remove All">
 <!ENTITY      removeall.accesskey             "A">
 
+<!ENTITY      import.label                    "Import…">
+<!ENTITY      import.accesskey                "I">
+
 <!ENTITY      filter.label                    "Search:">
 <!ENTITY      filter.accesskey                "S">
 
 <!ENTITY      windowClose.key                 "w">
 <!ENTITY      focusSearch1.key                "f">
 <!ENTITY      focusSearch2.key                "k">
 
 <!ENTITY      copyPasswordCmd.label           "Copy Password">
--- a/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties
+++ b/toolkit/locales/en-US/chrome/passwordmgr/passwordmgr.properties
@@ -51,8 +51,15 @@ hidePasswords=Hide Passwords
 hidePasswordsAccessKey=P
 showPasswords=Show Passwords
 showPasswordsAccessKey=P
 noMasterPasswordPrompt=Are you sure you wish to show your passwords?
 removeAllPasswordsPrompt=Are you sure you wish to remove all passwords?
 removeAllPasswordsTitle=Remove all passwords
 loginsSpielAll=Passwords for the following sites are stored on your computer:
 loginsSpielFiltered=The following passwords match your search:
+# LOCALIZATION NOTE (loginHostAge):
+# This is used to show the context menu login items with their age.
+# 1st string is the username for the login, 2nd is the login's age.
+loginHostAge=%1$S (%2$S)
+# LOCALIZATION NOTE (noUsername):
+# String is used on the context menu when a login doesn't have a username.
+noUsername=No username
--- a/toolkit/modules/InlineSpellChecker.jsm
+++ b/toolkit/modules/InlineSpellChecker.jsm
@@ -424,16 +424,19 @@ var SpellCheckHelper = {
 
   // Set when over an element that otherwise would not be considered
   // "editable" but is because content editable is enabled for the document.
   CONTENTEDITABLE: 0x20,
 
   // Set when over an <input type="number"> or other non-text field.
   NUMERIC: 0x40,
 
+  // Set when over an <input type="password"> field.
+  PASSWORD: 0x80,
+
   isTargetAKeywordField(aNode, window) {
     if (!(aNode instanceof window.HTMLInputElement))
       return false;
 
     var form = aNode.form;
     if (!form || aNode.type == "password")
       return false;
 
@@ -474,16 +477,19 @@ var SpellCheckHelper = {
 
         // Allow spellchecking UI on all text and search inputs.
         if (!element.readOnly &&
             (element.type == "text" || element.type == "search")) {
           flags |= this.EDITABLE;
         }
         if (this.isTargetAKeywordField(element, window))
           flags |= this.KEYWORD;
+        if (element.type == "password") {
+          flags |= this.PASSWORD;
+        }
       }
     } else if (element instanceof window.HTMLTextAreaElement) {
       flags |= this.TEXTINPUT | this.TEXTAREA;
       if (!element.readOnly) {
         flags |= this.EDITABLE;
       }
     }