Merge mozilla-central to b2g-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 14 Mar 2014 12:43:37 +0100
changeset 190800 7cf597a3d65bddfec4d0e100147be70f8a90dbe4
parent 190799 ba7a3ccaab3962260e010484208a5b6ada7f3baf (current diff)
parent 190760 142911d6d9870866166926abbdc799db3a7d891b (diff)
child 190801 25f1f496e4d4237c28297450a9dc67b2ce60c400
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to b2g-inbound
content/media/encoder/Makefile.in
content/media/omx/mediaresourcemanager/Makefile.in
mobile/android/base/resources/drawable-hdpi/fxaccount_icon.png
mobile/android/base/resources/drawable-mdpi/fxaccount_icon.png
widget/gonk/Makefile.in
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
+@namespace svg url("http://www.w3.org/2000/svg");
 
 #main-window:not([chromehidden~="toolbar"]) {
 %ifdef XP_MACOSX
   min-width: 335px;
 %else
   min-width: 300px;
 %endif
 }
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -399,24 +399,19 @@
     <!-- Sync Panel -->
     <panel id="sync-start-panel" class="sync-panel" type="arrow" hidden="true"
            noautofocus="true" onclick="this.hidePopup();"
            flip="slide">
       <hbox class="sync-panel-outer">
         <image class="sync-panel-icon"/>
         <vbox class="sync-panel-inner">
           <description id="sync-start-panel-title"
-                       value="&syncStartPanel.heading;"/>
-          <description id="sync-start-panel-subtitle">
-#ifdef XP_UNIX
-            &syncStartPanel.subTitleUnix;
-#else
-            &syncStartPanel.subTitle;
-#endif
-          </description>
+                       value="&syncStartPanel2.heading;"/>
+          <description id="sync-start-panel-subtitle"
+                       value="&syncStartPanel2.subTitle;"/>
         </vbox>
       </hbox>
     </panel>
 
     <!-- Sync Error Panel -->
     <panel id="sync-error-panel" class="sync-panel" type="arrow" hidden="true"
            noautofocus="true" onclick="this.hidePopup();"
            flip="slide">
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -1,35 +1,25 @@
 /* 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/. */
 
 .highlighter-container {
   pointer-events: none;
 }
 
-.highlighter-outline-container {
-  overflow: hidden;
-  position: relative;
-}
-
-.highlighter-outline {
-  position: absolute;
-}
-
-.highlighter-outline[hidden] {
-  opacity: 0;
-  pointer-events: none;
-  display: -moz-box;
-}
-
-.highlighter-outline:not([disable-transitions]) {
-  transition-property: opacity, top, left, width, height;
-  transition-duration: 0.1s;
-  transition-timing-function: linear;
+/*
+ * Box model highlighter
+ */
+svg|svg.box-model-root[hidden],
+svg|line.box-model-guide-top[hidden],
+svg|line.box-model-guide-right[hidden],
+svg|line.box-model-guide-left[hidden],
+svg|line.box-model-guide-bottom[hidden] {
+  display: none;
 }
 
 /*
  * Node Infobar
  */
 .highlighter-nodeinfobar-container {
   position: relative;
 }
@@ -40,23 +30,16 @@
 }
 
 .highlighter-nodeinfobar-positioner[hidden] {
   opacity: 0;
   pointer-events: none;
   display: -moz-box;
 }
 
-.highlighter-nodeinfobar-positioner:not([disable-transitions]),
-.highlighter-nodeinfobar-positioner[disable-transitions][force-transitions] {
-  transition-property: transform, opacity, top, left;
-  transition-duration: 0.1s;
-  transition-timing-function: linear;
-}
-
 .highlighter-nodeinfobar-text {
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
   direction: ltr;
 }
 
 html|*.highlighter-nodeinfobar-id,
--- a/browser/base/content/socialmarks.xml
+++ b/browser/base/content/socialmarks.xml
@@ -215,20 +215,21 @@
                               CustomizableUI.AREA_PANEL);
         } else {
           let anchor = document.getAnonymousElementByAttribute(this, "class", "toolbarbutton-icon");
           panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
           this.setAttribute("open", "true");
         }
         if (aResetOnClose) {
           let evName = inMenuPanel ? "ViewHiding": "popuphidden";
-          panel.addEventListener(evName, function _hidden() {
+          let _hidden = () => {
             panel.removeEventListener(evName, _hidden);
             this.update();
-          }.bind(this), false);
+          };
+          panel.addEventListener(evName, _hidden, false);
         }
          ]]></body>
        </method>
 
       <method name="markCurrentPage">
         <parameter name="aOpenPanel"/>
         <body><![CDATA[
         // we always set the src on click if it has not been set for this tab,
@@ -277,22 +278,23 @@
         // showing as well as after load
         let sizeSocialPanelToContent = Cu.import("resource:///modules/Social.jsm", {}).sizeSocialPanelToContent;
         if (!this._loading && this.contentDocument &&
             this.contentDocument.readyState == "complete") {
           this.dispatchPanelEvent("socialFrameShow");
           if (!this.inMenuPanel)
             sizeSocialPanelToContent(this.panel, this.content);
         } else {
-          this.content.addEventListener("load", function panelBrowserOnload(e) {
+          let panelBrowserOnload = (e) => {
             this.content.removeEventListener("load", panelBrowserOnload, true);
             this.dispatchPanelEvent("socialFrameShow");
             if (!this.inMenuPanel)
               sizeSocialPanelToContent(this.panel, this.content);
-          }.bind(this), true);
+          };
+          this.content.addEventListener("load", panelBrowserOnload, true);
         }
         ]]></body>
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
         if (aEvent.eventPhase != aEvent.BUBBLING_PHASE)
--- a/browser/base/content/test/general/domplate_test.js
+++ b/browser/base/content/test/general/domplate_test.js
@@ -41,11 +41,11 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
-  content.location = "data:text/html,basic domplate tests";
+  content.location = "data:text/html;charset=utf-8,domplate_test.js";
 }
 
--- a/browser/base/content/test/general/mochitest.ini
+++ b/browser/base/content/test/general/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 support-files =
   audio.ogg
   bug364677-data.xml
   bug364677-data.xml^headers^
   bug395533-data.txt
   contextmenu_common.js
   ctxmenu-image.png
   feed_discovery.html
--- a/browser/components/feeds/test/mochitest.ini
+++ b/browser/components/feeds/test/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 support-files =
   bug368464-data.xml
   bug408328-data.xml
   bug436801-data.xml
   bug494328-data.xml
   bug589543-data.xml
   valid-feed.xml
   valid-unsniffable-feed.xml
--- a/browser/devtools/app-manager/test/head.js
+++ b/browser/devtools/app-manager/test/head.js
@@ -14,16 +14,21 @@ const {AppProjects} = require("devtools/
 
 const APP_MANAGER_URL = "about:app-manager";
 const TEST_BASE =
   "chrome://mochitests/content/browser/browser/devtools/app-manager/test/";
 const HOSTED_APP_MANIFEST = TEST_BASE + "hosted_app.manifest";
 
 const PACKAGED_APP_DIR_PATH = getTestFilePath(".");
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 function addTab(url, targetWindow = window) {
   info("Adding tab: " + url);
 
   let deferred = promise.defer();
   let targetBrowser = targetWindow.gBrowser;
 
   targetWindow.focus();
   let tab = targetBrowser.selectedTab = targetBrowser.addTab(url);
--- a/browser/devtools/commandline/test/head.js
+++ b/browser/devtools/commandline/test/head.js
@@ -5,16 +5,21 @@
 const TEST_BASE_HTTP = "http://example.com/browser/browser/devtools/commandline/test/";
 const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/commandline/test/";
 
 // Import the GCLI test helper
 let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
 Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
 Services.scriptloader.loadSubScript(testDir + "/mockCommands.js", this);
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 function whenDelayedStartupFinished(aWindow, aCallback) {
   Services.obs.addObserver(function observer(aSubject, aTopic) {
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
       executeSoon(aCallback);
     }
   }, "browser-delayed-startup-finished", false);
 }
--- a/browser/devtools/debugger/test/browser_dbg_listtabs-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_listtabs-02.js
@@ -40,17 +40,17 @@ function test() {
     .then(addTabC)
     .then(testTabC)
     .then(removeTabC)
     .then(testNewWindow)
     .then(removeNewWindow)
     .then(testWindowClosed)
     .then(removeTabB)
     .then(checkSingleTab)
-    .then(finish);
+    .then(finishUp);
 }
 
 function checkSingleTab() {
   return gTabList.getList().then(aTabActors => {
     is(aTabActors.length, 1, "initial tab list: contains initial tab");
     gFirstActor = aTabActors[0];
     is(gFirstActor.url, "about:blank", "initial tab list: initial tab URL is 'about:blank'");
     is(gFirstActor.title, "New Tab", "initial tab list: initial tab title is 'New Tab'");
@@ -203,8 +203,13 @@ function removeTabB() {
 
     // Let the actor's TabClose handler finish first.
     executeSoon(deferred.resolve);
   }, false);
 
   removeTab(gTabB);
   return deferred.promise;
 }
+
+function finishUp() {
+  gTabList = gFirstActor = gActorA = gTabA = gTabB = gTabC = gNewWindow = null;
+  finish();
+}
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-frame-with.js
@@ -202,9 +202,10 @@ function testFunctionScope() {
     "Should have the right token class for 'foo'.");
 }
 
 registerCleanupFunction(function() {
   gTab = null;
   gDebuggee = null;
   gPanel = null;
   gDebugger = null;
+  gVariables = null;
 });
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -22,16 +22,21 @@ let { BrowserToolboxProcess } = Cu.impor
 let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
 let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
 let { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
 let TargetFactory = devtools.TargetFactory;
 let Toolbox = devtools.Toolbox;
 
 const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 // All tests are asynchronous.
 waitForExplicitFinish();
 
 registerCleanupFunction(function() {
   info("finish() was called, cleaning up...");
   Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
 
   // Properly shut down the server to avoid memory leaks.
--- a/browser/devtools/fontinspector/test/browser_fontinspector.js
+++ b/browser/devtools/fontinspector/test/browser_fontinspector.js
@@ -11,16 +11,21 @@ let DOMUtils = Cc["@mozilla.org/inspecto
 function test() {
   waitForExplicitFinish();
 
   let doc;
   let view;
   let viewDoc;
   let inspector;
 
+  gDevTools.testing = true;
+  SimpleTest.registerCleanupFunction(() => {
+    gDevTools.testing = false;
+  });
+
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onload() {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     doc = content.document;
     waitForFocus(setupTest, content);
   }, true);
 
   content.location = "http://mochi.test:8888/browser/browser/devtools/fontinspector/test/browser_fontinspector.html";
--- a/browser/devtools/framework/gDevTools.jsm
+++ b/browser/devtools/framework/gDevTools.jsm
@@ -27,24 +27,49 @@ const MAX_ORDINAL = 99;
 this.DevTools = function DevTools() {
   this._tools = new Map();     // Map<toolId, tool>
   this._toolboxes = new Map(); // Map<target, toolbox>
 
   // destroy() is an observer's handler so we need to preserve context.
   this.destroy = this.destroy.bind(this);
   this._teardown = this._teardown.bind(this);
 
+  this._testing = false;
+
   EventEmitter.decorate(this);
 
   Services.obs.addObserver(this._teardown, "devtools-unloaded", false);
   Services.obs.addObserver(this.destroy, "quit-application", false);
 }
 
 DevTools.prototype = {
   /**
+   * When the testing flag is set we take appropriate action to prevent race
+   * conditions in our testing environment. This means setting
+   * dom.send_after_paint_to_content to false to prevent infinite MozAfterPaint
+   * loops and not autohiding the highlighter.
+   */
+  get testing() {
+    return this._testing;
+  },
+
+  set testing(state) {
+    this._testing = state;
+
+    if (state) {
+      // dom.send_after_paint_to_content is set to true (non-default) in
+      // testing/profiles/prefs_general.js so lets set it to the same as it is
+      // in a default browser profile for the duration of the test.
+      Services.prefs.setBoolPref("dom.send_after_paint_to_content", false);
+    } else {
+      Services.prefs.setBoolPref("dom.send_after_paint_to_content", true);
+    }
+  },
+
+  /**
    * Register a new developer tool.
    *
    * A definition is a light object that holds different information about a
    * developer tool. This object is not supposed to have any operational code.
    * See it as a "manifest".
    * The only actual code lives in the build() function, which will be used to
    * start an instance of this tool.
    *
--- a/browser/devtools/framework/selection.js
+++ b/browser/devtools/framework/selection.js
@@ -155,30 +155,32 @@ Selection.prototype = {
     if (this.isNode()) {
       return this.node.ownerDocument;
     }
     return null;
   },
 
   setNodeFront: function(value, reason="unknown") {
     this.reason = reason;
-    if (value !== this._nodeFront) {
-      let rawValue = null;
-      if (value && value.isLocal_toBeDeprecated()) {
-        rawValue = value.rawNode();
-      }
-      this.emit("before-new-node", rawValue, reason);
-      this.emit("before-new-node-front", value, reason);
-      let previousNode = this._node;
-      let previousFront = this._nodeFront;
-      this._node = rawValue;
-      this._nodeFront = value;
-      this.emit("new-node", previousNode, this.reason);
-      this.emit("new-node-front", value, this.reason);
+
+    // We used to return here if the node had not changed but we now need to
+    // set the node even if it is already set otherwise it is not possible to
+    // e.g. highlight the same node twice.
+    let rawValue = null;
+    if (value && value.isLocal_toBeDeprecated()) {
+      rawValue = value.rawNode();
     }
+    this.emit("before-new-node", rawValue, reason);
+    this.emit("before-new-node-front", value, reason);
+    let previousNode = this._node;
+    let previousFront = this._nodeFront;
+    this._node = rawValue;
+    this._nodeFront = value;
+    this.emit("new-node", previousNode, this.reason);
+    this.emit("new-node-front", value, this.reason);
   },
 
   get documentFront() {
     return this._walker.document(this._nodeFront);
   },
 
   get nodeFront() {
     return this._nodeFront;
--- a/browser/devtools/framework/test/head.js
+++ b/browser/devtools/framework/test/head.js
@@ -8,16 +8,21 @@ let tempScope = {};
 Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
 let console = tempScope.console;
 Components.utils.import("resource://gre/modules/commonjs/sdk/core/promise.js", tempScope);
 let promise = tempScope.Promise;
 
 let {devtools} = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
 let TargetFactory = devtools.TargetFactory;
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 /**
  * Open a new tab at a URL and call a callback on load
  */
 function addTab(aURL, aCallback)
 {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -68,16 +68,18 @@ function Toolbox(target, selectedTool, h
   this._telemetry = new Telemetry();
 
   this._toolRegistered = this._toolRegistered.bind(this);
   this._toolUnregistered = this._toolUnregistered.bind(this);
   this._refreshHostTitle = this._refreshHostTitle.bind(this);
   this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this)
   this.destroy = this.destroy.bind(this);
   this.highlighterUtils = new ToolboxHighlighterUtils(this);
+  this._highlighterReady = this._highlighterReady.bind(this);
+  this._highlighterHidden = this._highlighterHidden.bind(this);
 
   this._target.on("close", this.destroy);
 
   if (!hostType) {
     hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST);
   }
   if (!selectedTool) {
     selectedTool = Services.prefs.getCharPref(this._prefs.LAST_TOOL);
@@ -1092,55 +1094,72 @@ Toolbox.prototype = {
    * Returns a promise that resolves when the fronts are initialized
    */
   initInspector: function() {
     if (!this._initInspector) {
       this._initInspector = Task.spawn(function*() {
         this._inspector = InspectorFront(this._target.client, this._target.form);
         this._walker = yield this._inspector.getWalker();
         this._selection = new Selection(this._walker);
+
         if (this.highlighterUtils.isRemoteHighlightable) {
-          this._highlighter = yield this._inspector.getHighlighter();
+          let autohide = !gDevTools.testing;
+
+          this.walker.on("highlighter-ready", this._highlighterReady);
+          this.walker.on("highlighter-hide", this._highlighterHidden);
+
+          this._highlighter = yield this._inspector.getHighlighter(autohide);
         }
       }.bind(this));
     }
     return this._initInspector;
   },
 
   /**
    * Destroy the inspector/walker/selection fronts
    * Returns a promise that resolves when the fronts are destroyed
    */
   destroyInspector: function() {
+    if (this._destroying) {
+      return this._destroying;
+    }
+
     if (!this._inspector) {
       return promise.resolve();
     }
 
     let outstanding = () => {
       return Task.spawn(function*() {
         yield this.highlighterUtils.stopPicker();
         yield this._inspector.destroy();
         if (this._highlighter) {
           yield this._highlighter.destroy();
         }
         if (this._selection) {
           this._selection.destroy();
         }
 
+        if (this.walker) {
+          this.walker.off("highlighter-ready", this._highlighterReady);
+          this.walker.off("highlighter-hide", this._highlighterHidden);
+        }
+
         this._inspector = null;
         this._highlighter = null;
         this._selection = null;
         this._walker = null;
       }.bind(this));
     };
 
     // Releasing the walker (if it has been created)
     // This can fail, but in any case, we want to continue destroying the
     // inspector/highlighter/selection
-    let walker = this._walker ? this._walker.release() : promise.resolve();
+    let walker = (this._destroying = this._walker) ?
+                 this._walker.release() :
+                 promise.resolve();
     return walker.then(outstanding, outstanding);
   },
 
   /**
    * Get the toolbox's notification box
    *
    * @return The notification box element.
    */
@@ -1219,17 +1238,25 @@ Toolbox.prototype = {
       return target.destroy();
     }).then(() => {
       this.emit("destroyed");
       // Free _host after the call to destroyed in order to let a chance
       // to destroyed listeners to still query toolbox attributes
       this._host = null;
       this._toolPanels.clear();
     }).then(null, console.error);
-  }
+  },
+
+  _highlighterReady: function() {
+    this.emit("highlighter-ready");
+  },
+
+  _highlighterHidden: function() {
+    this.emit("highlighter-hide");
+  },
 };
 
 /**
  * The ToolboxHighlighterUtils is what you should use for anything related to
  * node highlighting and picking.
  * It encapsulates the logic to connecting to the HighlighterActor.
  */
 function ToolboxHighlighterUtils(toolbox) {
@@ -1279,39 +1306,40 @@ ToolboxHighlighterUtils.prototype = {
   startPicker: function() {
     if (this._isPicking) {
       return promise.resolve();
     }
 
     let deferred = promise.defer();
 
     let done = () => {
+      this._isPicking = true;
       this.toolbox.emit("picker-started");
       this.toolbox.on("select", this.stopPicker);
       deferred.resolve();
     };
 
     promise.all([
       this.toolbox.initInspector(),
       this.toolbox.selectTool("inspector")
     ]).then(() => {
-      this._isPicking = true;
       this.toolbox._pickerButton.setAttribute("checked", "true");
 
       if (this.isRemoteHighlightable) {
-        this.toolbox.highlighter.pick().then(done);
-
         this.toolbox.walker.on("picker-node-hovered", this._onPickerNodeHovered);
         this.toolbox.walker.on("picker-node-picked", this._onPickerNodePicked);
+
+        this.toolbox.highlighter.pick().then(done);
       } else {
-        this.toolbox.walker.pick().then(node => {
-          this.toolbox.selection.setNodeFront(node, "picker-node-picked");
-          this.stopPicker();
+        return this.toolbox.walker.pick().then(node => {
+          this.toolbox.selection.setNodeFront(node, "picker-node-picked").then(() => {
+            this.stopPicker();
+            done();
+          });
         });
-        done();
       }
     });
 
     return deferred.promise;
   },
 
   /**
    * Stop the element picker
@@ -1399,21 +1427,26 @@ ToolboxHighlighterUtils.prototype = {
       return this.toolbox.walker.getNodeActorFromObjectActor(grip.actor);
     });
   },
 
   /**
    * Hide the highlighter.
    * @return a promise that resolves when the highlighter is hidden
    */
-  unhighlight: function() {
+  unhighlight: function(forceHide=false) {
     if (this.isRemoteHighlightable) {
       // If the remote highlighter exists on the target, use it
       return this.toolbox.initInspector().then(() => {
-        return this.toolbox.highlighter.hideBoxModel();
+        let autohide = forceHide || !gDevTools.testing;
+
+        if (autohide) {
+          return this.toolbox.highlighter.hideBoxModel();
+        }
+        return promise.resolve();
       });
     } else {
       // If not, no need to unhighlight as the older highlight method uses a
       // setTimeout to hide itself
       return promise.resolve();
     }
   }
 };
--- a/browser/devtools/inspector/breadcrumbs.js
+++ b/browser/devtools/inspector/breadcrumbs.js
@@ -694,13 +694,13 @@ HTMLBreadcrumbs.prototype = {
       this.scroll();
       this.inspector.emit("breadcrumbs-updated", this.selection.nodeFront);
       doneUpdating();
     }).then(null, err => {
       doneUpdating(this.selection.nodeFront);
       this.selectionGuardEnd(err);
     });
   }
-}
+};
 
 XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
   return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
 });
--- a/browser/devtools/inspector/test/browser_inspector_basic_highlighter.js
+++ b/browser/devtools/inspector/test/browser_inspector_basic_highlighter.js
@@ -13,72 +13,50 @@ function test() {
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onload() {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     doc = content.document;
     waitForFocus(setupTest, content);
   }, true);
 
-  content.location = "data:text/html,<h1>foo</h1><h2>bar</h2>";
+  content.location = "data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>";
 
   function setupTest() {
     openInspector((aInspector, aToolbox) => {
       toolbox = aToolbox;
       inspector = aInspector;
-      inspector.selection.setNode(doc.querySelector("h2"), null);
-      inspector.once("inspector-updated", runTests);
+      inspector.selection.setNode(doc.querySelector("span"), "test");
+      inspector.toolbox.once("highlighter-ready", runTests);
     });
   }
 
-  function runTests(aInspector) {
-    getHighlighterOutline().setAttribute("disable-transitions", "true");
+  function runTests() {
     Task.spawn(function() {
       yield hoverH1InMarkupView();
       yield assertH1Highlighted();
-      yield mouseLeaveMarkupView();
-      yield assertNoNodeHighlighted();
 
       finishUp();
     }).then(null, Cu.reportError);
   }
 
   function hoverH1InMarkupView() {
     let deferred = promise.defer();
+    let container = getContainerForRawNode(inspector.markup, doc.querySelector("h1"));
 
-    let container = getContainerForRawNode(inspector.markup, doc.querySelector("h1"));
-    EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
-      inspector.markup.doc.defaultView);
-    inspector.toolbox.once("node-highlight", deferred.resolve);
+    inspector.toolbox.once("highlighter-ready", deferred.resolve);
+    EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousemove"},
+                                       inspector.markup.doc.defaultView);
 
     return deferred.promise;
   }
 
   function assertH1Highlighted() {
     ok(isHighlighting(), "The highlighter is shown on a markup container hover");
     is(getHighlitNode(), doc.querySelector("h1"), "The highlighter highlights the right node");
-    return promise.resolve();
-  }
-
-  function mouseLeaveMarkupView() {
-    let deferred = promise.defer();
-
-    // Find another element to mouseover over in order to leave the markup-view
-    let btn = toolbox.doc.querySelector(".toolbox-dock-button");
-
-    EventUtils.synthesizeMouse(btn, 2, 2, {type: "mousemove"},
-      toolbox.doc.defaultView);
-    executeSoon(deferred.resolve);
-
-    return deferred.promise;
-  }
-
-  function assertNoNodeHighlighted() {
-    ok(!isHighlighting(), "After the mouse left the markup view, the highlighter is hidden");
-    return promise.resolve();
   }
 
   function finishUp() {
     inspector = doc = toolbox = null;
     gBrowser.removeCurrentTab();
     finish();
   }
 }
--- a/browser/devtools/inspector/test/browser_inspector_breadcrumbs.js
+++ b/browser/devtools/inspector/test/browser_inspector_breadcrumbs.js
@@ -86,13 +86,13 @@ function test()
 
     let checkedButton = container.querySelector("button[checked]");
     let labelId = checkedButton.querySelector(".breadcrumbs-widget-item-id");
     let id = inspector.selection.node.id;
     is(labelId.textContent, "#" + id, "Node " + cursor + ": selection matches");
   }
 
   function finishUp() {
-    doc = nodes = null;
+    doc = nodes = inspector = null;
     gBrowser.removeCurrentTab();
     finish();
   }
 }
--- a/browser/devtools/inspector/test/browser_inspector_bug_650804_search.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_650804_search.js
@@ -47,17 +47,18 @@ function test()
   ];
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onload() {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     waitForFocus(setupTest, content);
   }, true);
 
-  content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_bug_650804_search.html";
+  content.location = "http://mochi.test:8888/browser/browser/devtools/" +
+                     "inspector/test/browser_inspector_bug_650804_search.html";
 
   function $(id) {
     if (id == null) return null;
     return content.document.getElementById(id);
   }
 
   function setupTest()
   {
--- a/browser/devtools/inspector/test/browser_inspector_bug_674871.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_674871.js
@@ -45,51 +45,54 @@ function test()
     iframeNode = doc.querySelector("iframe");
     iframeBodyNode = iframeNode.contentDocument.querySelector("body");
     ok(iframeNode, "we have the iframe node");
     ok(iframeBodyNode, "we have the body node");
     openInspector(aInspector => {
       inspector = aInspector;
       // Make sure the highlighter is shown so we can disable transitions
       inspector.toolbox.highlighter.showBoxModel(getNodeFront(doc.body)).then(() => {
-        getHighlighterOutline().setAttribute("disable-transitions", "true");
         runTests();
       });
     });
   }
 
   function runTests()
   {
     inspector.toolbox.highlighterUtils.startPicker().then(() => {
       moveMouseOver(iframeNode, 1, 1, isTheIframeHighlighted);
     });
   }
 
   function isTheIframeHighlighted()
   {
-    let outlineRect = getHighlighterOutlineRect();
-    let iframeRect = iframeNode.getBoundingClientRect();
-    for (let dim of ["width", "height", "top", "left"]) {
-      is(Math.floor(outlineRect[dim]), Math.floor(iframeRect[dim]),
-         "Outline dimension is correct " + outlineRect[dim]);
-    }
+    let {p1, p2, p3, p4} = getBoxModelStatus().border.points;
+    let {top, right, bottom, left} = iframeNode.getBoundingClientRect();
+
+    is(top, p1.y, "iframeRect.top === boxModelStatus.p1.y");
+    is(top, p2.y, "iframeRect.top === boxModelStatus.p2.y");
+    is(right, p2.x, "iframeRect.right === boxModelStatus.p2.x");
+    is(right, p3.x, "iframeRect.right === boxModelStatus.p3.x");
+    is(bottom, p3.y, "iframeRect.bottom === boxModelStatus.p3.y");
+    is(bottom, p4.y, "iframeRect.bottom === boxModelStatus.p4.y");
+    is(left, p1.x, "iframeRect.left === boxModelStatus.p1.x");
+    is(left, p4.x, "iframeRect.left === boxModelStatus.p4.x");
 
     iframeNode.style.marginBottom = doc.defaultView.innerHeight + "px";
     doc.defaultView.scrollBy(0, 40);
 
     moveMouseOver(iframeNode, 40, 40, isTheIframeContentHighlighted);
   }
 
   function isTheIframeContentHighlighted()
   {
     is(getHighlitNode(), iframeBodyNode, "highlighter shows the right node");
 
-    // 184 == 200 + 11(border) + 13(padding) - 40(scroll)
-    let outlineRect = getHighlighterOutlineRect();
-    is(outlineRect.height, 184, "highlighter height");
+    let outlineRect = getSimpleBorderRect();
+    is(outlineRect.height, 200, "highlighter height");
 
     inspector.toolbox.highlighterUtils.stopPicker().then(() => {
       let target = TargetFactory.forTab(gBrowser.selectedTab);
       gDevTools.closeToolbox(target);
       finishUp();
     });
   }
 
--- a/browser/devtools/inspector/test/browser_inspector_bug_699308_iframe_navigation.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_699308_iframe_navigation.js
@@ -13,49 +13,44 @@ function test() {
       runInspectorTests();
     });
   }
 
   function showHighlighter(cb) {
     inspector.toolbox.highlighterUtils.startPicker().then(() => {
       EventUtils.synthesizeMouse(content.document.body, 1, 1,
         {type: "mousemove"}, content);
-      inspector.toolbox.once("picker-node-hovered", () => {
-        executeSoon(() => {
-          getHighlighterOutline().setAttribute("disable-transitions", "true");
-          cb();
-        });
-      });
+      inspector.toolbox.once("highlighter-ready", cb);
     });
   }
 
   function runInspectorTests() {
     iframe = content.document.querySelector("iframe");
     ok(iframe, "found the iframe element");
 
     showHighlighter(() => {
       ok(isHighlighting(), "Inspector is highlighting");
 
       iframe.addEventListener("load", onIframeLoad, false);
-
-      executeSoon(function() {
+      executeSoon(() => {
         iframe.contentWindow.location = "javascript:location.reload()";
       });
     });
   }
 
   function onIframeLoad() {
     if (++iframeLoads != 2) {
       executeSoon(function() {
         iframe.contentWindow.location = "javascript:location.reload()";
       });
       return;
     }
 
     iframe.removeEventListener("load", onIframeLoad, false);
+    info("Finished reloading iframe and inspector updated");
 
     ok(isHighlighting(), "Inspector is highlighting after iframe nav");
 
     checksAfterLoads = true;
 
     finishTest();
   }
 
@@ -73,11 +68,12 @@ function test() {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onBrowserLoad() {
     gBrowser.selectedBrowser.removeEventListener("load", onBrowserLoad, true);
     waitForFocus(startTest, content);
   }, true);
 
-  content.location = "data:text/html,<p>bug 699308 - test iframe navigation" +
-    "<iframe src='data:text/html,hello world'></iframe>";
+  content.location = "data:text/html;charset=utf-8," +
+                     "<p>bug 699308 - test iframe navigation</p>" +
+                     "<iframe src='data:text/html;charset=utf-8,hello world'></iframe>";
 }
--- a/browser/devtools/inspector/test/browser_inspector_bug_958456_highlight_comments.js
+++ b/browser/devtools/inspector/test/browser_inspector_bug_958456_highlight_comments.js
@@ -72,17 +72,16 @@ function finishTest() {
   finish();
 }
 
 function prepareHighlighter() {
   // Make sure the highlighter doesn't have transitions enabled
   let deferred = promise.defer();
   inspector.selection.setNode(doc.querySelector("p"), null);
   inspector.once("inspector-updated", () => {
-    getHighlighterOutline().setAttribute("disable-transitions", "true");
     deferred.resolve();
   });
   return deferred.promise;
 }
 
 function hoverContainer(container) {
   let deferred = promise.defer();
   EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
--- a/browser/devtools/inspector/test/browser_inspector_changes.js
+++ b/browser/devtools/inspector/test/browser_inspector_changes.js
@@ -145,10 +145,10 @@ function test() {
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
-  content.location = "data:text/html,basic tests for inspector";
+  content.location = "data:text/html;charset=utf-8,browser_inspector_changes.js";
 }
--- a/browser/devtools/inspector/test/browser_inspector_highlighter.js
+++ b/browser/devtools/inspector/test/browser_inspector_highlighter.js
@@ -46,71 +46,65 @@ function createDocument() {
   doc.body.appendChild(div);
   doc.body.appendChild(div2);
   doc.body.appendChild(div3);
 
   openInspector(aInspector => {
     inspector = aInspector;
     inspector.selection.setNode(div, null);
     inspector.once("inspector-updated", () => {
-      getHighlighterOutline().setAttribute("disable-transitions", "true");
       inspector.toolbox.highlighterUtils.startPicker().then(testMouseOverH1Highlights);
     });
   });
 }
 
 function testMouseOverH1Highlights() {
-  inspector.toolbox.once("picker-node-hovered", () => {
+  inspector.toolbox.once("highlighter-ready", () => {
     ok(isHighlighting(), "Highlighter is shown");
     is(getHighlitNode(), h1, "Highlighter's outline correspond to the selected node");
-    testOutlineDimensions();
+    testBoxModelDimensions();
   });
 
   EventUtils.synthesizeMouse(h1, 2, 2, {type: "mousemove"}, content);
 }
 
-function testOutlineDimensions() {
+function testBoxModelDimensions() {
   let h1Dims = h1.getBoundingClientRect();
-  let h1Width = h1Dims.width;
-  let h1Height = h1Dims.height;
+  let h1Width = Math.ceil(h1Dims.width);
+  let h1Height = Math.ceil(h1Dims.height);
 
-  let outlineDims = getHighlighterOutlineRect();
-  let outlineWidth = outlineDims.width;
-  let outlineHeight = outlineDims.height;
+  let outlineDims = getSimpleBorderRect();
+  let outlineWidth = Math.ceil(outlineDims.width);
+  let outlineHeight = Math.ceil(outlineDims.height);
 
   // Disabled due to bug 716245
   is(outlineWidth, h1Width, "outline width matches dimensions of element (no zoom)");
   is(outlineHeight, h1Height, "outline height matches dimensions of element (no zoom)");
 
   // zoom the page by a factor of 2
   let contentViewer = gBrowser.selectedBrowser.docShell.contentViewer
                              .QueryInterface(Ci.nsIMarkupDocumentViewer);
   contentViewer.fullZoom = 2;
 
-  // We wait at least 500ms to make sure the highlighter is not "mutting" the
-  // resize event
-
-  window.setTimeout(function() {
-    // simulate the zoomed dimensions of the div element
-    let h1Dims = h1.getBoundingClientRect();
-    // There seems to be some very minor differences in the floats, so let's
-    // floor the values
-    let h1Width = Math.floor(h1Dims.width * contentViewer.fullZoom);
-    let h1Height = Math.floor(h1Dims.height * contentViewer.fullZoom);
+  // simulate the zoomed dimensions of the div element
+  let h1Dims = h1.getBoundingClientRect();
+  // There seems to be some very minor differences in the floats, so let's
+  // floor the values
+  let h1Width = Math.floor(h1Dims.width * contentViewer.fullZoom);
+  let h1Height = Math.floor(h1Dims.height * contentViewer.fullZoom);
 
-    let outlineDims = getHighlighterOutlineRect();
-    let outlineWidth = Math.floor(outlineDims.width);
-    let outlineHeight = Math.floor(outlineDims.height);
+  let outlineDims = getSimpleBorderRect();
+  let outlineWidth = Math.floor(outlineDims.width);
+  let outlineHeight = Math.floor(outlineDims.height);
 
-    // Disabled due to bug 716245
-    is(outlineWidth, h1Width, "outline width matches dimensions of element (zoomed)");
-    is(outlineHeight, h1Height, "outline height matches dimensions of element (zoomed)");
+  is(outlineWidth, h1Width, "outline width matches dimensions of element (zoomed)");
 
-    executeSoon(finishUp);
-  }, 500);
+  is(outlineHeight, h1Height, "outline height matches dimensions of element (zoomed)");
+
+  executeSoon(finishUp);
 }
 
 function finishUp() {
   inspector.toolbox.highlighterUtils.stopPicker().then(() => {
     doc = h1 = inspector = null;
     let target = TargetFactory.forTab(gBrowser.selectedTab);
     gDevTools.closeToolbox(target);
     gBrowser.removeCurrentTab();
@@ -122,10 +116,10 @@ function test() {
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
-  content.location = "data:text/html,basic tests for inspector";
+  content.location = "data:text/html;charset=utf-8,browser_inspector_highlighter.js";
 }
--- a/browser/devtools/inspector/test/browser_inspector_iframeTest.js
+++ b/browser/devtools/inspector/test/browser_inspector_iframeTest.js
@@ -26,54 +26,54 @@ function createDocument() {
     iframe2 = iframe1.contentDocument.createElement('iframe');
 
     iframe2.addEventListener('load', function () {
       iframe2.removeEventListener("load", arguments.callee, false);
 
       div2 = iframe2.contentDocument.createElement('div');
       div2.textContent = 'nested div';
       iframe2.contentDocument.body.appendChild(div2);
+
       // Open the inspector, start the picker mode, and start the tests
       openInspector(aInspector => {
         inspector = aInspector;
-        inspector.toolbox.highlighterUtils.startPicker().then(runTests);
+        inspector.once("inspector-updated", () => {
+          inspector.toolbox.highlighterUtils.startPicker().then(runTests);
+        });
       });
     }, false);
 
     iframe2.src = 'data:text/html,nested iframe';
     iframe1.contentDocument.body.appendChild(iframe2);
   }, false);
 
   iframe1.src = 'data:text/html,little iframe';
   doc.body.appendChild(iframe1);
 }
 
 function moveMouseOver(aElement, cb) {
-  inspector.toolbox.once("picker-node-hovered", () => {
-    executeSoon(cb);
-  });
+  inspector.toolbox.once("picker-node-hovered", cb);
   EventUtils.synthesizeMouseAtCenter(aElement, {type: "mousemove"},
     aElement.ownerDocument.defaultView);
 }
 
 function runTests() {
   testDiv1Highlighter();
 }
 
 function testDiv1Highlighter() {
   moveMouseOver(div1, () => {
-    getHighlighterOutline().setAttribute("disable-transitions", "true");
-    is(getHighlitNode(), div1, "highlighter matches selection");
+    is(getHighlitNode(), div1, "highlighter matches selection of div1");
     testDiv2Highlighter();
   });
 }
 
 function testDiv2Highlighter() {
   moveMouseOver(div2, () => {
-    is(getHighlitNode(), div2, "highlighter matches selection");
+    is(getHighlitNode(), div2, "highlighter matches selection of div2");
     selectRoot();
   });
 }
 
 function selectRoot() {
   // Select the root document element to clear the breadcrumbs.
   inspector.selection.setNode(doc.documentElement, null);
   inspector.once("inspector-updated", selectIframe);
--- a/browser/devtools/inspector/test/browser_inspector_initialization.js
+++ b/browser/devtools/inspector/test/browser_inspector_initialization.js
@@ -132,10 +132,10 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
-  content.location = "data:text/html,basic tests for inspector";
+  content.location = "data:text/html;charset=utf-8,browser_inspector_initialization.js";
 }
--- a/browser/devtools/inspector/test/browser_inspector_invalidate.js
+++ b/browser/devtools/inspector/test/browser_inspector_invalidate.js
@@ -8,34 +8,34 @@ function test() {
 
   function createDocument() {
     div = doc.createElement("div");
     div.setAttribute("style", "width: 100px; height: 100px; background:yellow;");
     doc.body.appendChild(div);
 
     openInspector(aInspector => {
       inspector = aInspector;
-      inspector.toolbox.highlighter.showBoxModel(getNodeFront(div)).then(runTest);
+      inspector.once("inspector-updated", () => {
+        inspector.toolbox.highlighter.showBoxModel(getNodeFront(div)).then(runTest);
+      });
     });
   }
 
   function runTest() {
-    let outline = getHighlighterOutline();
-    is(outline.style.width, "100px", "outline has the right width");
+    let rect = getSimpleBorderRect();
+    is(rect.width, 100, "outline has the right width");
 
     div.style.width = "200px";
-    function pollTest() {
-      if (outline.style.width == "100px") {
-        setTimeout(pollTest, 10);
-        return;
-      }
-      is(outline.style.width, "200px", "outline updated");
-      finishUp();
-    }
-    setTimeout(pollTest, 10);
+    inspector.toolbox.once("highlighter-ready", testRectWidth);
+  }
+
+  function testRectWidth() {
+    let rect = getSimpleBorderRect();
+    is(rect.width, 200, "outline updated");
+    finishUp();
   }
 
   function finishUp() {
     inspector.toolbox.highlighter.hideBoxModel().then(() => {
       doc = div = inspector = null;
       gBrowser.removeCurrentTab();
       finish();
     });
@@ -44,10 +44,10 @@ function test() {
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
-  content.location = "data:text/html,basic tests for inspector";
+  content.location = "data:text/html;charset=utf-8,browser_inspector_invalidate.js";
 }
--- a/browser/devtools/inspector/test/browser_inspector_scrolling.js
+++ b/browser/devtools/inspector/test/browser_inspector_scrolling.js
@@ -28,44 +28,44 @@ function createDocument()
   iframe.src = "data:text/html,foo bar";
   doc.body.appendChild(iframe);
 }
 
 function inspectNode(aInspector)
 {
   inspector = aInspector;
 
-  inspector.once("inspector-updated", performScrollingTest);
-  executeSoon(function() {
-    inspector.selection.setNode(div, "");
-  });
+  let highlighter = inspector.toolbox.highlighter;
+  highlighter.showBoxModel(getNodeFront(div)).then(performScrollingTest);
 }
 
 function performScrollingTest()
 {
-  executeSoon(function() {
-    // FIXME: this will fail on retina displays. EventUtils will only scroll
-    // 25px down instead of 50.
-    EventUtils.synthesizeWheel(div, 10, 10,
-      { deltaY: 50.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL },
-      iframe.contentWindow);
-  });
-
   gBrowser.selectedBrowser.addEventListener("scroll", function() {
     gBrowser.selectedBrowser.removeEventListener("scroll", arguments.callee,
       false);
+    let isRetina = devicePixelRatio === 2;
+    is(iframe.contentDocument.body.scrollTop,
+      isRetina ? 25 : 50, "inspected iframe scrolled");
 
-    is(iframe.contentDocument.body.scrollTop, 50, "inspected iframe scrolled");
+    finishUp();
+  }, false);
 
-    inspector = div = iframe = doc = null;
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    gDevTools.closeToolbox(target);
-    gBrowser.removeCurrentTab();
-    finish();
-  }, false);
+  EventUtils.synthesizeWheel(div, 10, 10,
+    { deltaY: 50.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL },
+    iframe.contentWindow);
+}
+
+function finishUp()
+{
+  inspector = div = iframe = doc = null;
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  gDevTools.closeToolbox(target);
+  gBrowser.removeCurrentTab();
+  finish();
 }
 
 function test()
 {
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
--- a/browser/devtools/inspector/test/browser_inspector_sidebarstate.js
+++ b/browser/devtools/inspector/test/browser_inspector_sidebarstate.js
@@ -20,28 +20,29 @@ function inspectorRuleViewOpened()
 {
   is(inspector.sidebar.getCurrentTabID(), "ruleview", "Rule View is selected by default");
 
   // Select the computed view and turn off the inspector.
   inspector.sidebar.select("computedview");
 
   gDevTools.once("toolbox-destroyed", inspectorClosed);
   let target = TargetFactory.forTab(gBrowser.selectedTab);
-  gDevTools.getToolbox(target).destroy();
+  gDevTools.closeToolbox(target);
 }
 
 function inspectorClosed()
 {
   openInspector(function(panel) {
     inspector = panel;
+
     if (inspector.sidebar.getCurrentTabID()) {
-      // Default sidebar already selected.
+      info("Default sidebar already selected.")
       testNewDefaultTab();
     } else {
-      // Default sidebar still to be selected.
+      info("Default sidebar still to be selected, adding select listener.");
       inspector.sidebar.once("select", testNewDefaultTab);
     }
   });
 }
 
 function testNewDefaultTab()
 {
   is(inspector.sidebar.getCurrentTabID(), "computedview", "Computed view is selected by default.");
@@ -62,10 +63,10 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
-  content.location = "data:text/html,basic tests for inspector";
+  content.location = "data:text/html;charset=utf-8,browser_inspector_sidebarstate.js";
 }
--- a/browser/devtools/inspector/test/browser_inspector_tree_height.js
+++ b/browser/devtools/inspector/test/browser_inspector_tree_height.js
@@ -101,11 +101,11 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
-  content.location = "data:text/html,basic tests for inspector";
+  content.location = "data:text/html;charset=utf-8,browser_inspector_tree_height.js";
 }
 
--- a/browser/devtools/inspector/test/head.js
+++ b/browser/devtools/inspector/test/head.js
@@ -22,22 +22,28 @@ let TargetFactory = devtools.TargetFacto
 
 Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
 let console = tempScope.console;
 
 // Import the GCLI test helper
 let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
 Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
 
+gDevTools.testing = true;
 SimpleTest.registerCleanupFunction(() => {
-  console.error("Here we are\n")
+  gDevTools.testing = false;
+});
+
+SimpleTest.registerCleanupFunction(() => {
+  console.error("Here we are\n");
   let {DebuggerServer} = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
   console.error("DebuggerServer open connections: " + Object.getOwnPropertyNames(DebuggerServer._connections).length);
 
   Services.prefs.clearUserPref("devtools.dump.emit");
+  Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
 });
 
 function openInspector(callback)
 {
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
     callback(toolbox.getCurrentPanel(), toolbox);
   }).then(null, console.error);
@@ -55,73 +61,128 @@ function getNodeFront(node)
   return inspector.walker.frontForRawNode(node);
 }
 
 function getHighlighter()
 {
   return gBrowser.selectedBrowser.parentNode.querySelector(".highlighter-container");
 }
 
-function getHighlighterOutline()
-{
-  let h = getHighlighter();
-  if (h) {
-    return h.querySelector(".highlighter-outline");
-  }
+function getSimpleBorderRect() {
+  let {p1, p2, p3, p4} = getBoxModelStatus().border.points;
+
+  return {
+    top: p1.y,
+    left: p1.x,
+    width: p2.x - p1.x,
+    height: p4.y - p1.y
+  };
+}
+
+function getBoxModelRoot() {
+  let highlighter = getHighlighter();
+  return highlighter.querySelector(".box-model-root");
 }
 
-function getHighlighterOutlineRect() {
-  let helper = new LayoutHelpers(window.content);
-  let outline = getHighlighterOutline();
+function getBoxModelStatus() {
+  let root = getBoxModelRoot();
+  let inspector = getActiveInspector();
+
+  return {
+    visible: !root.hasAttribute("hidden"),
+    currentNode: inspector.walker.currentNode,
+    margin: {
+      points: getPointsForRegion("margin"),
+      visible: isRegionHidden("margin")
+    },
+    border: {
+      points: getPointsForRegion("border"),
+      visible: isRegionHidden("border")
+    },
+    padding: {
+      points: getPointsForRegion("padding"),
+      visible: isRegionHidden("padding")
+    },
+    content: {
+      points: getPointsForRegion("content"),
+      visible: isRegionHidden("content")
+    },
+    guides: {
+      top: getGuideStatus("top"),
+      right: getGuideStatus("right"),
+      bottom: getGuideStatus("bottom"),
+      left: getGuideStatus("left")
+    }
+  };
+}
+
+function getGuideStatus(location) {
+  let root = getBoxModelRoot();
+  let guide = root.querySelector(".box-model-guide-" + location);
 
-  if (outline) {
-    let browserOffsetRect = helper.getDirtyRect(gBrowser.selectedBrowser);
-    let outlineRect = helper.getDirtyRect(outline);
-    outlineRect.top -= browserOffsetRect.top;
-    outlineRect.left -= browserOffsetRect.left;
+  return {
+    visible: !guide.hasAttribute("hidden"),
+    x1: guide.getAttribute("x1"),
+    y1: guide.getAttribute("y1"),
+    x2: guide.getAttribute("x2"),
+    y2: guide.getAttribute("y2")
+  };
+}
+
+function getPointsForRegion(region) {
+  let root = getBoxModelRoot();
+  let box = root.querySelector(".box-model-" + region);
+  let points = box.getAttribute("points").split(/[, ]/);
 
-    return outlineRect;
-  }
+  // We multiply each value by 1 to cast it into a number
+  return {
+    p1: {
+      x: parseFloat(points[0]),
+      y: parseFloat(points[1])
+    },
+    p2: {
+      x: parseFloat(points[2]),
+      y: parseFloat(points[3])
+    },
+    p3: {
+      x: parseFloat(points[4]),
+      y: parseFloat(points[5])
+    },
+    p4: {
+      x: parseFloat(points[6]),
+      y: parseFloat(points[7])
+    }
+  };
+}
+
+function isRegionHidden(region) {
+  let root = getBoxModelRoot();
+  let box = root.querySelector(".box-model-" + region);
+
+  return !box.hasAttribute("hidden");
 }
 
 function isHighlighting()
 {
-  let outline = getHighlighterOutline();
-  return outline && !outline.hasAttribute("hidden");
+  let root = getBoxModelRoot();
+  return !root.hasAttribute("hidden");
 }
 
 function getHighlitNode()
 {
   if (isHighlighting()) {
     let helper = new LayoutHelpers(window.content);
-    let outlineRect = getHighlighterOutlineRect();
-
-    let a = {
-      x: outlineRect.left,
-      y: outlineRect.top
-    };
+    let points = getBoxModelStatus().content.points;
+    let x = (points.p1.x + points.p2.x + points.p3.x + points.p4.x) / 4;
+    let y = (points.p1.y + points.p2.y + points.p3.y + points.p4.y) / 4;
 
-    let b = {
-      x: a.x + outlineRect.width,
-      y: a.y + outlineRect.height
-    };
-
-    let {x, y} = getMidPoint(a, b);
     return helper.getElementFromPoint(window.content.document, x, y);
   }
 }
 
-function getMidPoint(aPointA, aPointB)
-{
-  let pointC = {};
-  pointC.x = (aPointB.x - aPointA.x) / 2 + aPointA.x;
-  pointC.y = (aPointB.y - aPointA.y) / 2 + aPointA.y;
-  return pointC;
-}
-
 function computedView()
 {
   let sidebar = getActiveInspector().sidebar;
   let iframe = sidebar.tabbox.querySelector(".iframe-computedview");
   return iframe.contentWindow.computedView;
 }
 
 function computedViewTree()
--- a/browser/devtools/layoutview/test/browser_layoutview.js
+++ b/browser/devtools/layoutview/test/browser_layoutview.js
@@ -2,16 +2,21 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let TargetFactory = devtools.TargetFactory;
 
 function test() {
   waitForExplicitFinish();
 
+  gDevTools.testing = true;
+  SimpleTest.registerCleanupFunction(() => {
+    gDevTools.testing = false;
+  });
+
   Services.prefs.setBoolPref("devtools.inspector.sidebarOpen", true);
 
   let doc;
   let node;
   let view;
   let inspector;
 
   // Expected values:
--- a/browser/devtools/layoutview/view.css
+++ b/browser/devtools/layoutview/view.css
@@ -49,33 +49,33 @@ body {
   body {
     position: absolute;
     width: 320px;
     left: -160px;
     margin-left: 50%;
   }
 }
 
-
-#margins {
-  padding: 28px;
+#content,
+#borders {
+  border-width: 1px;
 }
 
 #content {
-  height: 20px;
-  border-width: 1px;
+  height: 25px;
 }
 
+#margins,
 #padding {
+  border-style: solid;
   border-width: 25px;
 }
 
 #borders {
-  border-width: 2px;
-  box-shadow: 0 0 16px black;
+  padding: 25px;
 }
 
 #main > p {
   position: absolute;
   pointer-events: none;
 }
 
 #main > p {
@@ -84,98 +84,94 @@ body {
 }
 
 #main > p > span {
   vertical-align: middle;
   pointer-events: auto;
   cursor: default;
 }
 
-.border.top {
-  left: 0; top: 23px;
-  width: 98px;
-}
-
-.border.bottom {
-  right: 0; bottom: 22px;
-  width: 98px;
-  top: auto;
-}
-
-.border.left {
-  top: 42px; left: 0;
-  width: 56px;
-}
-
-.border.right{
-  bottom: 42px; right: 0;
-  width: 56px;
-  top: auto;
-}
-
-.top, .bottom {
+.top,
+.bottom {
   width: calc(100% - 2px);
   text-align: center;
 }
 
+.padding.top {
+  top: 55px;
+}
+
+.padding.bottom {
+  bottom: 57px;
+}
+
+.border.top {
+  top: 30px;
+}
+
+.border.bottom {
+  bottom: 31px;
+}
+
 .margin.top {
-  top: 8px;
+  top: 5px;
 }
 
 .margin.bottom {
   bottom: 6px;
 }
 
-.padding.top {
-  top: 35px;
-}
-
-.padding.bottom {
-  bottom: 35px;
-}
-
 .size,
 .margin.left,
 .margin.right,
+.border.left,
+.border.right,
 .padding.left,
 .padding.right {
-  top: 0;
+  top: 22px;
   line-height: 132px;
 }
 
 .size {
   width: calc(100% - 2px);
 }
 
 .margin.right,
-.margin.left {
-  width: 28px;
-}
-
+.margin.left,
+.border.left,
+.border.right,
 .padding.right,
 .padding.left {
   width: 25px;
 }
 
+.padding.left {
+  left: 52px;
+}
+
+.padding.right {
+  right: 51px;
+}
+
+.border.left {
+  left: 26px;
+}
+
+.border.right {
+  right: 26px;
+}
+
 .margin.right {
   right: 0;
 }
 
 .margin.left {
   left: 0;
 }
 
-.padding.left {
-  left: 30px;
-}
-
-.padding.right {
-  right: 30px;
-}
-
 .tooltip {
   position: absolute;
   bottom: 0;
   right: 2px;
   pointer-events: none;
 }
 
 body.dim > #header > #element-position,
--- a/browser/devtools/layoutview/view.js
+++ b/browser/devtools/layoutview/view.js
@@ -234,22 +234,51 @@ LayoutView.prototype = {
       }
 
       this.inspector.emit("layoutview-updated");
       return null;
     });
 
     this._lastRequest = lastRequest;
     return this._lastRequest;
-  }
-}
+  },
+
+  showBoxModel: function(options={}) {
+    let toolbox = this.inspector.toolbox;
+    let nodeFront = this.inspector.selection.nodeFront;
+
+    toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
+  },
+
+  hideBoxModel: function() {
+    let toolbox = this.inspector.toolbox;
+
+    toolbox.highlighterUtils.unhighlight();
+  },
+};
 
 let elts;
 let tooltip;
 
+let onmouseover = function(e) {
+  let region = e.target.getAttribute("data-box");
+
+  tooltip.textContent = e.target.getAttribute("tooltip");
+  this.layoutview.showBoxModel({region: region});
+
+  return false;
+}.bind(window);
+
+let onmouseout = function(e) {
+  tooltip.textContent = "";
+  this.layoutview.hideBoxModel();
+
+  return false;
+}.bind(window);
+
 window.setPanel = function(panel) {
   this.layoutview = new LayoutView(panel, window);
 
   // Tooltip mechanism
   elts = document.querySelectorAll("*[tooltip]");
   tooltip = document.querySelector(".tooltip");
   for (let i = 0; i < elts.length; i++) {
     let elt = elts[i];
@@ -271,16 +300,8 @@ window.onunload = function() {
   if (elts) {
     for (let i = 0; i < elts.length; i++) {
       let elt = elts[i];
       elt.removeEventListener("mouseover", onmouseover, true);
       elt.removeEventListener("mouseout", onmouseout, true);
     }
   }
 };
-
-function onmouseover(e) {
-  tooltip.textContent = e.target.getAttribute("tooltip");
-}
-
-function onmouseout(e) {
-  tooltip.textContent = "";
-}
\ No newline at end of file
--- a/browser/devtools/layoutview/view.xhtml
+++ b/browser/devtools/layoutview/view.xhtml
@@ -25,40 +25,40 @@
   <body class="theme-body devtools-monospace">
 
     <p id="header">
       <span id="element-size"></span><span id="element-position"></span>
     </p>
 
     <div id="main">
 
-      <div id="margins" tooltip="&margins.tooltip;">
-        <div id="borders" tooltip="&borders.tooltip;">
-          <div id="padding" tooltip="&padding.tooltip;">
-            <div id="content" tooltip="&content.tooltip;">
+      <div id="margins" data-box="margin" tooltip="&margins.tooltip;">
+        <div id="borders" data-box="border" tooltip="&borders.tooltip;">
+          <div id="padding" data-box="padding" tooltip="&padding.tooltip;">
+            <div id="content" data-box="content" tooltip="&content.tooltip;">
             </div>
           </div>
         </div>
       </div>
 
-      <p class="border top"><span tooltip="border-top"></span></p>
-      <p class="border right"><span tooltip="border-right"></span></p>
-      <p class="border bottom"><span tooltip="border-bottom"></span></p>
-      <p class="border left"><span tooltip="border-left"></span></p>
+      <p class="border top"><span data-box="border" tooltip="border-top"></span></p>
+      <p class="border right"><span data-box="border" tooltip="border-right"></span></p>
+      <p class="border bottom"><span data-box="border" tooltip="border-bottom"></span></p>
+      <p class="border left"><span data-box="border" tooltip="border-left"></span></p>
 
-      <p class="margin top"><span tooltip="margin-top"></span></p>
-      <p class="margin right"><span tooltip="margin-right"></span></p>
-      <p class="margin bottom"><span tooltip="margin-bottom"></span></p>
-      <p class="margin left"><span tooltip="margin-left"></span></p>
+      <p class="margin top"><span data-box="margin" tooltip="margin-top"></span></p>
+      <p class="margin right"><span data-box="margin" tooltip="margin-right"></span></p>
+      <p class="margin bottom"><span data-box="margin" tooltip="margin-bottom"></span></p>
+      <p class="margin left"><span data-box="margin" tooltip="margin-left"></span></p>
 
-      <p class="padding top"><span tooltip="padding-top"></span></p>
-      <p class="padding right"><span tooltip="padding-right"></span></p>
-      <p class="padding bottom"><span tooltip="padding-bottom"></span></p>
-      <p class="padding left"><span tooltip="padding-left"></span></p>
+      <p class="padding top"><span data-box="padding" tooltip="padding-top"></span></p>
+      <p class="padding right"><span data-box="padding" tooltip="padding-right"></span></p>
+      <p class="padding bottom"><span data-box="padding" tooltip="padding-bottom"></span></p>
+      <p class="padding left"><span data-box="padding" tooltip="padding-left"></span></p>
 
-      <p class="size"><span tooltip="&content.tooltip;"></span></p>
+      <p class="size"><span data-box="content" tooltip="&content.tooltip;"></span></p>
 
       <span class="tooltip"></span>
 
     </div>
 
   </body>
 </html>
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -160,29 +160,29 @@ MarkupView.prototype = {
       }
       this._containers.get(nodeFront).hovered = true;
 
       this._hoveredNode = nodeFront;
     }
   },
 
   _onMouseLeave: function() {
-    this._hideBoxModel();
+    this._hideBoxModel(true);
     if (this._hoveredNode) {
       this._containers.get(this._hoveredNode).hovered = false;
     }
     this._hoveredNode = null;
   },
 
   _showBoxModel: function(nodeFront, options={}) {
     this._inspector.toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
   },
 
-  _hideBoxModel: function() {
-    this._inspector.toolbox.highlighterUtils.unhighlight();
+  _hideBoxModel: function(forceHide) {
+    this._inspector.toolbox.highlighterUtils.unhighlight(forceHide);
   },
 
   _briefBoxModelTimer: null,
   _brieflyShowBoxModel: function(nodeFront, options) {
     let win = this._frame.contentWindow;
 
     if (this._briefBoxModelTimer) {
       win.clearTimeout(this._briefBoxModelTimer);
@@ -1540,18 +1540,16 @@ MarkupContainer.prototype = {
       if (firstChild.container) {
         firstChild.container.destroy();
       }
       this.children.removeChild(firstChild);
     }
 
     // Remove event listeners
     this.elt.removeEventListener("dblclick", this._onToggle, false);
-    this.elt.removeEventListener("mouseover", this._onMouseOver, false);
-    this.elt.removeEventListener("mouseout", this._onMouseOut, false);
     this.elt.removeEventListener("mousedown", this._onMouseDown, false);
     this.expander.removeEventListener("click", this._onToggle, false);
 
     // Destroy my editor
     this.editor.destroy();
   }
 };
 
--- a/browser/devtools/markupview/test/browser_inspector_markup_968316_highlight_node_after_mouseleave_mousemove.js
+++ b/browser/devtools/markupview/test/browser_inspector_markup_968316_highlight_node_after_mouseleave_mousemove.js
@@ -10,17 +10,17 @@ function test() {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     waitForFocus(startTests, content);
   }, true);
 
-  content.location = "data:text/html,<p>Select me!</p>";
+  content.location = "data:text/html;charset=utf-8,<p>Select me!</p>";
 }
 
 function startTests(aInspector, aToolbox) {
   let p = content.document.querySelector("p");
   Task.spawn(function() {
     info("opening the inspector tool");
     let {inspector, toolbox} = yield openInspector();
 
--- a/browser/devtools/markupview/test/browser_inspector_markup_968316_highlit_node_on_hover_then_select.js
+++ b/browser/devtools/markupview/test/browser_inspector_markup_968316_highlit_node_on_hover_then_select.js
@@ -10,17 +10,17 @@ function test() {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     waitForFocus(startTests, content);
   }, true);
 
-  content.location = "data:text/html,<p>It's going to be legen....</p>";
+  content.location = "data:text/html;charset=utf-8,<p>It's going to be legen....</p>";
 }
 
 function startTests(aInspector, aToolbox) {
   let p = content.document.querySelector("p");
   Task.spawn(function() {
     info("opening the inspector tool");
     let {inspector, toolbox} = yield openInspector();
 
--- a/browser/devtools/markupview/test/browser_inspector_markup_navigation.js
+++ b/browser/devtools/markupview/test/browser_inspector_markup_navigation.js
@@ -120,17 +120,17 @@ function test() {
       case "pagedown":
         EventUtils.synthesizeKey("VK_PAGE_DOWN", {});
         break;
       case "home":
         EventUtils.synthesizeKey("VK_HOME", {});
         break;
     }
 
-    inspector.markup._waitForChildren().then(() => executeSoon(function BIMNT_newNode() {
+    inspector.markup._waitForChildren().then(() => executeSoon(() => {
       let node = inspector.selection.node;
 
       if (className == "*comment*") {
         is(node.nodeType, Node.COMMENT_NODE, "[" + cursor + "] should be a comment after moving " + key);
       } else if (className == "*text*") {
         is(node.nodeType, Node.TEXT_NODE, "[" + cursor + "] should be text after moving " + key);
       } else if (className == "*doctype*") {
         is(node.nodeType, Node.DOCUMENT_TYPE_NODE, "[" + cursor + "] should be doctype after moving " + key);
--- a/browser/devtools/markupview/test/head.js
+++ b/browser/devtools/markupview/test/head.js
@@ -7,16 +7,21 @@ const Cu = Components.utils;
 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let TargetFactory = devtools.TargetFactory;
 let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
 let promise = devtools.require("sdk/core/promise");
 let {getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared/inplace-editor");
 
 //Services.prefs.setBoolPref("devtools.dump.emit", true);
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 // Clear preferences that may be set during the course of tests.
 function clearUserPrefs() {
   Services.prefs.clearUserPref("devtools.inspector.htmlPanelOpen");
   Services.prefs.clearUserPref("devtools.inspector.sidebarOpen");
   Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
   Services.prefs.clearUserPref("devtools.dump.emit");
 }
 
@@ -115,17 +120,17 @@ function selectNode(nodeOrSelector, insp
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently loaded in the toolbox
  * @return a promise that resolves when the container is hovered and the higlighter
  * is shown on the corresponding node
  */
 function hoverContainer(nodeOrSelector, inspector) {
   info("Hovering over the markup-container for node " + nodeOrSelector);
   let highlit = inspector.toolbox.once("node-highlight");
   let container = getContainerForRawNode(inspector.markup, getNode(nodeOrSelector));
-  EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
+  EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousemove"},
     inspector.markup.doc.defaultView);
   return highlit;
 }
 
 /**
  * Simulate a click on the markup-container (a line in the markup-view)
  * that corresponds to the node or selector passed.
  * @param {String|DOMNode} nodeOrSelector
@@ -143,33 +148,34 @@ function clickContainer(nodeOrSelector, 
   return updated;
 }
 
 /**
  * Checks if the highlighter is visible currently
  * @return {Boolean}
  */
 function isHighlighterVisible() {
-  let outline = gBrowser.selectedBrowser.parentNode.querySelector(".highlighter-container .highlighter-outline");
-  return outline && !outline.hasAttribute("hidden");
+  let highlighter = gBrowser.selectedBrowser.parentNode
+                            .querySelector(".highlighter-container .box-model-root");
+  return highlighter && !highlighter.hasAttribute("hidden");
 }
 
 /**
  * Simulate the mouse leaving the markup-view area
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently loaded in the toolbox
  * @return a promise when done
  */
 function mouseLeaveMarkupView(inspector) {
   info("Leaving the markup-view area");
   let def = promise.defer();
 
   // Find another element to mouseover over in order to leave the markup-view
   let btn = inspector.toolbox.doc.querySelector(".toolbox-dock-button");
 
-  EventUtils.synthesizeMouse(btn, 2, 2, {type: "mousemove"},
+  EventUtils.synthesizeMouseAtCenter(btn, {type: "mousemove"},
     inspector.toolbox.doc.defaultView);
   executeSoon(def.resolve);
 
   return def.promise;
 }
 
 /**
  * Focus a given editable element, enter edit mode, set value, and commit
--- a/browser/devtools/netmonitor/test/head.js
+++ b/browser/devtools/netmonitor/test/head.js
@@ -38,28 +38,34 @@ const STATISTICS_URL = EXAMPLE_URL + "ht
 const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
 const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs";
 const STATUS_CODES_SJS = EXAMPLE_URL + "sjs_status-codes-test-server.sjs";
 const SORTING_SJS = EXAMPLE_URL + "sjs_sorting-test-server.sjs";
 
 const TEST_IMAGE = EXAMPLE_URL + "test-image.png";
 const TEST_IMAGE_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==";
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 // All tests are asynchronous.
 waitForExplicitFinish();
 
 // Enable logging for all the relevant tests.
 const gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 
 // Always reset some prefs to their original values after the test finishes.
 const gDefaultFilters = Services.prefs.getCharPref("devtools.netmonitor.filters");
 
 registerCleanupFunction(() => {
   info("finish() was called, cleaning up...");
+
   Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
   Services.prefs.setCharPref("devtools.netmonitor.filters", gDefaultFilters);
 });
 
 function addTab(aUrl, aWindow) {
   info("Adding tab: " + aUrl);
 
   let deferred = promise.defer();
--- a/browser/devtools/profiler/test/head.js
+++ b/browser/devtools/profiler/test/head.js
@@ -18,16 +18,21 @@ let TargetFactory = temp.devtools.Target
 
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm", temp);
 let DebuggerServer = temp.DebuggerServer;
 
 // Import the GCLI test helper
 let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
 Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 registerCleanupFunction(function () {
   helpers = null;
   Services.prefs.clearUserPref(PROFILER_ENABLED);
   Services.prefs.clearUserPref(REMOTE_ENABLED);
   Services.prefs.clearUserPref(SHOW_PLATFORM_DATA);
   DebuggerServer.destroy();
 
   // These tests use a lot of memory due to GL contexts, so force a GC to help
--- a/browser/devtools/responsivedesign/test/head.js
+++ b/browser/devtools/responsivedesign/test/head.js
@@ -5,16 +5,21 @@
 
 let {devtools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
 let TargetFactory = devtools.TargetFactory;
 
 // Import the GCLI test helper
 let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
 Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 function openInspector(callback)
 {
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
     callback(toolbox.getCurrentPanel());
   });
 }
 
--- a/browser/devtools/scratchpad/test/browser_scratchpad_revert_to_saved.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_revert_to_saved.js
@@ -85,18 +85,17 @@ function testAfterSecondSave() {
 function testAfterSecondRevert() {
   // Check if the file's text got reverted
   is(gScratchpad.getText(), gFileContent + "\nalert(foo.toSource());",
      "The text reverted back to the changed saved text.");
   // The revert menu should be disabled again.
   ok(menu.hasAttribute("disabled"),
      "Revert menu entry is disabled after reverting to changed saved state.");
   gFile.remove(false);
-  gFile = null;
-  gScratchpad = null;
+  gFile = gScratchpad = menu = null;
   finish();
 }
 
 function createAndLoadTemporaryFile()
 {
   // Create a temporary file.
   gFile = FileUtils.getFile("TmpD", [gFileName]);
   gFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
--- a/browser/devtools/scratchpad/test/head.js
+++ b/browser/devtools/scratchpad/test/head.js
@@ -5,16 +5,21 @@
 "use strict";
 
 const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
 const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
 
 let gScratchpadWindow; // Reference to the Scratchpad chrome window object
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 /**
  * Open a Scratchpad window.
  *
  * @param function aReadyCallback
  *        Optional. The function you want invoked when the Scratchpad instance
  *        is ready.
  * @param object aOptions
  *        Optional. Options for opening the scratchpad:
--- a/browser/devtools/shared/test/head.js
+++ b/browser/devtools/shared/test/head.js
@@ -1,16 +1,21 @@
 /* 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/. */
 
 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let TargetFactory = devtools.TargetFactory;
 let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 /**
  * Open a new tab at a URL and call a callback on load
  */
 function addTab(aURL, aCallback)
 {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
--- a/browser/devtools/sourceeditor/editor.js
+++ b/browser/devtools/sourceeditor/editor.js
@@ -27,18 +27,17 @@ const L10N = Services.strings.createBund
 // CM_STYLES, CM_SCRIPTS and CM_IFRAME represent the HTML,
 // JavaScript and CSS that is injected into an iframe in
 // order to initialize a CodeMirror instance.
 
 const CM_STYLES   = [
   "chrome://browser/skin/devtools/common.css",
   "chrome://browser/content/devtools/codemirror/codemirror.css",
   "chrome://browser/content/devtools/codemirror/dialog.css",
-  "chrome://browser/content/devtools/codemirror/mozilla.css",
-  "chrome://browser/content/devtools/codemirror/foldgutter.css"
+  "chrome://browser/content/devtools/codemirror/mozilla.css"
 ];
 
 const CM_SCRIPTS  = [
   "chrome://browser/content/devtools/theme-switching.js",
   "chrome://browser/content/devtools/codemirror/codemirror.js",
   "chrome://browser/content/devtools/codemirror/dialog.js",
   "chrome://browser/content/devtools/codemirror/searchcursor.js",
   "chrome://browser/content/devtools/codemirror/search.js",
--- a/browser/devtools/sourceeditor/test/head.js
+++ b/browser/devtools/sourceeditor/test/head.js
@@ -3,16 +3,21 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 const { require } = devtools;
 const Editor  = require("devtools/sourceeditor/editor");
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 function setup(cb) {
   const opt = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
   const url = "data:text/xml;charset=UTF-8,<?xml version='1.0'?>" +
     "<?xml-stylesheet href='chrome://global/skin/global.css'?>" +
     "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
     " title='Editor' width='600' height='500'><box flex='1'/></window>";
 
   let win = Services.ww.openWindow(null, url, "_blank", opt, null);
--- a/browser/devtools/styleeditor/test/head.js
+++ b/browser/devtools/styleeditor/test/head.js
@@ -18,16 +18,21 @@ let gPanelWindow;
 let cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
               .getService(Ci.nsICacheStorageService);
 
 
 // Import the GCLI test helper
 let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
 Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 function cleanup()
 {
   gPanelWindow = null;
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 }
 
--- a/browser/devtools/styleinspector/style-inspector.js
+++ b/browser/devtools/styleinspector/style-inspector.js
@@ -130,17 +130,17 @@ RuleViewTool.prototype = {
 
     this.view.destroy();
 
     delete this.outerIFrame;
     delete this.view;
     delete this.doc;
     delete this.inspector;
   }
-}
+};
 
 function ComputedViewTool(aInspector, aWindow, aIFrame)
 {
   this.inspector = aInspector;
   this.window = aWindow;
   this.document = aWindow.document;
   this.outerIFrame = aIFrame;
   this.view = new ComputedView.CssHtmlTree(this, aInspector.pageStyle);
--- a/browser/devtools/styleinspector/test/browser_ruleview_inherit.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_inherit.js
@@ -107,10 +107,10 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function(evt) {
     gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
     doc = content.document;
     waitForFocus(() => openRuleView(simpleInherit), content);
   }, true);
 
-  content.location = "data:text/html,basic style inspector tests";
+  content.location = "data:text/html;charset=utf-8,browser_inspector_changes.js";
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js
@@ -78,10 +78,10 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function(evt) {
     gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
     doc = content.document;
     waitForFocus(() => openRuleView(simpleOverride), content);
   }, true);
 
-  content.location = "data:text/html,basic style inspector tests";
+  content.location = "data:text/html;charset=utf-8,browser_ruleview_manipulation.js";
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_override.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_override.js
@@ -173,10 +173,10 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function(evt) {
     gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
     doc = content.document;
     waitForFocus(() => openRuleView(simpleOverride), content);
   }, true);
 
-  content.location = "data:text/html,basic style inspector tests";
+  content.location = "data:text/html;charset=utf-8,browser_ruleview_override.js";
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_ui.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_ui.js
@@ -243,10 +243,10 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function(evt) {
     gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
     doc = content.document;
     waitForFocus(() => openRuleView(startTest), content);
   }, true);
 
-  content.location = "data:text/html,basic style inspector tests";
+  content.location = "data:text/html;charset=utf-8,browser_ruleview_ui.js";
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_update.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_update.js
@@ -184,10 +184,10 @@ function test()
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function(evt) {
     gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
     doc = content.document;
     waitForFocus(() => openRuleView(startTest), content);
   }, true);
 
-  content.location = "data:text/html,basic style inspector tests";
+  content.location = "data:text/html;charset=utf-8,browser_ruleview_update.js";
 }
--- a/browser/devtools/styleinspector/test/head.js
+++ b/browser/devtools/styleinspector/test/head.js
@@ -4,37 +4,42 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const TEST_BASE_HTTP = "http://example.com/browser/browser/devtools/styleinspector/test/";
 const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/styleinspector/test/";
 
 //Services.prefs.setBoolPref("devtools.dump.emit", true);
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 
-SimpleTest.registerCleanupFunction(() => {
-  Services.prefs.clearUserPref("devtools.debugger.log");
-  Services.prefs.clearUserPref("devtools.dump.emit");
-});
-
 let tempScope = {};
 
 Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
 let ConsoleUtils = tempScope.ConsoleUtils;
 let gDevTools = tempScope.gDevTools;
 
 Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
 let devtools = tempScope.devtools;
 
 let TargetFactory = devtools.TargetFactory;
 let {CssHtmlTree} = devtools.require("devtools/styleinspector/computed-view");
 let {CssRuleView, _ElementStyle} = devtools.require("devtools/styleinspector/rule-view");
 let {CssLogic, CssSelector} = devtools.require("devtools/styleinspector/css-logic");
 
 let promise = devtools.require("sdk/core/promise");
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
+SimpleTest.registerCleanupFunction(() => {
+  Services.prefs.clearUserPref("devtools.debugger.log");
+  Services.prefs.clearUserPref("devtools.dump.emit");
+});
+
 let {
   editableField,
   getInplaceEditorForSpan: inplaceEditor
 } = devtools.require("devtools/shared/inplace-editor");
 Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
 let console = tempScope.console;
 
 let browser, hudId, hud, hudBox, filterBox, outputNode, cs;
--- a/browser/devtools/tilt/test/head.js
+++ b/browser/devtools/tilt/test/head.js
@@ -51,16 +51,20 @@ const DESTROYED = Tilt.NOTIFICATIONS.DES
 const SHOWN = Tilt.NOTIFICATIONS.SHOWN;
 const HIDDEN = Tilt.NOTIFICATIONS.HIDDEN;
 const HIGHLIGHTING = Tilt.NOTIFICATIONS.HIGHLIGHTING;
 const UNHIGHLIGHTING = Tilt.NOTIFICATIONS.UNHIGHLIGHTING;
 const NODE_REMOVED = Tilt.NOTIFICATIONS.NODE_REMOVED;
 
 const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled");
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
 
 function isTiltEnabled() {
   info("Apparently, Tilt is" + (TILT_ENABLED ? "" : " not") + " enabled.");
   return TILT_ENABLED;
 }
 
 function isWebGLSupported() {
   let supported = !TiltGL.isWebGLForceEnabled() &&
--- a/browser/devtools/webconsole/test/browser_console_variables_view_highlighter.js
+++ b/browser/devtools/webconsole/test/browser_console_variables_view_highlighter.js
@@ -61,17 +61,17 @@ function onNodeListVviewFetched(aEvent, 
           clickOnDomNodeVariableAndAssertInspectorSelected(index);
         });
       });
 
       // Rather than trying to emulate a mouseenter event, let's call the
       // variable's highlightDomNode and see if it has the desired effect
       prop.highlightDomNode();
     } else {
-      finishTest();
+      finishUp();
     }
   }
 
   function clickOnDomNodeVariableAndAssertInspectorSelected(index) {
     let prop = props[index][1];
 
     // Make sure the inspector is initialized so we can listen to its events
     gToolbox.initInspector().then(() => {
@@ -84,8 +84,14 @@ function onNodeListVviewFetched(aEvent, 
           hoverOverDomNodeVariableAndAssertHighlighter(index + 1);
         });
       });
     });
   }
 
   hoverOverDomNodeVariableAndAssertHighlighter(0);
 }
+
+function finishUp() {
+  gWebConsole = gJSTerm = gVariablesView = gToolbox = null;
+
+  finishTest();
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_autocomplete_in_debugger_stackframe.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_autocomplete_in_debugger_stackframe.js
@@ -209,17 +209,17 @@ function testCompletion(hud) {
   input.setSelectionRange(11, 11);
   jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
   yield undefined;
 
   newItems = popup.getItems();
   is(newItems.length, 0, "no items for foo2Obj[0]");
 
   testDriver = null;
-  executeSoon(finishTest);
+  executeSoon(finishUp);
   yield undefined;
 }
 
 function debuggerOpened(aResult)
 {
   let debuggerWin = aResult.panelWin;
   let debuggerController = debuggerWin.DebuggerController;
   let thread = debuggerController.activeThread;
@@ -232,8 +232,13 @@ function debuggerOpened(aResult)
   });
 }
 
 function onFramesAdded()
 {
   info("onFramesAdded, openConsole() now");
   executeSoon(() => openConsole(null, testNext));
 }
+
+function finishUp() {
+  testDriver = gStackframes = null;
+  finishTest();
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
@@ -327,10 +327,15 @@ function popupHideAfterCompletionInText(
 
   ok(!popup.isOpen, "popup is not open");
   is(inputNode.value, "dump(window.testBug873250b)",
      "completion was successful after VK_TAB");
   is(inputNode.selectionStart, 26, "cursor location is correct");
   is(inputNode.selectionStart, inputNode.selectionEnd, "cursor location (confirmed)");
   ok(!completeNode.value, "completeNode is empty");
 
+  finishUp();
+}
+
+function finishUp() {
+  HUD = popup = jsterm = inputNode = completeNode = null;
   finishTest();
 }
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
@@ -79,10 +79,15 @@ function testPropertyPanel()
     EventUtils.synthesizeMouse(anchor, 2, 2, {}, gHUD.iframeWindow);
   });
 }
 
 function onVariablesViewReady(aEvent, aView)
 {
   findVariableViewProperties(aView, [
     { name: "body", value: "<body>" },
-  ], { webconsole: gHUD }).then(finishTest);
+  ], { webconsole: gHUD }).then(finishUp);
 }
+
+function finishUp() {
+  gHUD = null;
+  finishTest();
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_output_01.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_output_01.js
@@ -84,10 +84,15 @@ function test() {
     DebuggerServer.LONG_STRING_LENGTH = LONG_STRING_LENGTH;
     DebuggerServer.LONG_STRING_INITIAL_LENGTH = LONG_STRING_INITIAL_LENGTH;
   });
 
   Task.spawn(function*() {
     let {tab} = yield loadTab(TEST_URI);
     let hud = yield openConsole(tab);
     return checkOutputForInputs(hud, inputTests);
-  }).then(finishTest);
+  }).then(finishUp);
 }
+
+function finishUp() {
+  inputTests = null;
+  finishTest();
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_output_03.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_output_03.js
@@ -148,17 +148,22 @@ let inputTests = [
     output: 'class="test1 tezt2"',
     printOutput: "[object Attr]",
     inspectable: true,
     variablesViewLabel: 'class="test1 tezt2"',
   },
 ];
 
 function test() {
-
   addTab(TEST_URI);
   browser.addEventListener("load", function onLoad() {
     browser.removeEventListener("load", onLoad, true);
     openConsole().then((hud) => {
       return checkOutputForInputs(hud, inputTests);
-    }).then(finishTest);
+    }).then(finishUp);
   }, true);
 }
+
+function finishUp() {
+  inputTests = null;
+
+  finishTest();
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_output_05.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_output_05.js
@@ -75,10 +75,15 @@ let inputTests = [
   },
 ];
 
 function test() {
   Task.spawn(function*() {
     let {tab} = yield loadTab(TEST_URI);
     let hud = yield openConsole(tab);
     return checkOutputForInputs(hud, inputTests);
-  }).then(finishTest);
+  }).then(finishUp);
 }
+
+function finishUp() {
+  inputTests = null;
+  finishTest();
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_view_source.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_view_source.js
@@ -23,17 +23,17 @@ function testViewSource(hud) {
 
   let button = content.document.querySelector("button");
   ok(button, "we have the button on the page");
 
   expectUncaughtException();
   EventUtils.sendMouseEvent({ type: "click" }, button, content);
 
   openDebugger().then(({panelWin: { DebuggerView }}) => {
-    info("debugger openeed");
+    info("debugger opened");
     Sources = DebuggerView.Sources;
     openConsole(null, (hud) => {
       info("console opened again");
 
       waitForMessages({
         webconsole: hud,
         messages: [{
           text: "fooBazBaz is not defined",
@@ -66,22 +66,19 @@ let observer = {
   observe: function(aSubject, aTopic, aData) {
     if (aTopic != "domwindowopened") {
       return;
     }
 
     ok(true, "the view source window was opened in response to clicking " +
        "the location node");
 
-    // executeSoon() is necessary to avoid crashing Firefox. See bug 611543.
-    executeSoon(function() {
-      aSubject.close();
-      ok(containsValueInvoked, "custom containsValue() was invoked");
-      Sources.containsValue = containsValue;
-      Sources = containsValue = null;
-      finishTest();
-    });
+    aSubject.close();
+    ok(containsValueInvoked, "custom containsValue() was invoked");
+    Sources.containsValue = containsValue;
+    Sources = containsValue = null;
+    finishTest();
   }
 };
 
 registerCleanupFunction(function() {
   Services.ww.unregisterNotification(observer);
 });
--- a/browser/devtools/webconsole/test/head.js
+++ b/browser/devtools/webconsole/test/head.js
@@ -35,16 +35,21 @@ const SEVERITY_LOG = 3;
 const GROUP_INDENT = 12;
 
 // The default indent in pixels, applied even without any groups.
 const GROUP_INDENT_DEFAULT = 6;
 
 const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
 let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
 
+gDevTools.testing = true;
+SimpleTest.registerCleanupFunction(() => {
+  gDevTools.testing = false;
+});
+
 function log(aMsg)
 {
   dump("*** WebConsoleTest: " + aMsg + "\n");
 }
 
 function pprint(aObj)
 {
   for (let prop in aObj) {
@@ -293,17 +298,17 @@ function dumpMessageElement(aMessage)
                 "severity", aMessage.severity,
                 "repeats", repeats,
                 "clipboardText", aMessage.clipboardText,
                 "text", text);
 }
 
 function finishTest()
 {
-  browser = hudId = hud = filterBox = outputNode = cs = null;
+  browser = hudId = hud = filterBox = outputNode = cs = hudBox = null;
 
   dumpConsoles();
 
   let browserConsole = HUDService.getBrowserConsole();
   if (browserConsole) {
     if (browserConsole.jsterm) {
       browserConsole.jsterm.clearOutput(true);
     }
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -93,19 +93,18 @@ These should match what Safari and other
 <!ENTITY fullScreenCmd.label "Full Screen">
 <!ENTITY fullScreenCmd.accesskey "F">
 <!ENTITY fullScreenCmd.macCommandKey "f">
 <!ENTITY showAllTabsCmd.label "Show All Tabs">
 <!ENTITY showAllTabsCmd.accesskey "A">
 
 <!ENTITY fxaSignIn.label "Sign in to &syncBrand.shortName.label;">
 <!ENTITY fxaSignInError.label "Reconnect to &syncBrand.shortName.label;">
-<!ENTITY syncStartPanel.heading "&brandShortName; is now syncing">
-<!ENTITY syncStartPanel.subTitle "You can manage &syncBrand.shortName.label; in Options.">
-<!ENTITY syncStartPanel.subTitleUnix "You can manage &syncBrand.shortName.label; in Preferences.">
+<!ENTITY syncStartPanel2.heading "&syncBrand.shortName.label; enabled">
+<!ENTITY syncStartPanel2.subTitle "&brandShortName; will begin syncing momentarily.">
 <!ENTITY syncErrorPanel.heading "Cannot connect to &syncBrand.shortName.label;">
 <!ENTITY syncErrorPanel.subTitle "Please sign in to resume syncing.">
 <!ENTITY syncErrorPanel.signInButton.label "Sign In">
 <!ENTITY syncErrorPanel.signInButton.accesskey "S">
 
 
 <!ENTITY fullScreenMinimize.tooltip "Minimize">
 <!ENTITY fullScreenRestore.tooltip "Restore">
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -3,16 +3,17 @@
  * 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/");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
+@namespace svg url("http://www.w3.org/2000/svg");
 
 %include ../shared/browser.inc
 %include linuxShared.inc
 %filter substitution
 
 %define forwardTransitionLength 150ms
 %define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container
 %define conditionalForwardWithUrlbarWidth 27
@@ -1951,32 +1952,35 @@ toolbarbutton.chevron > .toolbarbutton-i
   color: ButtonText;
   padding: 0 3px;
   margin-top: 10px;
 }
 
 /* Sync Panel */
 
 .sync-panel-icon {
+  height:32px;
   width: 32px;
   background: url("chrome://browser/content/abouthome/sync.png") top left no-repeat;
 }
 
 .sync-panel-inner {
   width: 0;
   padding-left: 10px;
 }
 
 .sync-panel-button-box {
   margin-top: 1em;
 }
 
 #sync-error-panel-title,
 #sync-start-panel-title {
+  font-size: 120%;
   font-weight: bold;
+  margin-bottom: 5px;
 }
 
 #sync-start-panel-subtitle,
 #sync-error-panel-subtitle {
   margin: 0;
 }
 
 /* Status panel */
--- a/browser/themes/linux/devtools/layoutview.css
+++ b/browser/themes/linux/devtools/layoutview.css
@@ -6,41 +6,45 @@
   background-image: url(layout-background-grid.png);
 }
 
 .theme-light .theme-body {
   background-image: url(layout-background-grid.png), radial-gradient(circle at 50% 70%, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
 }
 
 .theme-body {
-  color: hsl(210,100%,85%) !important;
+  color: hsl(210,53%,45%) !important;
   box-sizing: border-box;
 }
 
 #main {
+  background-color: white;
   border-color: hsla(210,100%,85%,0.7);
   border-style: dotted;
 }
 
-#main > .border {
-  color: hsl(210,53%,45%);
+#content {
+  background-color: #80d4ff;
+  border-color: hsl(210,100%,85%);
+  border-style: dotted;
 }
 
-.border > span {
-  background-color: hsl(210,100%,85%);
-  border-radius: 2px;
-  padding: 0 4px;
-}
-
-#content {
-  border-color: hsla(210,100%,85%,0.7);
-  border-style: dotted 
+#padding,
+#margins {
+  border-color: hsla(210,100%,85%,0.2);
+  outline: dotted 1px hsl(210,100%,85%);
 }
 
 #padding {
-  border-color: hsla(210,100%,85%,0.2);
-  border-style: solid;
+  background-color: #66cc52;
 }
 
 #borders {
-  border-style: solid;
+  background-color: #ffe431;
+  border-style: dotted;
   border-color: hsl(210,100%,85%);
+  box-shadow: 0 0 8px #000;
 }
+
+#margins {
+  background-color: #d89b28;
+  opacity: 0.6;
+}
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -9,16 +9,17 @@
 %define forwardTransitionLength 150ms
 %define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container
 %define conditionalForwardWithUrlbarWidth 27
 %define spaceAboveTabbar 9px
 %define toolbarButtonPressed :hover:active:not([disabled="true"]):not([cui-areatype="menu-panel"])
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
+@namespace svg url("http://www.w3.org/2000/svg");
 
 #urlbar:-moz-lwtheme:not([focused="true"]),
 .searchbar-textbox:-moz-lwtheme:not([focused="true"]) {
   opacity: .9;
 }
 
 #navigator-toolbox::after {
   -moz-box-ordinal-group: 101; /* tabs toolbar is 100 */
@@ -3781,16 +3782,17 @@ toolbarbutton.chevron > .toolbarbutton-m
 
 #ctrlTab-showAll {
   margin-top: .5em;
 }
 
 /* Sync Panels */
 
 .sync-panel-icon {
+  height:32px;
   width: 32px;
   background: url("chrome://browser/content/abouthome/sync.png") top left no-repeat;
 }
 
 @media (min-resolution: 2dppx) {
   .sync-panel-icon {
     background: url("chrome://browser/content/abouthome/sync@2x.png") top left no-repeat;
     background-size: 32px 32px;
@@ -3818,17 +3820,19 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 
 .sync-panel-button:-moz-focusring {
   @hudButtonFocused@
 }
 
 #sync-error-panel-title,
 #sync-start-panel-title {
+  font-size: 120%;
   font-weight: bold;
+  margin-bottom: 5px;
 }
 
 #sync-start-panel-subtitle,
 #sync-error-panel-subtitle {
   margin: 0;
 }
 
 /* Status panel */
--- a/browser/themes/osx/devtools/layoutview.css
+++ b/browser/themes/osx/devtools/layoutview.css
@@ -6,41 +6,45 @@
   background-image: url(layout-background-grid.png);
 }
 
 .theme-light .theme-body {
   background-image: url(layout-background-grid.png), radial-gradient(circle at 50% 70%, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
 }
 
 .theme-body {
-  color: hsl(210,100%,85%) !important;
+  color: hsl(210,53%,45%) !important;
   box-sizing: border-box;
 }
 
 #main {
+  background-color: white;
   border-color: hsla(210,100%,85%,0.7);
   border-style: dotted;
 }
 
-#main > .border {
-  color: hsl(210,53%,45%);
+#content {
+  background-color: #80d4ff;
+  border-color: hsl(210,100%,85%);
+  border-style: dotted;
 }
 
-.border > span {
-  background-color: hsl(210,100%,85%);
-  border-radius: 2px;
-  padding: 0 4px;
-}
-
-#content {
-  border-color: hsla(210,100%,85%,0.7);
-  border-style: dotted 
+#padding,
+#margins {
+  border-color: hsla(210,100%,85%,0.2);
+  outline: dotted 1px hsl(210,100%,85%);
 }
 
 #padding {
-  border-color: hsla(210,100%,85%,0.2);
-  border-style: solid;
+  background-color: #66cc52;
 }
 
 #borders {
-  border-style: solid;
+  background-color: #ffe431;
+  border-style: dotted;
   border-color: hsl(210,100%,85%);
+  box-shadow: 0 0 8px #000;
 }
+
+#margins {
+  background-color: #d89b28;
+  opacity: 0.6;
+}
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -248,16 +248,17 @@ toolbarpaletteitem[place="toolbar"] {
 
 #wrapper-zoom-controls[place="palette"] > #zoom-controls > #zoom-reset-button,
 #wrapper-zoom-controls[place="palette"] > #zoom-controls > #zoom-reset-button + separator {
   display: none;
 }
 
 #wrapper-personal-bookmarks:not([place="toolbar"]) > #personal-bookmarks {
   -moz-box-pack: center;
+  min-height: 48px;
 }
 
 #customization-palette > toolbarpaletteitem > label {
   text-align: center;
   margin-left: 0;
   margin-right: 0;
 }
 
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -129,17 +129,18 @@
 .panelUI-grid:not([customize-transitioning]) .toolbarbutton-1 > .toolbarbutton-multiline-text {
   position: absolute;
   clip: rect(auto, auto, 2.2em, auto);
 }
 
 .panelUI-grid .toolbarbutton-1 > .toolbarbutton-text,
 .panelUI-grid .toolbarbutton-1 > .toolbarbutton-multiline-text {
   text-align: center;
-  margin: 2px 0 0;
+  /* Need to override toolkit theming which sets margin: 0 !important; */
+  margin: 2px 0 0 !important;
 }
 
 .panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-multiline-text {
   text-align: center;
   margin: -1px 0 0;
 }
 
 #wrapper-edit-controls:-moz-any([place="palette"],[place="panel"]) > #edit-controls,
--- a/browser/themes/shared/devtools/highlighter.inc.css
+++ b/browser/themes/shared/devtools/highlighter.inc.css
@@ -1,20 +1,48 @@
 %if 0
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 %endif
 
-/* Highlighter */
+/* Box model highlighter */
+svg|g.box-model-container {
+  opacity: 0.4;
+}
+
+svg|polygon.box-model-content {
+  fill: #80d4ff;
+}
+
+svg|polygon.box-model-padding {
+  fill: #66cc52;
+}
+
+svg|polygon.box-model-border {
+  fill: #ffe431;
+}
 
-.highlighter-outline {
-  box-shadow: 0 0 0 1px black;
-  outline: 1px dashed white;
-  outline-offset: -1px;
+svg|polygon.box-model-margin {
+  fill: #d89b28;
+}
+
+svg|polygon.box-model-content,
+svg|polygon.box-model-padding,
+svg|polygon.box-model-border,
+svg|polygon.box-model-margin {
+  stroke: none;
+}
+
+svg|line.box-model-guide-top,
+svg|line.box-model-guide-right,
+svg|line.box-model-guide-bottom,
+svg|line.box-model-guide-left {
+  stroke: #08C;
+  stroke-dasharray: 5 3;
 }
 
 /* Highlighter - Node Infobar */
 
 .highlighter-nodeinfobar {
   color: hsl(216,33%,97%);
   border-radius: 3px;
   background: hsl(214,13%,24%) no-repeat padding-box;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -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/. */
 
 @import url("chrome://global/skin/");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
+@namespace svg url("http://www.w3.org/2000/svg");
 
 %include ../shared/browser.inc
 %include windowsShared.inc
 %filter substitution
 %define toolbarShadowColor hsla(209,67%,12%,0.35)
 %define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32);
 %define forwardTransitionLength 150ms
 %define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container
@@ -2381,32 +2382,35 @@ toolbarbutton.bookmark-item[dragover="tr
 
 #ctrlTab-showAll {
   margin-top: .5em;
 }
 
 /* Sync Panel */
 
 .sync-panel-icon {
+  height:32px;
   width: 32px;
   background: url("chrome://browser/content/abouthome/sync.png") top left no-repeat;
 }
 
 .sync-panel-inner {
   width: 0;
   padding-left: 10px;
 }
 
 .sync-panel-button-box {
   margin-top: 1em;
 }
 
 #sync-error-panel-title,
 #sync-start-panel-title {
+  font-size: 120%;
   font-weight: bold;
+  margin-bottom: 5px;
 }
 
 #sync-start-panel-subtitle,
 #sync-error-panel-subtitle {
   margin: 0;
 }
 
 /* Status panel */
--- a/browser/themes/windows/devtools/layoutview.css
+++ b/browser/themes/windows/devtools/layoutview.css
@@ -6,41 +6,45 @@
   background-image: url(layout-background-grid.png);
 }
 
 .theme-light .theme-body {
   background-image: url(layout-background-grid.png), radial-gradient(circle at 50% 70%, hsl(210,53%,45%) 0%, hsl(210,54%,33%) 100%);
 }
 
 .theme-body {
-  color: hsl(210,100%,85%) !important;
+  color: hsl(210,53%,45%) !important;
   box-sizing: border-box;
 }
 
 #main {
+  background-color: white;
   border-color: hsla(210,100%,85%,0.7);
   border-style: dotted;
 }
 
-#main > .border {
-  color: hsl(210,53%,45%);
+#content {
+  background-color: #80d4ff;
+  border-color: hsl(210,100%,85%);
+  border-style: dotted;
 }
 
-.border > span {
-  background-color: hsl(210,100%,85%);
-  border-radius: 2px;
-  padding: 0 4px;
-}
-
-#content {
-  border-color: hsla(210,100%,85%,0.7);
-  border-style: dotted 
+#padding,
+#margins {
+  border-color: hsla(210,100%,85%,0.2);
+  outline: dotted 1px hsl(210,100%,85%);
 }
 
 #padding {
-  border-color: hsla(210,100%,85%,0.2);
-  border-style: solid;
+  background-color: #66cc52;
 }
 
 #borders {
-  border-style: solid;
+  background-color: #ffe431;
+  border-style: dotted;
   border-color: hsl(210,100%,85%);
+  box-shadow: 0 0 8px #000;
 }
+
+#margins {
+  background-color: #d89b28;
+  opacity: 0.6;
+}
--- a/caps/tests/mochitest/mochitest.ini
+++ b/caps/tests/mochitest/mochitest.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 support-files =
   file_disableScript.html
 
 [test_app_principal_equality.html]
+skip-if = e10s
 [test_bug246699.html]
 [test_bug292789.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug423375.html]
 [test_bug470804.html]
 [test_disallowInheritPrincipal.html]
--- a/content/base/test/csp/mochitest.ini
+++ b/content/base/test/csp/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   file_CSP.css
   file_CSP.sjs
   file_CSP_bug663567.xsl
   file_CSP_bug663567_allows.xml
   file_CSP_bug663567_allows.xml^headers^
   file_CSP_bug663567_blocks.xml
   file_CSP_bug663567_blocks.xml^headers^
--- a/content/base/test/mochitest.ini
+++ b/content/base/test/mochitest.ini
@@ -215,50 +215,51 @@ support-files =
   w3element_traversal.svg
   wholeTexty-helper.xml
 
 [test_CrossSiteXHR.html]
 skip-if = toolkit == 'android'
 [test_CrossSiteXHR_cache.html]
 skip-if = toolkit == 'android'
 [test_CrossSiteXHR_origin.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(https not working, bug 907770) b2g-debug(https not working, bug 907770) b2g-desktop(https not working, bug 907770)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(https not working, bug 907770) b2g-debug(https not working, bug 907770) b2g-desktop(https not working, bug 907770)
 [test_DOMException.html]
 [test_EventSource_redirects.html]
 [test_NodeIterator_basics_filters.xhtml]
 [test_NodeIterator_mutations_1.xhtml]
 [test_NodeIterator_mutations_2.html]
 [test_NodeIterator_mutations_3.html]
 [test_XHR.html]
 [test_XHRDocURI.html]
 [test_XHRSendData.html]
-skip-if = buildapp == 'b2g' # b2g(seems to stall) b2g-debug(seems to stall) b2g-desktop(seems to stall)
+skip-if = buildapp == 'b2g' || e10s # b2g(seems to stall) b2g-debug(seems to stall) b2g-desktop(seems to stall)
 [test_XHR_anon.html]
 [test_XHR_header.html]
 [test_XHR_onuploadprogress.html]
 [test_XHR_parameters.html]
 skip-if = buildapp == 'b2g' # b2g(86 total, 4 failing - testing mozAnon - got false, expected true) b2g-debug(86 total, 4 failing - testing mozAnon - got false, expected true) b2g-desktop(86 total, 4 failing - testing mozAnon - got false, expected true)
 [test_XHR_system.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(12 total, 2 failing - .mozSystem == true - got false, expected true + ) b2g-desktop(12 total, 2 failing - .mozSystem == true - got false, expected true + )
 [test_XHR_timeout.html]
 skip-if = buildapp == 'b2g' # b2g(flaky on B2G, bug 960743) b2g-debug(flaky on B2G, bug 960743) b2g-desktop(flaky on B2G, bug 960743)
 [test_XHR_timeout.js]
 [test_base.xhtml]
 [test_blobconstructor.html]
 [test_bug166235.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
 [test_bug199959.html]
 [test_bug218236.html]
 [test_bug218277.html]
 [test_bug238409.html]
 [test_bug254337.html]
 [test_bug270145.xhtml]
 [test_bug276037-1.html]
 [test_bug276037-2.xhtml]
 [test_bug282547.html]
+skip-if = e10s
 [test_bug28293.html]
 [test_bug28293.xhtml]
 [test_bug298064.html]
 [test_bug300992.html]
 [test_bug311681.xml]
 [test_bug313646.html]
 [test_bug320799.html]
 [test_bug322317.html]
@@ -319,16 +320,17 @@ skip-if = buildapp == 'b2g' || toolkit =
 [test_bug395915.html]
 [test_bug397234.html]
 [test_bug398243.html]
 [test_bug401662.html]
 [test_bug402150.html]
 [test_bug402150.html^headers^]
 [test_bug403841.html]
 [test_bug403852.html]
+skip-if = e10s
 [test_bug403868.xml]
 [test_bug405182.html]
 [test_bug409380.html]
 [test_bug410229.html]
 [test_bug413974.html]
 [test_bug414190.html]
 [test_bug415860.html]
 [test_bug416317-1.html]
@@ -342,32 +344,32 @@ skip-if = buildapp == 'b2g' || toolkit =
 [test_bug420609.xhtml]
 [test_bug420700.html]
 [test_bug421602.html]
 [test_bug422403-1.html]
 skip-if = buildapp == 'b2g' # b2g(bug 901343, specialpowers.wrap issue [nsIChannel.open]) b2g-debug(bug 901343, specialpowers.wrap issue [nsIChannel.open]) b2g-desktop(bug 901343, specialpowers.wrap issue [nsIChannel.open])
 [test_bug422403-2.xhtml]
 skip-if = buildapp == 'b2g'
 [test_bug422537.html]
-skip-if = buildapp == 'b2g' # b2g(xmlhttprequest causes crash, bug 902271) b2g-debug(xmlhttprequest causes crash, bug 902271) b2g-desktop(xmlhttprequest causes crash, bug 902271)
+skip-if = buildapp == 'b2g' || e10s # b2g(xmlhttprequest causes crash, bug 902271) b2g-debug(xmlhttprequest causes crash, bug 902271) b2g-desktop(xmlhttprequest causes crash, bug 902271)
 [test_bug424212.html]
 [test_bug424359-1.html]
 skip-if = buildapp == 'b2g'
 [test_bug424359-2.html]
 skip-if = buildapp == 'b2g'
 [test_bug425013.html]
 [test_bug426308.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk')
 [test_bug426646.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug428847.html]
 [test_bug429157.html]
 [test_bug431082.html]
 [test_bug431701.html]
-skip-if = buildapp == 'b2g' # b2g(xmlhttprequest causes crash, bug 902271) b2g-debug(xmlhttprequest causes crash, bug 902271) b2g-desktop(xmlhttprequest causes crash, bug 902271)
+skip-if = buildapp == 'b2g' || e10s # b2g(xmlhttprequest causes crash, bug 902271) b2g-debug(xmlhttprequest causes crash, bug 902271) b2g-desktop(xmlhttprequest causes crash, bug 902271)
 [test_bug431833.html]
 [test_bug433533.html]
 [test_bug433662.html]
 [test_bug435425.html]
 [test_bug438519.html]
 [test_bug444030.xhtml]
 [test_bug444322.html]
 [test_bug444722.html]
@@ -393,17 +395,17 @@ skip-if = buildapp == 'b2g'
 [test_bug466751.xhtml]
 [test_bug469020.html]
 [test_bug469304.html]
 [test_bug473162-1.html]
 [test_bug473162-2.html]
 [test_bug475156.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 855762 # b2g(36 total - bug 902611) b2g-debug(36 total - bug 902611) b2g-desktop(36 total - bug 902611)
 [test_bug482935.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 855762
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 855762
 [test_bug484396.html]
 [test_bug493881.html]
 [test_bug493881.js]
 [test_bug498240.html]
 [test_bug498433.html]
 skip-if = buildapp == 'b2g'
 [test_bug498897.html]
 [test_bug499656.html]
@@ -437,17 +439,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_bug562137.html]
 [test_bug562169-1.html]
 [test_bug562169-2.html]
 [test_bug562652.html]
 [test_bug564047.html]
 [test_bug564863.xhtml]
 [test_bug567350.html]
 [test_bug578096.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(debug-only failure; crash) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s # b2g-debug(debug-only failure; crash) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_bug585978.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only timeout
 [test_bug587931.html]
 [test_bug588990.html]
 [test_bug590812.html]
 skip-if = toolkit == 'android' #bug 687032
 [test_bug590870.html]
 [test_bug592366.html]
@@ -520,17 +522,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_bug810494.html]
 [test_bug811701.html]
 [test_bug811701.xhtml]
 [test_bug813919.html]
 [test_bug814576.html]
 [test_bug819051.html]
 [test_bug820909.html]
 [test_bug827160.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #needs plugin support # b2g(needs plugin support) b2g-debug(debug-only failure) b2g-desktop(needs plugin support)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #needs plugin support # b2g(needs plugin support) b2g-debug(debug-only failure) b2g-desktop(needs plugin support)
 [test_bug840098.html]
 [test_bug868999.html]
 [test_bug869000.html]
 [test_bug869002.html]
 [test_bug869006.html]
 [test_bug876282.html]
 [test_bug890580.html]
 [test_bug894874.html]
@@ -539,82 +541,83 @@ skip-if = buildapp == 'b2g' || toolkit =
 [test_bug902847.html]
 [test_bug907892.html]
 [test_bug922681.html]
 [test_bug927196.html]
 [test_caretPositionFromPoint.html]
 [test_classList.html]
 # This test fails on the Mac for some reason
 [test_copyimage.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows' #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows' || e10s #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_copypaste.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 904183 # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
 [test_copypaste.xhtml]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183) b2g-debug(bug 904183) b2g-desktop(bug 904183)
 [test_createHTMLDocument.html]
 [test_declare_stylesheet_obsolete.html]
 [test_domparser_null_char.html]
 [test_domparsing.html]
 [test_elementTraversal.html]
 [test_fileapi.html]
+skip-if = e10s
 [test_fileapi_slice.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 775227
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 775227
 [test_getElementById.html]
 [test_html_colors_quirks.html]
 [test_html_colors_standards.html]
 [test_html_in_xhr.html]
 [test_htmlcopyencoder.html]
 [test_htmlcopyencoder.xhtml]
 [test_ipc_messagemanager_blob.html]
 [test_meta_viewport0.html]
 [test_meta_viewport1.html]
 [test_meta_viewport2.html]
 [test_meta_viewport3.html]
 [test_meta_viewport4.html]
 [test_meta_viewport5.html]
 [test_meta_viewport6.html]
 [test_mixed_content_blocker.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT, SSL_REQUIRED
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT, SSL_REQUIRED
 [test_mixed_content_blocker_bug803225.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT, SSL_REQUIRED
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT, SSL_REQUIRED
 [test_mixed_content_blocker_frameNavigation.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT, SSL_REQUIRED
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT, SSL_REQUIRED
 [test_mozfiledataurl.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT
 [test_mutationobservers.html]
-skip-if = buildapp == 'b2g' # b2g(bug 901385, showmodaldialog) b2g-debug(bug 901385, showmodaldialog) b2g-desktop(bug 901385, showmodaldialog)
+skip-if = buildapp == 'b2g' || e10s # b2g(bug 901385, showmodaldialog) b2g-debug(bug 901385, showmodaldialog) b2g-desktop(bug 901385, showmodaldialog)
 [test_nodelist_holes.html]
 [test_object.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(needs plugin support) b2g-debug(needs plugin support) b2g-desktop(needs plugin support)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs plugin support) b2g-debug(needs plugin support) b2g-desktop(needs plugin support)
 [test_plugin_freezing.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #CLICK_TO_PLAY
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #CLICK_TO_PLAY
 [test_processing_instruction_update_stylesheet.xhtml]
 [test_range_bounds.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_reentrant_flush.html]
-skip-if = toolkit == 'android' #RANDOM
+skip-if = toolkit == 'android' || e10s #RANDOM
 [test_sync_xhr_timer.xhtml]
-skip-if = toolkit == 'android' #RANDOM
+skip-if = toolkit == 'android' || e10s #RANDOM
 [test_text_wholeText.html]
 [test_textnode_normalize_in_selection.html]
 [test_textnode_split_in_selection.html]
 [test_title.html]
 [test_treewalker_nextsibling.xml]
 [test_viewport_scroll.html]
 [test_w3element_traversal.html]
 [test_w3element_traversal.xhtml]
 [test_w3element_traversal_svg.html]
 [test_websocket.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android'
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
 [test_websocket_basic.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android'
 [test_websocket_hello.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android'
 [test_x-frame-options.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(observerservice issue) b2g-debug(observerservice issue) b2g-desktop(observerservice issue)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(observerservice issue) b2g-debug(observerservice issue) b2g-desktop(observerservice issue)
 [test_xbl_userdata.xhtml]
 [test_xhr_abort_after_load.html]
 skip-if = toolkit == 'android'
 [test_xhr_forbidden_headers.html]
 [test_xhr_progressevents.html]
 skip-if = toolkit == 'android'
 [test_xhr_send_readystate.html]
 [test_xhr_withCredentials.html]
--- a/content/base/test/websocket_hybi/mochitest.ini
+++ b/content/base/test/websocket_hybi/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   file_binary-frames_wsh.py
   file_check-binary-messages_wsh.py
 
 [test_receive-arraybuffer.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android'
 [test_receive-blob.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android'
--- a/content/canvas/test/webgl/mochitest.ini
+++ b/content/canvas/test/webgl/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   00_test_list.txt
   failing_tests_android.txt
   failing_tests_android_nvidia.txt
   failing_tests_android_x86.txt
   failing_tests_linux.txt
   failing_tests_linux_mesa.txt
   failing_tests_linux_nvidia.txt
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -73,16 +73,18 @@
 
 #include "AudioChannelService.h"
 
 #include "nsCSSParser.h"
 #include "nsIMediaList.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/WakeLock.h"
 
+#include "mozilla/dom/TextTrack.h"
+
 #include "ImageContainer.h"
 #include "nsRange.h"
 #include <algorithm>
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gMediaElementLog;
 static PRLogModuleInfo* gMediaElementEventsLog;
 #define LOG(type, msg) PR_LOG(gMediaElementLog, type, msg)
@@ -3942,19 +3944,21 @@ HTMLMediaElement::TextTracks() const
   return mTextTrackManager ? mTextTrackManager->TextTracks() : nullptr;
 }
 
 already_AddRefed<TextTrack>
 HTMLMediaElement::AddTextTrack(TextTrackKind aKind,
                                const nsAString& aLabel,
                                const nsAString& aLanguage)
 {
-  return mTextTrackManager ? mTextTrackManager->AddTextTrack(aKind, aLabel,
-                                                             aLanguage)
-                           : nullptr;
+  if (mTextTrackManager) {
+    return mTextTrackManager->AddTextTrack(aKind, aLabel, aLanguage,
+                                           TextTrackSource::AddTextTrack);
+  }
+  return nullptr;
 }
 
 void
 HTMLMediaElement::PopulatePendingTextTrackList()
 {
   if (mTextTrackManager) {
     mTextTrackManager->PopulatePendingList();
   }
--- a/content/html/content/src/HTMLTrackElement.cpp
+++ b/content/html/content/src/HTMLTrackElement.cpp
@@ -148,17 +148,19 @@ HTMLTrackElement::CreateTextTrack()
 
   TextTrackKind kind;
   if (const nsAttrValue* value = GetParsedAttr(nsGkAtoms::kind)) {
     kind = static_cast<TextTrackKind>(value->GetEnumValue());
   } else {
     kind = TextTrackKind::Subtitles;
   }
 
-  mTrack = new TextTrack(OwnerDoc()->GetParentObject(), kind, label, srcLang);
+  mTrack = new TextTrack(OwnerDoc()->GetParentObject(), kind, label, srcLang,
+                         TextTrackSource::Track);
+  mTrack->SetTrackElement(this);
 
   if (mMediaParent) {
     mMediaParent->AddTextTrack(mTrack);
   }
 }
 
 bool
 HTMLTrackElement::ParseAttribute(int32_t aNamespaceID,
--- a/content/html/content/src/TextTrackManager.cpp
+++ b/content/html/content/src/TextTrackManager.cpp
@@ -15,16 +15,69 @@
 #include "nsVideoFrame.h"
 #include "nsIFrame.h"
 #include "nsTArrayHelpers.h"
 #include "nsIWebVTTParserWrapper.h"
 
 namespace mozilla {
 namespace dom {
 
+CompareTextTracks::CompareTextTracks(HTMLMediaElement* aMediaElement)
+{
+  mMediaElement = aMediaElement;
+}
+
+int32_t
+CompareTextTracks::TrackChildPosition(TextTrack* aTextTrack) const {
+  HTMLTrackElement* trackElement = aTextTrack->GetTrackElement();
+  if (!trackElement) {
+    return -1;
+  }
+  return mMediaElement->IndexOf(trackElement);
+}
+
+bool
+CompareTextTracks::Equals(TextTrack* aOne, TextTrack* aTwo) const {
+  // Two tracks can never be equal. If they have corresponding TrackElements
+  // they would need to occupy the same tree position (impossible) and in the
+  // case of tracks coming from AddTextTrack source we put the newest at the
+  // last position, so they won't be equal as well.
+  return false;
+}
+
+bool
+CompareTextTracks::LessThan(TextTrack* aOne, TextTrack* aTwo) const
+{
+  TextTrackSource sourceOne = aOne->GetTextTrackSource();
+  TextTrackSource sourceTwo = aTwo->GetTextTrackSource();
+  if (sourceOne != sourceTwo) {
+    return sourceOne == Track ||
+           (sourceOne == AddTextTrack && sourceTwo == MediaResourceSpecific);
+  }
+  switch (sourceOne) {
+    case Track: {
+      int32_t positionOne = TrackChildPosition(aOne);
+      int32_t positionTwo = TrackChildPosition(aTwo);
+      // If either position one or positiontwo are -1 then something has gone
+      // wrong. In this case we should just put them at the back of the list.
+      return positionOne != -1 && positionTwo != -1 &&
+             positionOne < positionTwo;
+    }
+    case AddTextTrack:
+      // For AddTextTrack sources the tracks will already be in the correct relative
+      // order in the source array. Assume we're called in iteration order and can
+      // therefore always report aOne < aTwo to maintain the original temporal ordering.
+      return true;
+    case MediaResourceSpecific:
+      // No rules for Media Resource Specific tracks yet.
+      break;
+  }
+  return true;
+}
+
 NS_IMPL_CYCLE_COLLECTION_3(TextTrackManager, mTextTracks,
                            mPendingTextTracks, mNewCues)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(TextTrackManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(TextTrackManager, Release)
 
 StaticRefPtr<nsIWebVTTParserWrapper> TextTrackManager::sParserWrapper;
 
 TextTrackManager::TextTrackManager(HTMLMediaElement *aMediaElement)
@@ -53,29 +106,37 @@ TextTrackManager::~TextTrackManager()
 TextTrackList*
 TextTrackManager::TextTracks() const
 {
   return mTextTracks;
 }
 
 already_AddRefed<TextTrack>
 TextTrackManager::AddTextTrack(TextTrackKind aKind, const nsAString& aLabel,
-                               const nsAString& aLanguage)
+                               const nsAString& aLanguage,
+                               TextTrackSource aTextTrackSource)
 {
+  if (!mMediaElement) {
+    return nullptr;
+  }
   nsRefPtr<TextTrack> ttrack =
-    mTextTracks->AddTextTrack(aKind, aLabel, aLanguage);
+    mTextTracks->AddTextTrack(aKind, aLabel, aLanguage, aTextTrackSource,
+                              CompareTextTracks(mMediaElement));
   ttrack->SetReadyState(HTMLTrackElement::READY_STATE_LOADED);
   AddCues(ttrack);
   return ttrack.forget();
 }
 
 void
 TextTrackManager::AddTextTrack(TextTrack* aTextTrack)
 {
-  mTextTracks->AddTextTrack(aTextTrack);
+  if (!mMediaElement) {
+    return;
+  }
+  mTextTracks->AddTextTrack(aTextTrack, CompareTextTracks(mMediaElement));
   AddCues(aTextTrack);
 }
 
 void
 TextTrackManager::AddCues(TextTrack* aTextTrack)
 {
   TextTrackCueList* cueList = aTextTrack->GetCues();
   if (cueList) {
@@ -152,15 +213,16 @@ void
 TextTrackManager::PopulatePendingList()
 {
   uint32_t len = mTextTracks->Length();
   bool dummy;
   for (uint32_t index = 0; index < len; ++index) {
     TextTrack* ttrack = mTextTracks->IndexedGetter(index, dummy);
     if (ttrack && ttrack->Mode() != TextTrackMode::Disabled &&
         ttrack->ReadyState() == HTMLTrackElement::READY_STATE_LOADING) {
-      mPendingTextTracks->AddTextTrack(ttrack);
+      mPendingTextTracks->AddTextTrack(ttrack,
+                                       CompareTextTracks(mMediaElement));
     }
   }
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/src/TextTrackManager.h
+++ b/content/html/content/src/TextTrackManager.h
@@ -14,32 +14,44 @@
 #include "mozilla/StaticPtr.h"
 
 class nsIWebVTTParserWrapper;
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMediaElement;
+
+class CompareTextTracks {
+private:
+  HTMLMediaElement* mMediaElement;
+public:
+  CompareTextTracks(HTMLMediaElement* aMediaElement);
+  int32_t TrackChildPosition(TextTrack* aTrack) const;
+  bool Equals(TextTrack* aOne, TextTrack* aTwo) const;
+  bool LessThan(TextTrack* aOne, TextTrack* aTwo) const;
+};
+
 class TextTrack;
 class TextTrackCue;
 
 class TextTrackManager
 {
 public:
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(TextTrackManager)
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TextTrackManager);
 
   TextTrackManager(HTMLMediaElement *aMediaElement);
   ~TextTrackManager();
 
   TextTrackList* TextTracks() const;
   already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
                                            const nsAString& aLabel,
-                                           const nsAString& aLanguage);
+                                           const nsAString& aLanguage,
+                                           TextTrackSource aTextTrackSource);
   void AddTextTrack(TextTrack* aTextTrack);
   void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);
   void DidSeek();
 
   void AddCue(TextTrackCue& aCue);
   void AddCues(TextTrack* aTextTrack);
 
   /**
--- a/content/html/content/test/forms/mochitest.ini
+++ b/content/html/content/test/forms/mochitest.ini
@@ -49,35 +49,39 @@ skip-if = (toolkit == 'gonk' && debug) #
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_input_sanitization.html]
 [test_input_textarea_set_value_no_scroll.html]
 [test_input_typing_sanitization.html]
 [test_input_untrusted_key_events.html]
 [test_input_url.html]
 [test_label_control_attribute.html]
 [test_max_attribute.html]
+skip-if = e10s
 [test_maxlength_attribute.html]
 [test_meter_element.html]
 [test_meter_pseudo-classes.html]
 [test_min_attribute.html]
+skip-if = e10s
 [test_mozistextfield.html]
 [test_novalidate_attribute.html]
 [test_option_disabled.html]
 [test_option_index_attribute.html]
 [test_option_text.html]
 [test_output_element.html]
 [test_pattern_attribute.html]
 [test_progress_element.html]
 [test_required_attribute.html]
+skip-if = e10s
 [test_restore_form_elements.html]
 [test_save_restore_radio_groups.html]
 [test_select_selectedOptions.html]
 [test_set_range_text.html]
 [test_step_attribute.html]
+skip-if = e10s
 [test_stepup_stepdown.html]
 [test_submit_invalid_file.html]
 [test_textarea_attributes_reflection.html]
 [test_validation.html]
-skip-if = buildapp == 'b2g' # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
+skip-if = buildapp == 'b2g' || e10s # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
 [test_valueAsDate_pref.html]
 [test_valueasdate_attribute.html]
 [test_valueasnumber_attribute.html]
 [test_validation_not_in_doc.html]
--- a/content/html/content/test/mochitest.ini
+++ b/content/html/content/test/mochitest.ini
@@ -241,17 +241,17 @@ skip-if = buildapp == 'b2g' # b2g(13 fai
 [test_bug481335.xhtml]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(timed out, bug 870262, :visited support) b2g-debug(timed out, bug 870262, :visited support) b2g-desktop(timed out, bug 870262, :visited support)
 [test_bug500885.html]
 [test_bug514856.html]
 skip-if = toolkit == 'android'
 [test_bug518122.html]
 [test_bug519987.html]
 [test_bug523771.html]
-skip-if = buildapp == 'b2g' # b2g(onload of iframe not firing, because submit not working?) b2g-debug(onload of iframe not firing, because submit not working?) b2g-desktop(onload of iframe not firing, because submit not working?)
+skip-if = buildapp == 'b2g' || e10s # b2g(onload of iframe not firing, because submit not working?) b2g-debug(onload of iframe not firing, because submit not working?) b2g-desktop(onload of iframe not firing, because submit not working?)
 [test_bug529819.html]
 [test_bug529859.html]
 [test_bug535043.html]
 [test_bug536891.html]
 [test_bug536895.html]
 [test_bug546995.html]
 [test_bug547850.html]
 [test_bug551846.html]
@@ -265,17 +265,17 @@ skip-if = toolkit == 'android' #TIMED_OU
 [test_bug557087-5.html]
 [test_bug557087-6.html]
 [test_bug557620.html]
 [test_bug558788-1.html]
 [test_bug558788-2.html]
 [test_bug560112.html]
 [test_bug561634.html]
 [test_bug561636.html]
-skip-if = buildapp == 'b2g' # b2g(observerservice not working) b2g-debug(observerservice not working) b2g-desktop(observerservice not working)
+skip-if = buildapp == 'b2g' || e10s # b2g(observerservice not working) b2g-debug(observerservice not working) b2g-desktop(observerservice not working)
 [test_bug561640.html]
 [test_bug564001.html]
 [test_bug566046.html]
 [test_bug567938-1.html]
 [test_bug567938-2.html]
 [test_bug567938-3.html]
 [test_bug567938-4.html]
 [test_bug569955.html]
@@ -286,65 +286,75 @@ skip-if = buildapp == 'b2g' # b2g(observ
 [test_bug583514.html]
 [test_bug583533.html]
 [test_bug586763.html]
 [test_bug586786.html]
 [test_bug587469.html]
 [test_bug589.html]
 [test_bug590353-1.html]
 [test_bug590353-2.html]
+skip-if = e10s
 [test_bug590363.html]
 [test_bug592802.html]
 [test_bug593689.html]
 [test_bug595429.html]
+skip-if = e10s
 [test_bug595447.html]
 [test_bug595449.html]
-skip-if = (toolkit == 'gonk' && debug) #debug-only failure
+skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
 [test_bug596350.html]
 [test_bug596511.html]
 [test_bug598643.html]
+skip-if = e10s
 [test_bug598833-1.html]
 [test_bug600155.html]
 [test_bug601030.html]
 [test_bug605124-1.html]
 [test_bug605124-2.html]
 [test_bug605125-1.html]
 [test_bug605125-2.html]
 [test_bug606817.html]
 [test_bug607145.html]
 [test_bug610212.html]
 [test_bug610687.html]
 [test_bug611189.html]
 [test_bug612730.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-debug(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-desktop(form control not selected/checked with synthesizeMouse, also fails on Android)
 [test_bug613113.html]
-skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
+skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
 [test_bug613722.html]
 [test_bug613979.html]
 [test_bug615595.html]
 [test_bug615833.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-debug(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-desktop(form control not selected/checked with synthesizeMouse, also fails on Android)
 [test_bug617528.html]
 [test_bug618948.html]
-skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
+skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
 [test_bug619278.html]
-skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
+skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
 [test_bug622558.html]
+skip-if = e10s
 [test_bug622597.html]
-skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
+skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
 [test_bug623291.html]
+skip-if = e10s
 [test_bug6296.html]
+skip-if = e10s
 [test_bug629801.html]
+skip-if = e10s
 [test_bug633058.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_bug636336.html]
+skip-if = e10s
 [test_bug641219.html]
+skip-if = e10s
 [test_bug643051.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_bug646157.html]
+skip-if = e10s
 [test_bug649134.html]
 # This extra subdirectory is needed due to the nature of this test.
 # With the bug, the test loads the base URL of the bug649134/file_*.sjs
 # files, and the mochitest server responds with the contents of index.html if
 # it exists in that case, which we use to detect failure.
 # We cannot have index.html in this directory because it would prevent
 # running the tests here.
 support-files =
@@ -385,74 +395,76 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_bug803677.html]
 [test_bug827126.html]
 [test_bug827426.html]
 [test_bug838582.html]
 [test_bug839371.html]
 [test_bug839913.html]
 [test_bug840877.html]
 [test_bug841466.html]
-skip-if = (toolkit == 'gonk' && debug) #debug-only failure
+skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
 [test_bug845057.html]
 [test_bug869040.html]
 [test_bug870787.html]
 [test_bug874758.html]
 [test_bug879319.html]
 [test_bug885024.html]
 [test_bug893537.html]
 [test_bug969346.html]
 [test_change_crossorigin.html]
 [test_checked.html]
 [test_dir_attributes_reflection.html]
 [test_dl_attributes_reflection.html]
 [test_element_prototype.html]
 [test_embed_attributes_reflection.html]
 [test_formData.html]
 [test_formSubmission.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-debug(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-desktop(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-debug(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) b2g-desktop(NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
 [test_formSubmission2.html]
 skip-if = toolkit == 'android'
 [test_formelements.html]
 [test_fullscreen-api.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(time out, some kind of focus issue) b2g-debug(time out, some kind of focus issue) b2g-desktop(time out, some kind of focus issue)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(time out, some kind of focus issue) b2g-debug(time out, some kind of focus issue) b2g-desktop(time out, some kind of focus issue)
 [test_hidden.html]
 [test_html_attributes_reflection.html]
 [test_htmlcollection.html]
 [test_iframe_sandbox_general.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_iframe_sandbox_inheritance.html]
-skip-if = buildapp == 'b2g' # b2g(Crash, bug 904659) b2g-debug(Crash, bug 904659) b2g-desktop(Crash, bug 904659)
+skip-if = buildapp == 'b2g' || e10s # b2g(Crash, bug 904659) b2g-debug(Crash, bug 904659) b2g-desktop(Crash, bug 904659)
 [test_iframe_sandbox_modal.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #modal tests fail on android # b2g(modal tests fail on B2G) b2g-debug(modal tests fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #modal tests fail on android # b2g(modal tests fail on B2G) b2g-debug(modal tests fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_iframe_sandbox_navigation.html]
-skip-if = buildapp == 'b2g' # b2g(Crash, bug 904659) b2g-debug(Crash, bug 904659) b2g-desktop(Crash, bug 904659)
+skip-if = buildapp == 'b2g' || e10s # b2g(Crash, bug 904659) b2g-debug(Crash, bug 904659) b2g-desktop(Crash, bug 904659)
 [test_iframe_sandbox_navigation2.html]
-skip-if = buildapp == 'b2g' # b2g(Crash, bug 904659) b2g-debug(Crash, bug 904659) b2g-desktop(Crash, bug 904659)
+skip-if = buildapp == 'b2g' || e10s # b2g(Crash, bug 904659) b2g-debug(Crash, bug 904659) b2g-desktop(Crash, bug 904659)
 [test_iframe_sandbox_plugins.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
 [test_iframe_sandbox_popups.html]
-skip-if = buildapp == 'b2g' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
+skip-if = buildapp == 'b2g' || e10s # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_iframe_sandbox_popups_inheritance.html]
-skip-if = buildapp == 'b2g' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
+skip-if = buildapp == 'b2g' || e10s # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_iframe_sandbox_same_origin.html]
+skip-if = e10s
 [test_iframe_sandbox_workers.html]
+skip-if = e10s
 [test_img_attributes_reflection.html]
 [test_imageSrcSet.html]
 [test_li_attributes_reflection.html]
 [test_link_attributes_reflection.html]
 [test_map_attributes_reflection.html]
 [test_meta_attributes_reflection.html]
 [test_mod_attributes_reflection.html]
 [test_mozaudiochannel.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Perma-orange on debug emulator) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_named_options.html]
 [test_nested_invalid_fieldsets.html]
 [test_object_attributes_reflection.html]
 [test_object_plugin_nav.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
 [test_ol_attributes_reflection.html]
 [test_option_defaultSelected.html]
 [test_option_selected_state.html]
 [test_param_attributes_reflection.html]
 [test_q_attributes_reflection.html]
 [test_restore_from_parser_fragment.html]
 [test_rowscollection.html]
 [test_srcdoc-2.html]
--- a/content/html/document/test/mochitest.ini
+++ b/content/html/document/test/mochitest.ini
@@ -20,33 +20,33 @@ support-files =
   bug499092.xml
   bug499092.html
   test_non-ascii-cookie.html^headers^
 
 [test_bug1682.html]
 [test_bug1823.html]
 [test_bug57600.html]
 [test_bug196523.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_bug199692.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #bug 811644 #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' || e10s #bug 811644 #Bug 931116, b2g desktop specific, initial triage
 [test_bug172261.html]
 [test_bug255820.html]
 [test_bug259332.html]
 [test_bug311681.html]
 [test_bug311681.xhtml]
 [test_bug324378.html]
 [test_bug332848.xhtml]
 [test_bug340017.xhtml]
 [test_bug359657.html]
 [test_bug369370.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android'
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
 [test_bug380383.html]
 [test_bug391777.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_bug402680.html]
 [test_bug403868.html]
 [test_bug403868.xhtml]
 [test_bug435128.html]
 skip-if = true # Disabled for timeouts.
 [test_bug463104.html]
 [test_form-parsing.html]
 [test_viewport.html]
@@ -66,15 +66,15 @@ skip-if = toolkit == 'android'
 [test_bug486741.html]
 [test_bug489532.html]
 [test_bug497242.xhtml]
 [test_bug499092.html]
 [test_bug512367.html]
 [test_bug677495.html]
 [test_bug677495-1.html]
 [test_bug741266.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size)
 [test_non-ascii-cookie.html]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 [test_bug765780.html]
 [test_bug871161.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 support-files = file_bug871161-1.html file_bug871161-2.html
--- a/content/media/TextTrack.cpp
+++ b/content/media/TextTrack.cpp
@@ -11,55 +11,61 @@
 #include "mozilla/dom/TextTrackCueList.h"
 #include "mozilla/dom/TextTrackRegion.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLTrackElement.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_4(TextTrack,
+NS_IMPL_CYCLE_COLLECTION_INHERITED_5(TextTrack,
                                      nsDOMEventTargetHelper,
                                      mParent,
                                      mCueList,
                                      mActiveCueList,
-                                     mTextTrackList)
+                                     mTextTrackList,
+                                     mTrackElement)
 
 NS_IMPL_ADDREF_INHERITED(TextTrack, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(TextTrack, nsDOMEventTargetHelper)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrack)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
-TextTrack::TextTrack(nsISupports* aParent)
+TextTrack::TextTrack(nsISupports* aParent, TextTrackSource aTextTrackSource)
   : mParent(aParent)
+  , mTextTrackSource(aTextTrackSource)
 {
   SetDefaultSettings();
   SetIsDOMBinding();
 }
 
 TextTrack::TextTrack(nsISupports* aParent,
                      TextTrackKind aKind,
                      const nsAString& aLabel,
-                     const nsAString& aLanguage)
+                     const nsAString& aLanguage,
+                     TextTrackSource aTextTrackSource)
   : mParent(aParent)
+  , mTextTrackSource(aTextTrackSource)
 {
   SetDefaultSettings();
   mKind = aKind;
   mLabel = aLabel;
   mLanguage = aLanguage;
   SetIsDOMBinding();
 }
 
 TextTrack::TextTrack(nsISupports* aParent,
                      TextTrackList* aTextTrackList,
                      TextTrackKind aKind,
                      const nsAString& aLabel,
-                     const nsAString& aLanguage)
+                     const nsAString& aLanguage,
+                     TextTrackSource aTextTrackSource)
   : mParent(aParent)
   , mTextTrackList(aTextTrackList)
+  , mTextTrackSource(aTextTrackSource)
 {
   SetDefaultSettings();
   mKind = aKind;
   mLabel = aLabel;
   mLanguage = aLanguage;
   SetIsDOMBinding();
 }
 
@@ -206,10 +212,20 @@ TextTrack::GetTextTrackList()
 }
 
 void
 TextTrack::SetTextTrackList(TextTrackList* aTextTrackList)
 {
   mTextTrackList = aTextTrackList;
 }
 
+HTMLTrackElement*
+TextTrack::GetTrackElement() {
+  return mTrackElement;
+}
+
+void
+TextTrack::SetTrackElement(HTMLTrackElement* aTrackElement) {
+  mTrackElement = aTrackElement;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/content/media/TextTrack.h
+++ b/content/media/TextTrack.h
@@ -15,33 +15,43 @@
 
 namespace mozilla {
 namespace dom {
 
 class TextTrackList;
 class TextTrackCue;
 class TextTrackCueList;
 class TextTrackRegion;
+class HTMLTrackElement;
+
+enum TextTrackSource {
+  Track,
+  AddTextTrack,
+  MediaResourceSpecific
+};
 
 class TextTrack MOZ_FINAL : public nsDOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrack, nsDOMEventTargetHelper)
 
-  TextTrack(nsISupports* aParent);
+  TextTrack(nsISupports* aParent,
+            TextTrackSource aTextTrackSource);
   TextTrack(nsISupports* aParent,
             TextTrackKind aKind,
             const nsAString& aLabel,
-            const nsAString& aLanguage);
+            const nsAString& aLanguage,
+            TextTrackSource aTextTrackSource);
   TextTrack(nsISupports* aParent,
             TextTrackList* aTextTrackList,
             TextTrackKind aKind,
             const nsAString& aLabel,
-            const nsAString& aLanguage);
+            const nsAString& aLanguage,
+            TextTrackSource aTextTrackSource);
 
   void SetDefaultSettings();
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsISupports* GetParentObject() const
   {
@@ -94,33 +104,44 @@ public:
   void CueChanged(TextTrackCue& aCue);
   void SetDirty() { mDirty = true; }
 
   TextTrackList* GetTextTrackList();
   void SetTextTrackList(TextTrackList* aTextTrackList);
 
   IMPL_EVENT_HANDLER(cuechange)
 
+  HTMLTrackElement* GetTrackElement();
+  void SetTrackElement(HTMLTrackElement* aTrackElement);
+
+  TextTrackSource GetTextTrackSource() {
+    return mTextTrackSource;
+  }
+
 private:
   void UpdateActiveCueList();
 
   nsCOMPtr<nsISupports> mParent;
   nsRefPtr<TextTrackList> mTextTrackList;
 
   TextTrackKind mKind;
   nsString mLabel;
   nsString mLanguage;
   nsString mType;
   nsString mId;
   TextTrackMode mMode;
 
   nsRefPtr<TextTrackCueList> mCueList;
   nsRefPtr<TextTrackCueList> mActiveCueList;
+  nsRefPtr<HTMLTrackElement> mTrackElement;
 
   uint32_t mCuePos;
   uint16_t mReadyState;
   bool mDirty;
+
+  // An enum that represents where the track was sourced from.
+  TextTrackSource mTextTrackSource;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TextTrack_h
--- a/content/media/TextTrackList.cpp
+++ b/content/media/TextTrackList.cpp
@@ -59,27 +59,31 @@ TextTrackList::IndexedGetter(uint32_t aI
 {
   aFound = aIndex < mTextTracks.Length();
   return aFound ? mTextTracks[aIndex] : nullptr;
 }
 
 already_AddRefed<TextTrack>
 TextTrackList::AddTextTrack(TextTrackKind aKind,
                             const nsAString& aLabel,
-                            const nsAString& aLanguage)
+                            const nsAString& aLanguage,
+                            TextTrackSource aTextTrackSource,
+                            const CompareTextTracks& aCompareTT)
 {
-  nsRefPtr<TextTrack> track = new TextTrack(mGlobal, this, aKind, aLabel, aLanguage);
-  AddTextTrack(track);
+  nsRefPtr<TextTrack> track = new TextTrack(mGlobal, this, aKind, aLabel, aLanguage,
+                                            aTextTrackSource);
+  AddTextTrack(track, aCompareTT);
   return track.forget();
 }
 
 void
-TextTrackList::AddTextTrack(TextTrack* aTextTrack)
+TextTrackList::AddTextTrack(TextTrack* aTextTrack,
+                            const CompareTextTracks& aCompareTT)
 {
-  if (mTextTracks.AppendElement(aTextTrack)) {
+  if (mTextTracks.InsertElementSorted(aTextTrack, aCompareTT)) {
     aTextTrack->SetTextTrackList(this);
     CreateAndDispatchTrackEventRunner(aTextTrack, NS_LITERAL_STRING("addtrack"));
   }
 }
 
 TextTrack*
 TextTrackList::GetTrackById(const nsAString& aId)
 {
--- a/content/media/TextTrackList.h
+++ b/content/media/TextTrackList.h
@@ -11,16 +11,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMEventTargetHelper.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMediaElement;
 class TextTrackManager;
+class CompareTextTracks;
 class TrackEvent;
 class TrackEventRunner;
 
 class TextTrackList MOZ_FINAL : public nsDOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrackList, nsDOMEventTargetHelper)
@@ -43,20 +44,22 @@ public:
 
   // Get all the current active cues.
   void GetAllActiveCues(nsTArray<nsRefPtr<TextTrackCue> >& aCues);
 
   TextTrack* IndexedGetter(uint32_t aIndex, bool& aFound);
 
   already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
                                            const nsAString& aLabel,
-                                           const nsAString& aLanguage);
+                                           const nsAString& aLanguage,
+                                           TextTrackSource aTextTrackSource,
+                                           const CompareTextTracks& aCompareTT);
   TextTrack* GetTrackById(const nsAString& aId);
 
-  void AddTextTrack(TextTrack* aTextTrack);
+  void AddTextTrack(TextTrack* aTextTrack, const CompareTextTracks& aCompareTT);
 
   void RemoveTextTrack(TextTrack* aTrack);
   void DidSeek();
 
   HTMLMediaElement* GetMediaElement();
   void SetTextTrackManager(TextTrackManager* aTextTrackManager);
 
   nsresult DispatchTrackEvent(nsIDOMEvent* aEvent);
deleted file mode 100644
--- a/content/media/encoder/Makefile.in
+++ /dev/null
@@ -1,13 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-include $(topsrcdir)/config/rules.mk
-
-# These includes are from Android JB, for use of MediaCodec.
-INCLUDES	+= \
-		-I$(topsrcdir)/ipc/chromium/src \
-		-I$(ANDROID_SOURCE)/frameworks/native/opengl/include/ \
-		-I$(ANDROID_SOURCE)/frameworks/native/include/ \
-		-I$(ANDROID_SOURCE)/frameworks/av/include/media/ \
-		$(NULL)
--- a/content/media/encoder/moz.build
+++ b/content/media/encoder/moz.build
@@ -36,9 +36,19 @@ if CONFIG['MOZ_WEBM_ENCODER']:
                         'VP8TrackEncoder.cpp',
     ]
     LOCAL_INCLUDES += ['/media/libyuv/include']
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
 
+# These includes are from Android JB, for use of MediaCodec.
+LOCAL_INCLUDES += ['/ipc/chromium/src']
+CXXFLAGS += [
+    '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+        'frameworks/native/opengl/include',
+        'frameworks/native/include',
+        'frameworks/av/include/media',
+    ]
+]
+
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/content/media/mediasource/test/mochitest.ini
+++ b/content/media/mediasource/test/mochitest.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
+skip-if = e10s
 support-files = seek.webm seek.webm^headers^
 
 [test_MediaSource.html]
 skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined) b2g-debug( ReferenceError: MediaSource is not defined) b2g-desktop( ReferenceError: MediaSource is not defined)
--- a/content/media/omx/RtspOmxReader.cpp
+++ b/content/media/omx/RtspOmxReader.cpp
@@ -294,16 +294,28 @@ nsresult RtspOmxReader::Seek(int64_t aTi
 
   // Call |MediaOmxReader::Seek| to notify the OMX decoder we are performing a
   // seek operation. The function will clear the |mVideoQueue| and |mAudioQueue|
   // that store the decoded data and also call the |DecodeToTarget| to pass
   // the seek time to OMX a/v decoders.
   return MediaOmxReader::Seek(aTime, aStartTime, aEndTime, aCurrentTime);
 }
 
+nsresult
+RtspOmxReader::ReadMetadata(MediaInfo* aInfo,
+                            MetadataTags** aTags)
+{
+  nsresult rv = MediaOmxReader::ReadMetadata(aInfo, aTags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  SetActive();
+
+  return NS_OK;
+}
+
 void RtspOmxReader::SetIdle() {
   // Need to pause RTSP streaming OMXCodec decoding.
   if (mRtspResource) {
     nsIStreamingProtocolController* controller =
         mRtspResource->GetMediaStreamController();
     if (controller) {
       controller->Pause();
     }
@@ -314,17 +326,17 @@ void RtspOmxReader::SetIdle() {
 }
 
 void RtspOmxReader::SetActive() {
   // Need to start RTSP streaming OMXCodec decoding.
   if (mRtspResource) {
     nsIStreamingProtocolController* controller =
         mRtspResource->GetMediaStreamController();
     if (controller) {
-      controller->Play();  
+      controller->Play();
     }
   }
 
   // Call parent class to set OMXCodec active.
   MediaOmxReader::SetActive();
 }
 
 } // namespace mozilla
--- a/content/media/omx/RtspOmxReader.h
+++ b/content/media/omx/RtspOmxReader.h
@@ -39,16 +39,19 @@ public:
     mRtspResource = mDecoder->GetResource()->GetRtspPointer();
     MOZ_ASSERT(mRtspResource);
   }
 
   virtual ~RtspOmxReader() MOZ_OVERRIDE {
     MOZ_COUNT_DTOR(RtspOmxReader);
   }
 
+  virtual nsresult ReadMetadata(MediaInfo* aInfo,
+                                MetadataTags** aTags) MOZ_OVERRIDE;
+
   // Implement a time-based seek instead of byte-based..
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
                         int64_t aCurrentTime) MOZ_FINAL MOZ_OVERRIDE;
 
   // Override GetBuffered() to do nothing for below reasons:
   // 1. Because the Rtsp stream is a/v separated. The buffered data in a/v
   // tracks are not consistent with time stamp.
   // For example: audio buffer: 1~2s, video buffer: 1.5~2.5s
deleted file mode 100644
--- a/content/media/omx/mediaresourcemanager/Makefile.in
+++ /dev/null
@@ -1,14 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-include $(topsrcdir)/config/rules.mk
-
-CXXFLAGS += \
-		-I$(ANDROID_SOURCE)/frameworks/base/include/ \
-		-I$(ANDROID_SOURCE)/frameworks/base/include/binder/ \
-		-I$(ANDROID_SOURCE)/frameworks/base/include/utils/ \
-		-I$(ANDROID_SOURCE)/frameworks/base/include/media/ \
-		-I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright/openmax \
-		-I$(ANDROID_SOURCE)/frameworks/base/media/libstagefright/include/ \
-		$(NULL)
--- a/content/media/omx/mediaresourcemanager/moz.build
+++ b/content/media/omx/mediaresourcemanager/moz.build
@@ -9,9 +9,20 @@ SOURCES += [
     'IMediaResourceManagerDeathNotifier.cpp',
     'IMediaResourceManagerService.cpp',
     'MediaResourceManagerClient.cpp',
     'MediaResourceManagerService.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
+CXXFLAGS += [
+    '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+        'frameworks/base/include',
+        'frameworks/base/include/binder',
+        'frameworks/base/include/utils',
+        'frameworks/base/include/media/',
+        'frameworks/base/include/media/stagefright/openmax',
+        'frameworks/base/media/libstagefright/include',
+    ]
+]
+
 FINAL_LIBRARY = 'gklayout'
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -328,17 +328,17 @@ skip-if = buildapp == 'b2g' # b2g(timed 
 [test_contentDuration5.html]
 [test_contentDuration6.html]
 [test_contentDuration7.html]
 [test_can_play_type.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
 [test_can_play_type_mpeg.html]
 skip-if = buildapp == 'b2g' # b2g(7 failures out of 27) b2g-debug(7 failures out of 27) b2g-desktop(7 failures out of 27)
 [test_can_play_type_ogg.html]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 [test_can_play_type_no_ogg.html]
 [test_closing_connections.html]
 [test_constants.html]
 [test_controls.html]
 [test_currentTime.html]
 [test_decode_error.html]
 [test_defaultMuted.html]
 [test_delay_load.html]
--- a/content/media/test/test_texttrack.html
+++ b/content/media/test/test_texttrack.html
@@ -22,48 +22,89 @@ SpecialPowers.pushPrefEnv({"set": [["med
     var video = document.createElement("video");
 
     isnot(video.textTracks, undefined, "HTMLMediaElement::TextTrack() property should be available.")
 
     var trackList = video.textTracks;
     is(trackList.length, 0, "Length should be 0.");
 
     ok(typeof video.addTextTrack == "function", "HTMLMediaElement::AddTextTrack() function should be available.")
-    video.addTextTrack("subtitles", "label", "en-CA");
+    video.addTextTrack("subtitles", "third", "en-CA");
     is(trackList.length, 1, "Length should be 1.");
 
     var textTrack = video.textTracks[0];
-    is(textTrack.label, "label", "Label should be set to label.");
+    is(textTrack.label, "third", "Label should be set to third.");
     is(textTrack.language, "en-CA", "Language should be en-CA.");
     is(textTrack.kind, "subtitles", "Default kind should be subtitles.");
     is(textTrack.mode, "hidden", "Default mode should be hidden.");
 
     // Mode should not allow a bogus value.
     textTrack.mode = 'bogus';
     is(textTrack.mode, 'hidden', "Mode should be not allow a bogus value.");
 
     // Should allow all these values for mode.
     checkMode("showing", "Mode should allow \"showing\"");
     checkMode("disabled", "Mode should allow \"disabled\"");
     checkMode("hidden", "Mode should allow \"hidden\"");
 
     // All below are read-only properties and so should not allow setting.
     textTrack.label = "French subtitles";
-    is(textTrack.label, "label", "Label is read-only so should still be \"label\".");
+    is(textTrack.label, "third", "Label is read-only so should still be \"label\".");
 
     textTrack.language = "en";
     is(textTrack.language, "en-CA", "Language is read-only so should still be \"en-CA\".");
 
     textTrack.kind = "captions";
     is(textTrack.kind, "subtitles", "Kind is read-only so should still be \"subtitles\"");
 
     function checkMode(value, message) {
       textTrack.mode = value;
       is(textTrack.mode, value, message);
     }
 
-    SimpleTest.finish();
-  }
-);
+    // Test that text tracks are sorted correctly when being inserted on the
+    // MediaElements list of text tracks. For this test we add four tracks, the
+    // first one was at the start of the test, the next three are below.
+    var trackOne = document.createElement("track");
+    trackOne.label = "first";
+    trackOne.src = "basic.vtt";
+    video.appendChild(trackOne);
+
+    video.addTextTrack("subtitles", "fourth", "en-CA");
+
+    var trackTwo = document.createElement("track");
+    trackTwo.label = "second";
+    trackTwo.src = "basic.vtt";
+    video.appendChild(trackTwo);
+
+    video.src = "seek.webm";
+    video.preload = "auto";
+
+    document.getElementById("content").appendChild(video);
+
+    video.addEventListener("loadedmetadata", function run_tests() {
+      // Re-que run_tests() at the end of the event loop until the track
+      // element has loaded its data.
+      if (trackOne.readyState == 1 || trackTwo.readyState == 1) {
+        setTimeout(run_tests, 0);
+        return;
+      }
+      is(trackOne.readyState, 2, "First Track::ReadyState should be set to LOADED.");
+      is(trackTwo.readyState, 2, "Second Track::ReadyState should be set to LOADED.");
+
+      // For the tracks to be sorted the first two tracks, added through a
+      // TrackElement, must occupy the first two indexes in their TrackElement
+      // tree order. The second two tracks, added through the 'addTextTrack'
+      // method, will occupy the last two indexes in the order that they were
+      // added in.
+      var labels = [ "first", "second", "third", "fourth" ];
+      is(video.textTracks.length, labels.length, "TextTracks length should be " + labels.length);
+      for (var i = 0; i < video.textTracks.length; i++) {
+        isnot(video.textTracks[i], null, "Video should have a text track at " + i + " index.");
+        is(video.textTracks[i].label, labels[i], "Text track at " + i + " should be " + labels[i]);
+      }
+      SimpleTest.finish();
+    });
+});
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/webspeech/recognition/test/mochitest.ini
+++ b/content/media/webspeech/recognition/test/mochitest.ini
@@ -5,15 +5,15 @@ support-files =
   hello.ogg^headers^
   silence.ogg
   silence.ogg^headers^
 
 [test_abort.html]
 [test_audio_capture_error.html]
 [test_call_start_from_end_handler.html]
 [test_nested_eventloop.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_preference_enable.html]
 [test_recognition_service_error.html]
 skip-if = buildapp == 'b2g' # b2g(timed out) b2g-debug(timed out) b2g-desktop(timed out)
 [test_success_without_recognition_service.html]
 [test_timeout.html]
 skip-if = os == "win"
--- a/content/media/webspeech/synth/ipc/test/mochitest.ini
+++ b/content/media/webspeech/synth/ipc/test/mochitest.ini
@@ -1,4 +1,5 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_ipc.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 857673 # b2g(comp.classes['@mozilla.org/special-powers-observer;1'] is undefined) b2g-debug(comp.classes['@mozilla.org/special-powers-observer;1'] is undefined) b2g-desktop(comp.classes['@mozilla.org/special-powers-observer;1'] is undefined)
--- a/content/media/webspeech/synth/test/mochitest.ini
+++ b/content/media/webspeech/synth/test/mochitest.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
+skip-if = e10s
 support-files = common.js
 
 [test_setup.html]
 [test_speech_queue.html]
 skip-if = buildapp == 'b2g' # b2g(Test timed out) b2g-debug(Test timed out) b2g-desktop(Test timed out)
 [test_speech_simple.html]
 skip-if = buildapp == 'b2g' # b2g(Test timed out) b2g-debug(Test timed out) b2g-desktop(Test timed out)
--- a/content/xml/document/test/mochitest.ini
+++ b/content/xml/document/test/mochitest.ini
@@ -3,14 +3,14 @@ support-files =
   file_bug293347.xml
   file_bug293347xslt.xml
 
 [test_bug232004.xhtml]
 [test_bug293347.html]
 [test_bug343870.xhtml]
 [test_bug355213.xhtml]
 [test_bug392338.html]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 [test_bug399502.xhtml]
 [test_bug445330.html]
 [test_bug691215.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_viewport.xhtml]
--- a/docshell/test/iframesandbox/mochitest.ini
+++ b/docshell/test/iframesandbox/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   file_other_auxiliary_navigation_by_location.html
   file_our_auxiliary_navigation_by_location.html
   file_parent_navigation_by_location.html
   file_sibling_navigation_by_location.html
   file_top_navigation_by_location.html
   file_top_navigation_by_location_exotic.html
 
--- a/docshell/test/mochitest.ini
+++ b/docshell/test/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   bug123696-subframe.html
   bug369814.jar
   bug369814.zip
   bug404548-subframe.html
   bug413310-post.sjs
   bug413310-subframe.html
   bug529119-window.html
--- a/docshell/test/navigation/mochitest.ini
+++ b/docshell/test/navigation/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   NavigationUtils.js
   blank.html
   file_bug462076_1.html
   file_bug462076_2.html
   file_bug462076_3.html
   file_bug508537_1.html
   file_bug534178.html
--- a/dom/alarm/test/mochitest.ini
+++ b/dom/alarm/test/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_alarm_add_data.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_alarm_add_date.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_alarm_add_respectTimezone.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_alarm_non_permitted_app.html]
--- a/dom/apps/tests/mochitest.ini
+++ b/dom/apps/tests/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = toolkit=='gonk' #b2g(bug 972927, nearly perma-fail) b2g-debug(bug 972927, nearly perma-fail)
+skip-if = toolkit=='gonk' || e10s #b2g(bug 972927, nearly perma-fail) b2g-debug(bug 972927, nearly perma-fail)
 support-files =
   file_app.sjs
   file_app.template.html
   file_cached_app.template.appcache
   file_cached_app.template.webapp
   file_hosted_app.template.webapp
   file_packaged_app.sjs
   file_packaged_app.template.html
--- a/dom/battery/test/mochitest.ini
+++ b/dom/battery/test/mochitest.ini
@@ -1,4 +1,5 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_battery_basics.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
--- a/dom/browser-element/mochitest/mochitest-oop.ini
+++ b/dom/browser-element/mochitest/mochitest-oop.ini
@@ -1,14 +1,14 @@
 [DEFAULT]
 # Both the "inproc" and "oop" versions of OpenMixedProcess open remote frames,
 # so we don't run that test on platforms which don't support OOP tests.
 # OOP tests don't work on native-fennec (bug 774939).
 # Bug 960345 - Disabled on OSX debug for frequent crashes.
-skip-if = os == "android" || (toolkit == "cocoa" && debug) || (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
+skip-if = os == "android" || (toolkit == "cocoa" && debug) || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
 support-files =
   browserElement_OpenMixedProcess.js
   file_browserElement_OpenMixedProcess.html
 
 [test_browserElement_inproc_ErrorSecurity.html]
 skip-if = toolkit=='gonk'
 [test_browserElement_inproc_OpenMixedProcess.html]
 skip-if = toolkit=='gonk' || (toolkit == 'gonk' && !debug)
--- a/dom/browser-element/mochitest/mochitest.ini
+++ b/dom/browser-element/mochitest/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
 support-files =
   ../../../browser/base/content/test/general/audio.ogg
   ../../../content/media/test/short-video.ogv
   browserElementTestHelpers.js
   browserElement_Alert.js
   browserElement_AlertInFrame.js
   browserElement_AppFramePermission.js
   browserElement_AppWindowNamespace.js
--- a/dom/browser-element/mochitest/priority/mochitest.ini
+++ b/dom/browser-element/mochitest/priority/mochitest.ini
@@ -1,11 +1,11 @@
 [DEFAULT]
 # Good luck running these tests on anything but desktop Linux.
-skip-if = toolkit != "gtk2" || (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
+skip-if = toolkit != "gtk2" || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
 
 # Note: ../browserElementTestHelpers.js makes all tests in this directory OOP,
 # because testing the process-priority manager without OOP frames does not make
 # much sense.
 
 [test_Simple.html]
 [test_Visibility.html]
 [test_HighPriority.html]
--- a/dom/contacts/tests/mochitest.ini
+++ b/dom/contacts/tests/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 
 [shared.js]
 [test_contacts_basics.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
 [test_contacts_basics2.html]
 [test_contacts_blobs.html]
 [test_contacts_events.html]
 [test_contacts_getall.html]
--- a/dom/datastore/tests/mochitest.ini
+++ b/dom/datastore/tests/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = toolkit=='gonk' #b2g(bug 974270, frequent failures) b2g-debug(bug 974270, frequent failures)
+skip-if = toolkit=='gonk' || e10s #b2g(bug 974270, frequent failures) b2g-debug(bug 974270, frequent failures)
 support-files =
   file_app_install.html
   file_readonly.html
   file_basic.html
   file_changes.html
   file_changes2.html
   file_app.sjs
   file_app.template.webapp
--- a/dom/devicestorage/ipc/mochitest.ini
+++ b/dom/devicestorage/ipc/mochitest.ini
@@ -1,6 +1,6 @@
 [DEFAULT]
-skip-if = toolkit == 'android' #bug 781789 & bug 782275
+skip-if = toolkit == 'android' || e10s #bug 781789 & bug 782275
 support-files = ../test/devicestorage_common.js
 
 [test_ipc.html]
 skip-if = buildapp == 'b2g' # b2g(nested ipc not working) b2g-debug(nested ipc not working) b2g-desktop(nested ipc not working)
--- a/dom/devicestorage/test/mochitest.ini
+++ b/dom/devicestorage/test/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = toolkit == 'android' #bug 781789 & bug 782275
+skip-if = toolkit == 'android' || e10s #bug 781789 & bug 782275
 support-files = devicestorage_common.js
 
 [test_823965.html]
 # [test_add.html]
 # man, our mime database sucks hard.  followup bug # 788273
 [test_addCorrectType.html]
 [test_available.html]
 [test_basic.html]
--- a/dom/encoding/test/mochitest.ini
+++ b/dom/encoding/test/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   file_utf16_be_bom.css
   file_utf16_be_bom.js
   file_utf16_be_bom.xhtml
   file_utf16_le_bom.css
   file_utf16_le_bom.js
   file_utf16_le_bom.xhtml
   file_utf16_le_nobom.xhtml
--- a/dom/encoding/test/unit/mochitest.ini
+++ b/dom/encoding/test/unit/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_big5.js]
 [test_euc-jp.js]
 [test_euc-kr.js]
 [test_gbk.js]
 [test_hz-gb-2312.js]
 [test_iso-2022-jp.js]
 [test_shift_jis.js]
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -18,50 +18,50 @@ support-files =
 [test_bug226361.xhtml]
 skip-if = buildapp == 'b2g'
 [test_bug238987.html]
 skip-if = buildapp == 'b2g'
 [test_bug288392.html]
 [test_bug299673-1.html]
 [test_bug299673-2.html]
 [test_bug322588.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_bug328885.html]
 [test_bug336682.js]
 [test_bug336682_1.html]
 [test_bug367781.html]
 [test_bug368835.html]
 [test_bug379120.html]
 [test_bug391568.xhtml]
 [test_bug402089.html]
 [test_bug405632.html]
 [test_bug409604.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_bug412567.html]
 [test_bug422132.html]
-skip-if = buildapp == 'b2g' # b2g(2 failures out of 8, mousewheel test) b2g-debug(2 failures out of 8, mousewheel test) b2g-desktop(2 failures out of 8, mousewheel test)
+skip-if = buildapp == 'b2g' || e10s # b2g(2 failures out of 8, mousewheel test) b2g-debug(2 failures out of 8, mousewheel test) b2g-desktop(2 failures out of 8, mousewheel test)
 [test_bug426082.html]
-skip-if = buildapp == 'b2g' || os == "win" || toolkit == 'android' # Intermittent failures, bug 921693 # b2g(1 failure out of 6, Moving the mouse down from the label should have unpressed the button) b2g-debug(1 failure out of 6, Moving the mouse down from the label should have unpressed the button) b2g-desktop(1 failure out of 6, Moving the mouse down from the label should have unpressed the button)
+skip-if = buildapp == 'b2g' || os == "win" || toolkit == 'android' || e10s # Intermittent failures, bug 921693 # b2g(1 failure out of 6, Moving the mouse down from the label should have unpressed the button) b2g-debug(1 failure out of 6, Moving the mouse down from the label should have unpressed the button) b2g-desktop(1 failure out of 6, Moving the mouse down from the label should have unpressed the button)
 [test_bug427537.html]
 [test_bug428988.html]
 [test_bug432698.html]
 [test_bug443985.html]
 [test_bug447736.html]
 [test_bug448602.html]
 [test_bug450876.html]
 [test_bug456273.html]
 [test_bug457672.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug489671.html]
 [test_bug493251.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug502818.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug508479.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #CRASH_DUMP, RANDOM # b2g(drag event, also fails on Android) b2g-debug(drag event, also fails on Android) b2g-desktop(drag event, also fails on Android)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #CRASH_DUMP, RANDOM # b2g(drag event, also fails on Android) b2g-debug(drag event, also fails on Android) b2g-desktop(drag event, also fails on Android)
 [test_bug822898.html]
 [test_bug517851.html]
 [test_bug534833.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #CRASH_DUMP, RANDOM # b2g(4 failures out of 6, bug 901564,click not fired, also disabled on Android) b2g-debug(4 failures out of 6, bug 901564,click not fired, also disabled on Android) b2g-desktop(4 failures out of 6, bug 901564,click not fired, also disabled on Android)
 [test_bug545268.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #CRASH_DUMP, RANDOM #Bug 931116, b2g desktop specific, initial triage
 [test_bug547996-1.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
@@ -90,17 +90,17 @@ skip-if = toolkit == 'android' #CRASH_DU
 [test_bug635465.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug641477.html]
 [test_bug648573.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug650493.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug656379-1.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #TIMED_OUT #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' || e10s #TIMED_OUT #Bug 931116, b2g desktop specific, initial triage
 [test_bug656379-2.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug656954.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug659071.html]
 skip-if = buildapp == 'b2g' # b2g(1 failure out of 2, mousewheel zoom test) b2g-debug(1 failure out of 2, mousewheel zoom test) b2g-desktop(1 failure out of 2, mousewheel zoom test)
 [test_bug659350.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
@@ -126,29 +126,29 @@ skip-if = buildapp == 'b2g' # b2g(failin
 [test_bug944847.html]
 [test_bug967796.html]
 skip-if = toolkit == "gonk"
 [test_bug944011.html]
 [test_bug946632.html]
 [test_clickevent_on_input.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_continuous_wheel_events.html]
-skip-if = buildapp == 'b2g' # b2g(5535 passed, 108 failed - more tests running than desktop) b2g-debug(5535 passed, 108 failed - more tests running than desktop) b2g-desktop(5535 passed, 108 failed - more tests running than desktop)
+skip-if = buildapp == 'b2g' || e10s # b2g(5535 passed, 108 failed - more tests running than desktop) b2g-debug(5535 passed, 108 failed - more tests running than desktop) b2g-desktop(5535 passed, 108 failed - more tests running than desktop)
 [test_dblclick_explicit_original_target.html]
 [test_dom_keyboard_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_mouse_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_wheel_event.html]
-skip-if = buildapp == 'b2g' # b2g(456 failed out of 19873, mousewheel test) b2g-debug(456 failed out of 19873, mousewheel test) b2g-desktop(456 failed out of 19873, mousewheel test)
+skip-if = buildapp == 'b2g' || e10s # b2g(456 failed out of 19873, mousewheel test) b2g-debug(456 failed out of 19873, mousewheel test) b2g-desktop(456 failed out of 19873, mousewheel test)
 [test_draggableprop.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dragstart.html]
 skip-if = buildapp == 'b2g' # b2g(drag event, also fails on Android) b2g-debug(drag event, also fails on Android) b2g-desktop(drag event, also fails on Android)
 [test_error_events.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_eventctors.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_focus_disabled.html]
 [test_messageEvent.html]
 [test_moz_mouse_pixel_scroll_event.html]
 [test_wheel_default_action.html]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
--- a/dom/file/test/mochitest.ini
+++ b/dom/file/test/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   dummy_worker.js
   helpers.js
 
 [test_append_read_data.html]
 skip-if = buildapp == 'b2g'
 [test_archivereader.html]
 skip-if = buildapp == 'b2g'
--- a/dom/indexedDB/ipc/mochitest.ini
+++ b/dom/indexedDB/ipc/mochitest.ini
@@ -1,4 +1,4 @@
 [DEFAULT]
 
 [test_ipc.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 783513 # b2g(nested ipc not working) b2g-debug(nested ipc not working) b2g-desktop(nested ipc not working)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 783513 # b2g(nested ipc not working) b2g-debug(nested ipc not working) b2g-desktop(nested ipc not working)
--- a/dom/indexedDB/test/mochitest.ini
+++ b/dom/indexedDB/test/mochitest.ini
@@ -156,17 +156,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_open_objectStore.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_optionalArguments.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_overlapping_transactions.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_persistenceType.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_put_get_values.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_put_get_values_autoIncrement.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_readonly_transactions.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_remove_index.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
--- a/dom/inputmethod/mochitest/mochitest.ini
+++ b/dom/inputmethod/mochitest/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = toolkit == 'android' #Not supported on Android
+skip-if = toolkit == 'android' || e10s #Not supported on Android
 support-files =
   inputmethod_common.js
   file_inputmethod.html
   file_test_app.html
   file_test_sendkey_cancel.html
 
 [test_basic.html]
 [test_bug944397.html]
--- a/dom/media/tests/identity/mochitest.ini
+++ b/dom/media/tests/identity/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   /.well-known/idp-proxy/idp.html
   /.well-known/idp-proxy/idp-proxy.js
 
 # All tests are disabled on android due to lack of https support in mochitest
 # (Bug 975149)
 # All tests are disabled on b2g due to lack of e10s support in WebRTC identity
 # (Bug 975144)
--- a/dom/media/tests/ipc/mochitest.ini
+++ b/dom/media/tests/ipc/mochitest.ini
@@ -1,4 +1,5 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_ipc.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 910661 # b2g(nested ipc not working) b2g-debug(debug-only failure) b2g-desktop(nested ipc not working)
--- a/dom/mobilemessage/tests/mochitest.ini
+++ b/dom/mobilemessage/tests/mochitest.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_sms_basics.html]
 skip-if = toolkit == 'android' #Bug 909036
 [test_smsfilter.html]
--- a/dom/network/tests/mochitest.ini
+++ b/dom/network/tests/mochitest.ini
@@ -1,16 +1,16 @@
 [test_network_basics.html]
 skip-if = toolkit == "gonk" || toolkit == 'android'
 [test_tcpsocket_default_permissions.html]
 skip-if = toolkit == "gonk"
 [test_tcpsocket_enabled_no_perm.html]
 skip-if = toolkit == "gonk"
 [test_tcpsocket_enabled_with_perm.html]
-skip-if = toolkit == "gonk"
+skip-if = toolkit == "gonk" || e10s
 [test_networkstats_alarms.html]
 skip-if = toolkit != "gonk"
 [test_networkstats_basics.html]
 skip-if = toolkit != "gonk" || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Will be fixed in bug 858005) b2g-desktop(Will be fixed in bug 858005)
 [test_networkstats_disabled.html]
 skip-if = toolkit != "gonk"
 [test_networkstats_enabled_no_perm.html]
 skip-if = toolkit != "gonk"
--- a/dom/permission/tests/mochitest.ini
+++ b/dom/permission/tests/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   file_framework.js
   file_shim.html
 
 [test_alarms.html]
 [test_browser.html]
 [test_embed-apps.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
--- a/dom/phonenumberutils/tests/mochitest.ini
+++ b/dom/phonenumberutils/tests/mochitest.ini
@@ -1,3 +1,4 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_phonenumberutils_basics.html]
--- a/dom/plugins/test/mochitest/mochitest.ini
+++ b/dom/plugins/test/mochitest/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #b2g-desktop(tests that use plugins)
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #b2g-desktop(tests that use plugins)
 support-files =
   307-xo-redirect.sjs
   crashing_subpage.html
   file_bug738396.html
   file_bug771202.html
   file_bug863792.html
   large-pic.jpg
   loremipsum.txt
--- a/dom/power/test/mochitest.ini
+++ b/dom/power/test/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_bug957893.html]
 [test_bug957899.html]
 [test_wakelock_not_exposed.html]
 run-if = appname != "b2g"
 [test_power_basics.html]
 [test_power_set_cpusleepallowed.html]
 skip-if = toolkit != "gonk"
--- a/dom/settings/tests/mochitest.ini
+++ b/dom/settings/tests/mochitest.ini
@@ -1,9 +1,9 @@
 [DEFAULT]
-skip-if = (toolkit == 'gonk' && debug) #debug-only failure, bug 932878
+skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure, bug 932878
 
 [test_settings_basics.html]
 [test_settings_blobs.html]
 [test_settings_data_uris.html]
 [test_settings_events.html]
 [test_settings_navigator_object.html]
 [test_settings_onsettingchange.html]
--- a/dom/src/json/test/mochitest.ini
+++ b/dom/src/json/test/mochitest.ini
@@ -1,3 +1,4 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_json.html]
--- a/dom/src/jsurl/test/mochitest.ini
+++ b/dom/src/jsurl/test/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   fail.html
   form-submit.html
   load-stopping-1a.html
   load-stopping-1b.html
   load-stopping-1c.html
   load-stopping-1d.html
   pass.html
--- a/dom/tests/mochitest/ajax/jquery/mochitest.ini
+++ b/dom/tests/mochitest/ajax/jquery/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   manifest.json
   dist/jquery.js
   test/index.html
   test/offset.html
   test/test.js
   test/fix.html
   test/data/cow.jpg
--- a/dom/tests/mochitest/ajax/mochikit/mochitest.ini
+++ b/dom/tests/mochitest/ajax/mochikit/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   manifest.json
   MochiKit/Async.js
   MochiKit/Base.js
   MochiKit/Color.js
   MochiKit/Controls.js
   MochiKit/DOM.js
   MochiKit/DateTime.js
--- a/dom/tests/mochitest/ajax/mochikit/tests/mochitest.ini
+++ b/dom/tests/mochitest/ajax/mochikit/tests/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   FakeJSAN.js
   MochiKit-Async.html
   MochiKit-Base.html
   MochiKit-Color.html
   MochiKit-DOM.html
   MochiKit-DateTime.html
   MochiKit-DragAndDrop.html
--- a/dom/tests/mochitest/ajax/offline/mochitest.ini
+++ b/dom/tests/mochitest/ajax/offline/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = toolkit == 'android' #SLOW_DIRECTORY
+skip-if = toolkit == 'android' || e10s #SLOW_DIRECTORY
 support-files =
   445544.cacheManifest
   445544.cacheManifest^headers^
   445544_part1.html
   445544_part2.html
   460353_iframe_nomanifest.html
   460353_iframe_ownmanifest.html
   460353_iframe_samemanifest.html
--- a/dom/tests/mochitest/ajax/prototype/mochitest.ini
+++ b/dom/tests/mochitest/ajax/prototype/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   manifest.json
   dist/prototype.js
   test/browser.html
   test/console.html
   test/test.css
   test/functional/event.html
   test/lib/unittest.js
--- a/dom/tests/mochitest/ajax/scriptaculous/mochitest.ini
+++ b/dom/tests/mochitest/ajax/scriptaculous/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   manifest.json
   lib/prototype.js
   src/builder.js
   src/controls.js
   src/dragdrop.js
   src/effects.js
   src/scriptaculous.js
--- a/dom/tests/mochitest/bugs/mochitest.ini
+++ b/dom/tests/mochitest/bugs/mochitest.ini
@@ -33,75 +33,75 @@ support-files =
   utils_bug743615.js
   worker_bug743615.js
   file_bug927901.html
 
 [test_DOMWindowCreated_chromeonly.html]
 [test_bug132255.html]
 [test_bug159849.html]
 [test_bug260264.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(dom.disable_open_during_load not implemented in b2g) b2g-debug(dom.disable_open_during_load not implemented in b2g) b2g-desktop(dom.disable_open_during_load not implemented in b2g)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(dom.disable_open_during_load not implemented in b2g) b2g-debug(dom.disable_open_during_load not implemented in b2g) b2g-desktop(dom.disable_open_during_load not implemented in b2g)
 [test_bug260264_nested.html]
-skip-if = buildapp == 'b2g' # b2g(dom.disable_open_during_load not implemented in b2g) b2g-debug(dom.disable_open_during_load not implemented in b2g) b2g-desktop(dom.disable_open_during_load not implemented in b2g)
+skip-if = buildapp == 'b2g' || e10s # b2g(dom.disable_open_during_load not implemented in b2g) b2g-debug(dom.disable_open_during_load not implemented in b2g) b2g-desktop(dom.disable_open_during_load not implemented in b2g)
 [test_bug265203.html]
 [test_bug291377.html]
 [test_bug291653.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_bug304459.html]
 [test_bug308856.html]
 [test_bug327891.html]
 [test_bug333983.html]
 [test_bug335976.xhtml]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_bug342448.html]
 [test_bug345521.html]
 [test_bug346659.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug351601.html]
 [test_bug369306.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #TIMED_OUT # b2g-debug(test timed out, can't focus back from popup window to opener?) b2g-desktop(test timed out, can't focus back from popup window to opener?)
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(test timed out, can't focus back from popup window to opener?) b2g-desktop(test timed out, can't focus back from popup window to opener?)
 [test_bug370098.html]
 [test_bug377539.html]
 [test_bug384122.html]
 [test_bug389366.html]
 [test_bug38959.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug393974.html]
 [test_bug394769.html]
 [test_bug396843.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_bug397571.html]
 [test_bug400204.html]
 [test_bug404748.html]
 [test_bug406375.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android'
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
 [test_bug411103.html]
 [test_bug414291.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_bug427744.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android'
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
 [test_bug42976.html]
 [test_bug430276.html]
 [test_bug437361.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(dom.disable_open_during_load not implemented in b2g, showmodaldialog) b2g-debug(dom.disable_open_during_load not implemented in b2g, showmodaldialog) b2g-desktop(dom.disable_open_during_load not implemented in b2g, showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(dom.disable_open_during_load not implemented in b2g, showmodaldialog) b2g-debug(dom.disable_open_during_load not implemented in b2g, showmodaldialog) b2g-desktop(dom.disable_open_during_load not implemented in b2g, showmodaldialog)
 [test_bug440572.html]
 [test_bug456151.html]
 [test_bug458091.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug459848.html]
 [test_bug465263.html]
 [test_bug479143.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_bug484775.html]
 [test_bug492925.html]
 [test_bug49312.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug495219.html]
 [test_bug504862.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #RANDOM # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #RANDOM # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_bug529328.html]
 [test_bug531176.html]
 [test_bug531542.html]
 [test_bug534149.html]
 [test_bug541530.html]
 [test_bug545314.html]
 [test_bug548828.html]
 [test_bug558973.html]
@@ -110,27 +110,27 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_bug563487.html]
 [test_bug581072.html]
 [test_bug583225.html]
 [test_bug585240.html]
 [test_bug585819.html]
 [test_bug593174.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug597809.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug61098.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_bug612267.html]
 [test_bug617296.html]
 [test_bug620947.html]
 [test_bug622361.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug633133.html]
 [test_bug641552.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android'
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s
 [test_bug642026.html]
 [test_bug648465.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug654137.html]
 [test_bug664737.html]
 [test_bug665548.html]
 [test_bug684544.html]
 [test_bug691707.html]
@@ -149,19 +149,19 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_bug823173.html]
 [test_bug848088.html]
 [test_bug850517.html]
 [test_bug857555.html]
 [test_bug862540.html]
 [test_bug876098.html]
 [test_bug927901.html]
 [test_devicemotion_multiple_listeners.html]
-skip-if = toolkit == 'android' #bug 775227
+skip-if = toolkit == 'android' || e10s #bug 775227
 [test_domparser_after_blank.html]
 [test_onerror_message.html]
 [test_protochains.html]
 [test_resize_move_windows.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #Windows can't change size and position on Android # b2g(Windows can't change size and position on B2G) b2g-debug(Windows can't change size and position on B2G) b2g-desktop(Windows can't change size and position on B2G)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #Windows can't change size and position on Android # b2g(Windows can't change size and position on B2G) b2g-debug(Windows can't change size and position on B2G) b2g-desktop(Windows can't change size and position on B2G)
 [test_sizetocontent_clamp.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #Windows can't change size on Android # b2g(Windows can't change size on B2G) b2g-debug(Windows can't change size on B2G) b2g-desktop(Windows can't change size on B2G)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #Windows can't change size on Android # b2g(Windows can't change size on B2G) b2g-debug(Windows can't change size on B2G) b2g-desktop(Windows can't change size on B2G)
 [test_toJSON.html]
 [test_window_bar.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android'
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
--- a/dom/tests/mochitest/crypto/mochitest-legacy.ini
+++ b/dom/tests/mochitest/crypto/mochitest-legacy.ini
@@ -1,1 +1,2 @@
 [test_legacy.html]
+skip-if = e10s
--- a/dom/tests/mochitest/crypto/mochitest-no-legacy.ini
+++ b/dom/tests/mochitest/crypto/mochitest-no-legacy.ini
@@ -1,1 +1,2 @@
 [test_no_legacy.html]
+skip-if = e10s
--- a/dom/tests/mochitest/crypto/mochitest.ini
+++ b/dom/tests/mochitest/crypto/mochitest.ini
@@ -1,3 +1,4 @@
 [DEFAULT]
+skip-if = e10s
 
 [test_getRandomValues.html]
--- a/dom/tests/mochitest/gamepad/mochitest.ini
+++ b/dom/tests/mochitest/gamepad/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   gamepad_frame.html
   gamepad_frame_state.html
   mock_gamepad.js
 
 [test_gamepad.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_gamepad_connect_events.html]
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   497633.html
   file_MozEnteredDomFullscreen.html
   file_bug628069.html
   file_clonewrapper.html
   file_domWindowUtils_scrollbarSize.html
   file_frameElementWrapping.html
   file_interfaces.xml
--- a/dom/tests/mochitest/geolocation/mochitest.ini
+++ b/dom/tests/mochitest/geolocation/mochitest.ini
@@ -5,46 +5,46 @@ support-files =
   network_geolocation.sjs
   windowTest.html
 
 [test_allowCurrent.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(Bug 910235 - Error: no message manager set when calling method: [nsIObserver::observe]) b2g-debug(Bug 910235 - Error: no message manager set when calling method: [nsIObserver::observe]) b2g-desktop(Bug 910235 - Error: no message manager set when calling method: [nsIObserver::observe])
 [test_allowWatch.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_cachedPosition.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT
 [test_cancelCurrent.html]
 skip-if = buildapp == 'b2g'
 [test_cancelWatch.html]
 skip-if = buildapp == 'b2g'
 [test_clearWatch.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_clearWatch_invalid.html]
 skip-if = buildapp == 'b2g'
 [test_errorcheck.html]
-skip-if = toolkit=='gonk' || toolkit == 'android' #TIMED_OUT # b2g-debug(debug-only timeout)
+skip-if = toolkit=='gonk' || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(debug-only timeout)
 [test_geolocation_is_undefined_when_pref_is_off.html]
 [test_handlerSpinsEventLoop.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #Don't run modal tests on Android # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #Don't run modal tests on Android # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_manyCurrentConcurrent.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_manyCurrentSerial.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_manyWatchConcurrent.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_manyWatchSerial.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_manyWindows.html]
 skip-if = buildapp == 'b2g'
 [test_mozsettings.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #mozSettings is undefined
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #mozSettings is undefined
 [test_mozsettingsWatch.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #mozSettings is undefined
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #mozSettings is undefined
 [test_optional_api_params.html]
 skip-if = buildapp == 'b2g'
 [test_shutdown.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_timerRestartWatch.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT
 [test_windowClose.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_worseAccuracyDoesNotBlockCallback.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
--- a/dom/tests/mochitest/localstorage/mochitest.ini
+++ b/dom/tests/mochitest/localstorage/mochitest.ini
@@ -25,17 +25,17 @@ skip-if = buildapp == 'b2g' || toolkit =
 skip-if = os == "android" # bug 962029
 [test_cookieBlock.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(bug 913706) b2g-desktop(bug 913706)
 [test_cookieSession.html]
 skip-if = toolkit=='gonk' # b2g(4 failures) b2g-debug(debug-only failure)
 [test_embededNulls.html]
 [test_keySync.html]
 [test_localStorageBase.html]
-skip-if = buildapp == 'b2g' # b2g(no storage chrome event received)
+skip-if = buildapp == 'b2g' || e10s # b2g(no storage chrome event received)
 [test_localStorageBaseSessionOnly.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_localStorageCookieSettings.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_localStorageEnablePref.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_localStorageKeyOrder.html]
 [test_localStorageOriginsDiff.html]
--- a/dom/tests/mochitest/notification/mochitest.ini
+++ b/dom/tests/mochitest/notification/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   MockServices.js
   NotificationTest.js
 
 [test_notification_basics.html]
 [test_notification_storage.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only timeout
 [test_bug931307.html]
--- a/dom/tests/mochitest/orientation/mochitest.ini
+++ b/dom/tests/mochitest/orientation/mochitest.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
+skip-if = e10s
 support-files = bug507902-frame.html
 
 [test_bug507902.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
--- a/dom/tests/mochitest/sessionstorage/mochitest.ini
+++ b/dom/tests/mochitest/sessionstorage/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   file_http.html
   file_https.html
   frameEqual.html
   frameNotEqual.html
   frameReplace.html
   interOriginSlave.js
   interOriginTest.js
--- a/dom/tests/mochitest/storageevent/mochitest.ini
+++ b/dom/tests/mochitest/storageevent/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   frameLocalStorageMaster.html
   frameLocalStorageSlaveEqual.html
   frameLocalStorageSlaveNotEqual.html
   frameSessionStorageMasterEqual.html
   frameSessionStorageMasterNotEqual.html
   frameSessionStorageSlaveEqual.html
   frameSessionStorageSlaveNotEqual.html
--- a/dom/tests/mochitest/webapps/mochitest.ini
+++ b/dom/tests/mochitest/webapps/mochitest.ini
@@ -1,7 +1,8 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   file_bug_779982.html
   file_bug_779982.js
 
 [test_bug_779982.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #Bug 793211
--- a/dom/tests/mochitest/whatwg/mochitest.ini
+++ b/dom/tests/mochitest/whatwg/mochitest.ini
@@ -20,17 +20,17 @@ support-files =
   postMessage_userpass_helper.html
 
 [test_bug477323.html]
 [test_document_scripts.html]
 [test_MessageEvent_dispatchToOther.html]
 [test_MessageEvent.html]
 [test_postMessage_basehref.html]
 [test_postMessage_closed.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 894914 - wrong data - got FAIL, expected message # b2g(bug 894914 - wrong data - got FAIL, expected message) b2g-debug(bug 894914 - wrong data - got FAIL, expected message) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 894914 - wrong data - got FAIL, expected message # b2g(bug 894914 - wrong data - got FAIL, expected message) b2g-debug(bug 894914 - wrong data - got FAIL, expected message) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_postMessage_hash.html]
 [test_postMessage.html]
 [test_postMessage_idn.xhtml]
 [test_postMessage_jar.html]
 [test_postMessage_joined.html]
 [test_postMessage_onOther.html]
 [test_postMessage_origin.xhtml]
 [test_postMessage_override.html]
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -115,34 +115,34 @@ skip-if = (toolkit == 'gonk' && debug) #
 [test_relativeLoad.html]
 skip-if = buildapp == 'b2g' # b2g(Failed to load script: relativeLoad_import.js) b2g-debug(Failed to load script: relativeLoad_import.js) b2g-desktop(Failed to load script: relativeLoad_import.js)
 [test_resolveWorker-assignment.html]
 [test_resolveWorker.html]
 [test_rvals.html]
 [test_sharedWorker.html]
 [test_simpleThread.html]
 [test_suspend.html]
-skip-if = buildapp == 'b2g' # b2g(test timed out, might need more time) b2g-debug(test timed out, might need more time) b2g-desktop(test timed out, might need more time)
+skip-if = buildapp == 'b2g' || e10s # b2g(test timed out, might need more time) b2g-debug(test timed out, might need more time) b2g-desktop(test timed out, might need more time)
 [test_terminate.html]
 [test_threadErrors.html]
 [test_threadTimeouts.html]
 [test_throwingOnerror.html]
 [test_timeoutTracing.html]
 [test_transferable.html]
 [test_url.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only crash, bug 931887
 [test_urlApi.html]
 [test_workersDisabled.html]
 [test_xhr.html]
 [test_xhr2.html]
 [test_xhrAbort.html]
 [test_xhr_headers.html]
 [test_xhr_implicit_cancel.html]
 [test_xhr_parameters.html]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 [test_xhr_parameters.js]
 [test_xhr_system.html]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 [test_xhr_system.js]
 [test_xhr_timeout.html]
-skip-if = (os == "win") || (os == "mac") || toolkit == 'android' #bug 798220
+skip-if = (os == "win") || (os == "mac") || toolkit == 'android' || e10s #bug 798220
 [test_url_exceptions.html]
 [test_urlSearchParams.html]
--- a/editor/libeditor/base/tests/mochitest.ini
+++ b/editor/libeditor/base/tests/mochitest.ini
@@ -3,13 +3,13 @@ skip-if = buildapp == 'b2g'
 support-files = file_bug586662.html
 
 [test_bug408231.html]
 skip-if = toolkit == 'android'
 [test_bug502673.html]
 [test_bug514156.html]
 [test_bug567213.html]
 [test_bug586662.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug599983.html]
 [test_bug742261.html]
 [test_bug773262.html]
 [test_bug795785.html]
--- a/editor/libeditor/html/tests/mochitest.ini
+++ b/editor/libeditor/html/tests/mochitest.ini
@@ -19,69 +19,70 @@ skip-if = os != "mac"
 [test_bug291780.html]
 [test_bug316447.html]
 [test_bug332636.html]
 [test_bug332636.html^headers^]
 [test_bug372345.html]
 skip-if = toolkit == 'android'
 [test_bug404320.html]
 [test_bug410986.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug414526.html]
 [test_bug417418.html]
 [test_bug432225.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug439808.html]
 [test_bug442186.html]
 [test_bug449243.html]
 [test_bug455992.html]
 [test_bug456244.html]
 [test_bug460740.html]
 [test_bug468353.html]
 [test_bug478725.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug480647.html]
 [test_bug480972.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug484181.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug487524.html]
 [test_bug520189.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug525389.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug537046.html]
 [test_bug549262.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug550434.html]
 [test_bug551704.html]
 [test_bug552782.html]
 [test_bug570144.html]
 [test_bug578771.html]
 [test_bug587461.html]
 [test_bug592592.html]
 [test_bug597784.html]
 [test_bug599322.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug607584.html]
 [test_bug611182.html]
 skip-if = toolkit == 'android'
 [test_bug612128.html]
 [test_bug612447.html]
 [test_bug620906.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_bug622371.html]
 skip-if = toolkit == 'android' #bug 957797
 [test_bug629845.html]
 [test_bug640321.html]
+skip-if = e10s
 [test_bug668599.html]
 [test_bug674770-1.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug674770-2.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug674861.html]
 [test_bug676401.html]
 [test_bug677752.html]
 [test_bug686203.html]
 [test_bug697842.html]
 [test_bug725069.html]
 [test_bug735059.html]
 [test_bug738366.html]
@@ -97,10 +98,11 @@ skip-if = toolkit == 'android'
 skip-if = os != "win"
 [test_bug966552.html]
 skip-if = os != "win"
 [test_contenteditable_focus.html]
 [test_dom_input_event_on_htmleditor.html]
 [test_keypress_untrusted_event.html]
 [test_root_element_replacement.html]
 [test_select_all_without_body.html]
+skip-if = e10s
 [test_spellcheck_pref.html]
 skip-if = toolkit == 'android'
--- a/editor/libeditor/text/tests/mochitest.ini
+++ b/editor/libeditor/text/tests/mochitest.ini
@@ -1,30 +1,30 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g'
 
 [test_bug318065.html]
 [test_bug471722.html]
 [test_bug527935.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug590554.html]
 [test_bug596001.html]
 [test_bug596333.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug596506.html]
 [test_bug597331.html]
 [test_bug600570.html]
 skip-if = toolkit == 'android'
 [test_bug602130.html]
 [test_bug603556.html]
 [test_bug604532.html]
 skip-if = toolkit == 'android'
 [test_bug625452.html]
 [test_bug629172.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
 [test_bug638596.html]
 [test_bug641466.html]
 [test_bug645914.html]
 [test_bug681229.html]
 [test_bug692520.html]
 [test_bug740784.html]
 [test_bug757771.html]
 [test_dom_input_event_on_texteditor.html]
--- a/embedding/test/mochitest.ini
+++ b/embedding/test/mochitest.ini
@@ -7,9 +7,9 @@ support-files =
 
 [test_bug293834.html]
 [test_bug449141.html]
 skip-if = toolkit == 'android'
 [test_bug499115.html]
 [test_nsFind.html]
 [test_private_window_from_content.html]
 [test_window_open_units.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || e10s
--- a/extensions/cookie/test/mochitest.ini
+++ b/extensions/cookie/test/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 support-files =
   beltzner.jpg
   beltzner.jpg^headers^
   damonbowling.jpg
   damonbowling.jpg^headers^
   file_domain_hierarchy_inner.html
   file_domain_hierarchy_inner_inner.html
   file_domain_hierarchy_inner_inner_inner.html
--- a/gfx/gl/Makefile.in
+++ b/gfx/gl/Makefile.in
@@ -1,14 +1,10 @@
 # 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 $(topsrcdir)/config/rules.mk
 
-ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
-CXXFLAGS += -I$(ANDROID_SOURCE)/hardware/libhardware/include
-endif
-
 DEFINES := $(filter-out -DUNICODE,$(DEFINES))
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
 CFLAGS   += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -79,16 +79,17 @@ if CONFIG['MOZ_ENABLE_SKIA_GPU']:
     UNIFIED_SOURCES += [
         'SkiaGLGlue.cpp',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     UNIFIED_SOURCES += ['SharedSurfaceGralloc.cpp']
     EXPORTS += ['SharedSurfaceGralloc.h']
     LOCAL_INCLUDES += ['/widget/gonk']
+    CXXFLAGS += ['-I%s/%s' % (CONFIG['ANDROID_SOURCE'], 'hardware/libhardware/include')]
 
 if gl_provider == 'CGL':
     # These files include Mac headers that are unfriendly to unified builds
     SOURCES += [
         "GLContextProviderCGL.mm",
         "TextureImageCGL.mm"
     ]
     EXPORTS += [
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -245,19 +245,16 @@ public:
   // Note that this is structured in such a way that it doesn't depend on the
   // method layout uses to scroll content.
   //
   // May be larger or smaller than |mScrollableRect|.
   //
   // To pre-render a margin of 100 CSS pixels around the window,
   // { x = -100, y = - 100,
   //   width = window.innerWidth + 200, height = window.innerHeight + 200 }
-  //
-  // This is only valid on the root layer. Nested iframes do not have a
-  // displayport set on them. See bug 775452.
   CSSRect mDisplayPort;
 
   // If non-empty, the area of a frame's contents that is considered critical
   // to paint. Area outside of this area (i.e. area inside mDisplayPort, but
   // outside of mCriticalDisplayPort) is considered low-priority, and may be
   // painted with lower precision, or not painted at all.
   //
   // The same restrictions for mDisplayPort apply here.
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -1,18 +1,11 @@
 #
 # 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 $(topsrcdir)/config/rules.mk
 
-CXXFLAGS += \
-        -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright \
-        -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright/openmax \
-        -I$(ANDROID_SOURCE)/frameworks/av/include/media/stagefright \
-        -I$(ANDROID_SOURCE)/frameworks/native/include/media/openmax \
-        $(NULL)
-
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
 
 PremultiplyTables.h: $(srcdir)/genTables.py
 	$(PYTHON) $(srcdir)/genTables.py
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -343,8 +343,17 @@ if CONFIG['MOZ_DEBUG']:
     DEFINES['D3D_DEBUG_INFO'] = True
 
 if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
     DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
 
 GENERATED_FILES = [
     'PremultiplyTables.h',
 ]
+
+CXXFLAGS += [
+    '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+        'frameworks/base/include/media/stagefright',
+        'frameworks/base/include/media/stagefright/openmax',
+        'frameworks/av/include/media/stagefright',
+        'frameworks/native/include/media/openmax',
+    ]
+]
--- a/gfx/tests/mochitest.ini
+++ b/gfx/tests/mochitest.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g'
 [mochitest/test_bug509244.html]
 [mochitest/test_bug513439.html]
+skip-if = e10s
 [mochitest/test_acceleration.html]
--- a/image/test/mochitest/mochitest.ini
+++ b/image/test/mochitest/mochitest.ini
@@ -52,16 +52,17 @@ support-files =
   schrep.png
   shaver.png
   short_header.gif
   source.png
   over.png
 
 [test_ImageContentLoaded.html]
 [test_bug399925.html]
+skip-if = e10s
 # [test_bug435296.html]
 # disabled - See bug 578591
 [test_bug466586.html]
 [test_bug468160.html]
 # [test_bug478398.html]
 # disabled - See bug 579139
 [test_bug490949.html]
 [test_bug496292.html]
--- a/js/src/jit-test/tests/asm.js/testFloat32.js
+++ b/js/src/jit-test/tests/asm.js/testFloat32.js
@@ -81,16 +81,19 @@ assertEq(asmLink(asmCompile('glob', 'ffi
 
 // -> to Float32
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(~~x); } return f"), this)(23), 23);
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x >> 0); } return f"), this)(23), 23);
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = +x; return toF(x); } return f"), this)(13.37), Math.fround(13.37));
 
 UINT32_MAX = Math.pow(2, 32)-1;
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x >>> 0); } return f"), this)(-1), Math.fround(UINT32_MAX));
+var tof = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "function f(x) { x = x|0; return toF(x>>>0) } return f"), this);
+for (x of [0, 1, 10, 64, 1025, 65000, Math.pow(2,30), Math.pow(2,31), Math.pow(2,32)-2, Math.pow(2,32)-1])
+    assertEq(tof(x), Math.fround(x));
 
 // Global variables imports
 assertAsmTypeFail('glob', USE_ASM + "var x = toF(); function f() {} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = some(3); function f() {} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(); function f() {} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(3, 4); function f() {} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF({x: 3}); function f() {} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var x = toF(true); function f() {} return f");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug980585.js
@@ -0,0 +1,10 @@
+var g = newGlobal();
+var dbg = new Debugger(g);
+
+try {
+  g.eval("function f() { var array = ['a', 'b']; [1].map(function () {}); return {array}; }");
+} catch (e) {
+  // Ignore the syntax error.
+}
+
+dbg.findScripts();
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -983,25 +983,18 @@ class MacroAssemblerX86 : public MacroAs
 
         // dest is now a double with the int range.
         // correct the double value by adding 0x80000000.
         addConstantDouble(2147483648.0, dest);
     }
 
     // Note: this function clobbers the source register.
     void convertUInt32ToFloat32(const Register &src, const FloatRegister &dest) {
-        // src is [0, 2^32-1]
-        subl(Imm32(0x80000000), src);
-
-        // Do it the GCC way
-        convertInt32ToFloat32(src, dest);
-
-        // dest is now a double with the int range.
-        // correct the double value by adding 0x80000000.
-        addConstantFloat32(2147483648.f, dest);
+        convertUInt32ToDouble(src, dest);
+        convertDoubleToFloat32(dest, dest);
     }
 
     void inc64(AbsoluteAddress dest) {
         addl(Imm32(1), Operand(dest));
         Label noOverflow;
         j(NonZero, &noOverflow);
         addl(Imm32(1), Operand(dest.offset(4)));
         bind(&noOverflow);
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -715,24 +715,27 @@ AddInnerLazyFunctionsFromScript(JSScript
 }
 
 static bool
 CreateLazyScriptsForCompartment(JSContext *cx)
 {
     AutoObjectVector lazyFunctions(cx);
 
     // Find all live lazy scripts in the compartment, and via them all root
-    // lazy functions in the compartment: those which have not been compiled
-    // and which have a source object, indicating that their parent has been
-    // compiled.
+    // lazy functions in the compartment: those which have not been compiled,
+    // which have a source object, indicating that they have a parent, and
+    // which do not have an uncompiled enclosing script. The last condition is
+    // so that we don't compile lazy scripts whose enclosing scripts failed to
+    // compile, indicating that the lazy script did not escape the script.
     for (gc::CellIter i(cx->zone(), gc::FINALIZE_LAZY_SCRIPT); !i.done(); i.next()) {
         LazyScript *lazy = i.get<LazyScript>();
         JSFunction *fun = lazy->functionNonDelazifying();
         if (fun->compartment() == cx->compartment() &&
-            lazy->sourceObject() && !lazy->maybeScript())
+            lazy->sourceObject() && !lazy->maybeScript() &&
+            !lazy->hasUncompiledEnclosingScript())
         {
             MOZ_ASSERT(fun->isInterpretedLazy());
             MOZ_ASSERT(lazy == fun->lazyScriptOrNull());
             if (!lazyFunctions.append(fun))
                 return false;
         }
     }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -3668,16 +3668,34 @@ LazyScript::initRuntimeFields(uint64_t p
         uint64_t packed;
     };
 
     packed = packedFields;
     p_.hasBeenCloned = p.hasBeenCloned;
     p_.treatAsRunOnce = p.treatAsRunOnce;
 }
 
+bool
+LazyScript::hasUncompiledEnclosingScript() const
+{
+    // It can happen that we created lazy scripts while compiling an enclosing
+    // script, but we errored out while compiling that script. When we iterate
+    // over lazy script in a compartment, we might see lazy scripts that never
+    // escaped to script and should be ignored.
+    //
+    // If the enclosing scope is a function with a null script or has a script
+    // without code, it was not successfully compiled.
+
+    if (!enclosingScope() || !enclosingScope()->is<JSFunction>())
+        return false;
+
+    JSFunction &fun = enclosingScope()->as<JSFunction>();
+    return fun.isInterpreted() && (!fun.mutableScript() || !fun.nonLazyScript()->code());
+}
+
 uint32_t
 LazyScript::staticLevel(JSContext *cx) const
 {
     for (StaticScopeIter<NoGC> ssi(enclosingScope()); !ssi.done(); ssi++) {
         if (ssi.type() == StaticScopeIter<NoGC>::FUNCTION)
             return ssi.funScript()->staticLevel() + 1;
     }
     return 1;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1820,16 +1820,17 @@ class LazyScript : public gc::BarrieredC
     }
     uint32_t lineno() const {
         return lineno_;
     }
     uint32_t column() const {
         return column_;
     }
 
+    bool hasUncompiledEnclosingScript() const;
     uint32_t staticLevel(JSContext *cx) const;
 
     void markChildren(JSTracer *trc);
     void finalize(js::FreeOp *fop);
 
     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_LAZY_SCRIPT; }
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -72,24 +72,24 @@ skip-if = true # Bug 492575
 [test_bug404209.xhtml]
 [test_bug416896.html]
 [test_bug423523.html]
 [test_bug449781.html]
 [test_bug450930.xhtml]
 skip-if = buildapp == 'b2g' || true # bug 934301 # b2g(times out) b2g-debug(times out) b2g-desktop(times out)
 support-files = bug450930.xhtml
 [test_bug465448.xul]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 [test_bug469170.html]
 [test_bug471126.html]
 [test_bug435293-scale.html]
 [test_bug435293-interaction.html]
 [test_bug435293-skew.html]
 [test_reftests_with_caret.html]
-skip-if = (toolkit == 'gonk' && debug) #debug-only timeout
+skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only timeout
 support-files =
   bug106855-1.html
   bug106855-2.html
   bug106855-1-ref.html
   bug240933-1.html
   bug240933-2.html
   bug240933-1-ref.html
   bug389321-1.html
@@ -158,34 +158,34 @@ support-files =
 [test_bug548545.xhtml]
 [test_bug558663.html]
 [test_bug559499.html]
 [test_bug569520.html]
 [test_bug582181-1.html]
 [test_bug582181-2.html]
 [test_bug588174.html]
 [test_bug607529.html]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 support-files = file_bug607529.html
 [test_bug667512.html]
 [test_bug677878.html]
 [test_bug696020.html]
 [test_event_target_radius.html]
 [test_event_target_iframe_oop.html]
 support-files = bug921928_event_target_iframe_apps_oop.html
 [test_mozPaintCount.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(depends on plugins support) b2g-debug(depends on plugins support) b2g-desktop(depends on plugins support)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(depends on plugins support) b2g-debug(depends on plugins support) b2g-desktop(depends on plugins support)
 [test_scroll_event_ordering.html]
 [test_bug583889.html]
 support-files = bug583889_inner1.html bug583889_inner2.html
 [test_bug582771.html]
 [test_bug603550.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(Components.classes[@mozilla.org/widget/dragservice;1] is undefined) b2g-debug(Components.classes[@mozilla.org/widget/dragservice;1] is undefined) b2g-desktop(Components.classes[@mozilla.org/widget/dragservice;1] is undefined)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(Components.classes[@mozilla.org/widget/dragservice;1] is undefined) b2g-debug(Components.classes[@mozilla.org/widget/dragservice;1] is undefined) b2g-desktop(Components.classes[@mozilla.org/widget/dragservice;1] is undefined)
 [test_bug629838.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(depends on plugins support) b2g-debug(depends on plugins support) b2g-desktop(depends on plugins support)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(depends on plugins support) b2g-debug(depends on plugins support) b2g-desktop(depends on plugins support)
 [test_bug646757.html]
 [test_bug718809.html]
 [test_bug725426.html]
 [test_bug731777.html]
 [test_bug761572.html]
 [test_bug770106.html]
 [test_maxLineBoxWidth.html]
 [test_remote_frame.html]
--- a/layout/forms/test/mochitest.ini
+++ b/layout/forms/test/mochitest.ini
@@ -3,55 +3,56 @@ support-files =
   bug287446_subframe.html
   bug477700_subframe.html
   bug564115_window.html
 
 [test_bug231389.html]
 [test_bug287446.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #bug 947789
 [test_bug345267.html]
+skip-if = e10s
 [test_bug348236.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(select form control popup) b2g-debug(select form control popup) b2g-desktop(select form control popup)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(select form control popup) b2g-debug(select form control popup) b2g-desktop(select form control popup)
 [test_bug353539.html]
 [test_bug365410.html]
 [test_bug378670.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_bug402198.html]
 [test_bug411236.html]
 [test_bug446663.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(needs copy support) b2g-debug(needs copy support) b2g-desktop(needs copy support)
 [test_bug476308.html]
 [test_bug477531.html]
 [test_bug477700.html]
 [test_bug478219.xhtml]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795)
 [test_bug534785.html]
 [test_bug542914.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
 [test_bug549170.html]
 [test_bug562447.html]
 [test_bug563642.html]
 [test_bug564115.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #TIMED_OUT # b2g-debug(times out on window.open and focus event) b2g-desktop(times out on window.open and focus event)
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(times out on window.open and focus event) b2g-desktop(times out on window.open and focus event)
 [test_bug571352.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(shift-click multi-select not working?) b2g-debug(shift-click multi-select not working?) b2g-desktop(shift-click multi-select not working?)
 [test_bug572406.html]
 [test_bug572649.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_bug595310.html]
 [test_bug620936.html]
 [test_bug644542.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_bug672810.html]
 skip-if = toolkit == 'android'
 [test_bug704049.html]
 [test_bug717878_input_scroll.html]
 [test_bug869314.html]
 [test_bug903715.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #select elements don't use an in-page popup on Android # b2g(select elements don't use an in-page popup in B2G) b2g-debug(select elements don't use an in-page popup in B2G) b2g-desktop(select elements don't use an in-page popup in B2G)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #select elements don't use an in-page popup on Android # b2g(select elements don't use an in-page popup in B2G) b2g-debug(select elements don't use an in-page popup in B2G) b2g-desktop(select elements don't use an in-page popup in B2G)
 [test_bug935876.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Esc key is consumed by another event handler only on desktop B2G
 [test_bug957562.html]
 [test_bug960277.html]
 [test_listcontrol_search.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #select elements don't use an in-page popup on Android # b2g-debug(select elements don't use an in-page popup in B2G) b2g-desktop(select elements don't use an in-page popup in B2G)
 [test_select_prevent_default.html]
 [test_textarea_resize.html]
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -23,20 +23,20 @@ using namespace mozilla;
 class BRFrame : public nsFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   friend nsIFrame* NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) MOZ_OVERRIDE;
 
-  virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
-  virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+  virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
+  virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                      bool aRespectClusters = true) MOZ_OVERRIDE;
-  virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace,
+  virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace,
                               bool aIsKeyboardSelect, int32_t* aOffset,
                               PeekWordState* aState) MOZ_OVERRIDE;
 
   virtual nsresult Reflow(nsPresContext* aPresContext,
                           nsHTMLReflowMetrics& aDesiredSize,
                           const nsHTMLReflowState& aReflowState,
                           nsReflowStatus& aStatus) MOZ_OVERRIDE;
   virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
@@ -206,46 +206,46 @@ nsIFrame::ContentOffsets BRFrame::CalcCo
   if (offsets.content) {
     offsets.offset = offsets.content->IndexOf(mContent);
     offsets.secondaryOffset = offsets.offset;
     offsets.associateWithNext = true;
   }
   return offsets;
 }
 
-bool
+nsIFrame::FrameSearchResult
 BRFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   int32_t startOffset = *aOffset;
   // If we hit the end of a BR going backwards, go to its beginning and stay there.
   if (!aForward && startOffset != 0) {
     *aOffset = 0;
-    return true;
+    return FOUND;
   }
   // Otherwise, stop if we hit the beginning, continue (forward) if we hit the end.
-  return (startOffset == 0);
+  return (startOffset == 0) ? FOUND : CONTINUE;
 }
 
-bool
+nsIFrame::FrameSearchResult
 BRFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                              bool aRespectClusters)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   // Keep going. The actual line jumping will stop us.
-  return false;
+  return CONTINUE;
 }
 
-bool
+nsIFrame::FrameSearchResult
 BRFrame::PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
                         int32_t* aOffset, PeekWordState* aState)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   // Keep going. The actual line jumping will stop us.
-  return false;
+  return CONTINUE;
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 BRFrame::AccessibleType()
 {
   nsIContent *parent = mContent->GetParent();
   if (parent && parent->IsRootOfNativeAnonymousSubtree() &&
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -356,31 +356,31 @@ nsContainerFrame::ChildIsDirty(nsIFrame*
 }
 
 bool
 nsContainerFrame::IsLeaf() const
 {
   return false;
 }
 
-bool
+nsIFrame::FrameSearchResult
 nsContainerFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   // Don't allow the caret to stay in an empty (leaf) container frame.
-  return false;
+  return CONTINUE_EMPTY;
 }
 
-bool
+nsIFrame::FrameSearchResult
 nsContainerFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                       bool aRespectClusters)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   // Don't allow the caret to stay in an empty (leaf) container frame.
-  return false;
+  return CONTINUE_EMPTY;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Helper member functions
 
 static nsresult
 ReparentFrameViewTo(nsIFrame*       aFrame,
                     nsViewManager* aViewManager,
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -63,18 +63,18 @@ public:
                                nsIFrame* aOldFrame) MOZ_OVERRIDE;
 
   virtual const nsFrameList& GetChildList(ChildListID aList) const MOZ_OVERRIDE;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE;
   virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
   virtual void ChildIsDirty(nsIFrame* aChild) MOZ_OVERRIDE;
 
   virtual bool IsLeaf() const MOZ_OVERRIDE;
-  virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
-  virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+  virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
+  virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                      bool aRespectClusters = true) MOZ_OVERRIDE;
   
 #ifdef DEBUG_FRAME_DUMP
   void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const MOZ_OVERRIDE;
 #endif  
 
   // nsContainerFrame methods
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6264,42 +6264,54 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
   int32_t offset = aPos->mStartOffset - range.start;
   nsIFrame* current = this;
   
   switch (aPos->mAmount) {
     case eSelectCharacter:
     case eSelectCluster:
     {
       bool eatingNonRenderableWS = false;
-      bool done = false;
+      nsIFrame::FrameSearchResult peekSearchState = CONTINUE;
       bool jumpedLine = false;
+      bool movedOverNonSelectableText = false;
       
-      while (!done) {
+      while (peekSearchState != FOUND) {
         bool movingInFrameDirection =
           IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
 
         if (eatingNonRenderableWS)
-          done = current->PeekOffsetNoAmount(movingInFrameDirection, &offset); 
+          peekSearchState = current->PeekOffsetNoAmount(movingInFrameDirection, &offset); 
         else
-          done = current->PeekOffsetCharacter(movingInFrameDirection, &offset,
+          peekSearchState = current->PeekOffsetCharacter(movingInFrameDirection, &offset,
                                               aPos->mAmount == eSelectCluster);
 
-        if (!done) {
+        movedOverNonSelectableText |= (peekSearchState == CONTINUE_UNSELECTABLE);
+
+        if (peekSearchState != FOUND) {
           result =
             current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
                                            aPos->mJumpLines, aPos->mScrollViewStop,
                                            &current, &offset, &jumpedLine);
           if (NS_FAILED(result))
             return result;
 
           // If we jumped lines, it's as if we found a character, but we still need
           // to eat non-renderable content on the new line.
           if (jumpedLine)
             eatingNonRenderableWS = true;
         }
+
+        // Found frame, but because we moved over non selectable text we want the offset
+        // to be at the frame edge.
+        if (peekSearchState == FOUND && movedOverNonSelectableText)
+        {
+          int32_t start, end;
+          current->GetOffsets(start, end);
+          offset = aPos->mDirection == eDirNext ? 0 : end - start;
+        }
       }
 
       // Set outputs
       range = GetRangeForFrame(current);
       aPos->mResultFrame = current;
       aPos->mResultContent = range.content;
       // Output offset is relative to content, not frame
       aPos->mContentOffset = offset < 0 ? range.end : range.start + offset;
@@ -6357,17 +6369,17 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
       PeekWordState state;
       int32_t offsetAdjustment = 0;
       bool done = false;
       while (!done) {
         bool movingInFrameDirection =
           IsMovingInFrameDirection(current, aPos->mDirection, aPos->mVisual);
         
         done = current->PeekOffsetWord(movingInFrameDirection, wordSelectEatSpace,
-                                       aPos->mIsKeyboardSelect, &offset, &state);
+                                       aPos->mIsKeyboardSelect, &offset, &state) == FOUND;
         
         if (!done) {
           nsIFrame* nextFrame;
           int32_t nextFrameOffset;
           bool jumpedLine;
           result =
             current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
                                            aPos->mJumpLines, aPos->mScrollViewStop,
@@ -6572,75 +6584,75 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct*
     {
       NS_ASSERTION(false, "Invalid amount");
       return NS_ERROR_FAILURE;
     }
   }
   return NS_OK;
 }
 
-bool
+nsIFrame::FrameSearchResult
 nsFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   // Sure, we can stop right here.
-  return true;
-}
-
-bool
+  return FOUND;
+}
+
+nsIFrame::FrameSearchResult
 nsFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                              bool aRespectClusters)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   int32_t startOffset = *aOffset;
   // A negative offset means "end of frame", which in our case means offset 1.
   if (startOffset < 0)
     startOffset = 1;
   if (aForward == (startOffset == 0)) {
     // We're before the frame and moving forward, or after it and moving backwards:
     // skip to the other side and we're done.
     *aOffset = 1 - startOffset;
-    return true;
-  }
-  return false;
-}
-
-bool
+    return FOUND;
+  }
+  return CONTINUE;
+}
+
+nsIFrame::FrameSearchResult
 nsFrame::PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
                         int32_t* aOffset, PeekWordState* aState)
 {
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   int32_t startOffset = *aOffset;
   // This isn't text, so truncate the context
   aState->mContext.Truncate();
   if (startOffset < 0)
     startOffset = 1;
   if (aForward == (startOffset == 0)) {
     // We're before the frame and moving forward, or after it and moving backwards.
     // If we're looking for non-whitespace, we found it (without skipping this frame).
     if (!aState->mAtStart) {
       if (aState->mLastCharWasPunctuation) {
         // We're not punctuation, so this is a punctuation boundary.
         if (BreakWordBetweenPunctuation(aState, aForward, false, false, aIsKeyboardSelect))
-          return true;
+          return FOUND;
       } else {
         // This is not a punctuation boundary.
         if (aWordSelectEatSpace && aState->mSawBeforeType)
-          return true;
+          return FOUND;
       }
     }
     // Otherwise skip to the other side and note that we encountered non-whitespace.
     *aOffset = 1 - startOffset;
     aState->Update(false, // not punctuation
                    false     // not whitespace
                    );
     if (!aWordSelectEatSpace)
       aState->SetSawBeforeType();
   }
-  return false;
+  return CONTINUE;
 }
 
 bool
 nsFrame::BreakWordBetweenPunctuation(const PeekWordState* aState,
                                      bool aForward,
                                      bool aPunctAfter, bool aWhitespaceAfter,
                                      bool aIsKeyboardSelect)
 {
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -199,20 +199,20 @@ public:
   virtual nsIFrame* GetNextInFlowVirtual() const MOZ_OVERRIDE;
   virtual void SetNextInFlow(nsIFrame*) MOZ_OVERRIDE;
   virtual nsIAtom* GetType() const MOZ_OVERRIDE;
 
   virtual nsresult  IsSelectable(bool* aIsSelectable, uint8_t* aSelectStyle) const MOZ_OVERRIDE;
 
   virtual nsresult  GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) MOZ_OVERRIDE;
 
-  virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
-  virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+  virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
+  virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                      bool aRespectClusters = true) MOZ_OVERRIDE;
-  virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
+  virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
                                 int32_t* aOffset, PeekWordState *aState) MOZ_OVERRIDE;
   /**
    * Check whether we should break at a boundary between punctuation and
    * non-punctuation. Only call it at a punctuation boundary
    * (i.e. exactly one of the previous and next characters are punctuation).
    * @param aForward true if we're moving forward in content order
    * @param aPunctAfter true if the next character is punctuation
    * @param aWhitespaceAfter true if the next character is whitespace
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -434,16 +434,29 @@ public:
    * Destroys this frame and each of its child frames (recursively calls
    * Destroy() for each child). If this frame is a first-continuation, this
    * also removes the frame from the primary frame map and clears undisplayed
    * content for its content node.
    * If the frame is a placeholder, it also ensures the out-of-flow frame's
    * removal and destruction.
    */
   void Destroy() { DestroyFrom(this); }
+ 
+  /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values.
+    */
+  enum FrameSearchResult {
+    // Peek found a appropriate offset within frame.
+    FOUND = 0x00,
+    // try next frame for offset.
+    CONTINUE = 0x1,
+    // offset not found because the frame was empty of text.
+    CONTINUE_EMPTY = 0x2 | CONTINUE,
+    // offset not found because the frame didn't contain any text that could be selected.
+    CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
+  };
 
 protected:
   /**
    * Return true if the frame is part of a Selection.
    * Helper method to implement the public IsSelected() API.
    */
   virtual bool IsFrameSelected() const;
 
@@ -3035,35 +3048,37 @@ protected:
   } mOverflow;
 
   // Helpers
   /**
    * Can we stop inside this frame when we're skipping non-rendered whitespace?
    * @param  aForward [in] Are we moving forward (or backward) in content order.
    * @param  aOffset [in/out] At what offset into the frame to start looking.
    *         on output - what offset was reached (whether or not we found a place to stop).
-   * @return true: An appropriate offset was found within this frame,
+   * @return STOP: An appropriate offset was found within this frame,
    *         and is given by aOffset.
-   *         false: Not found within this frame, need to try the next frame.
+   *         CONTINUE: Not found within this frame, need to try the next frame.
+   *         see enum FrameSearchResult for more details.
    */
-  virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0;
+  virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0;
   
   /**
    * Search the frame for the next character
    * @param  aForward [in] Are we moving forward (or backward) in content order.
    * @param  aOffset [in/out] At what offset into the frame to start looking.
    *         on output - what offset was reached (whether or not we found a place to stop).
    * @param  aRespectClusters [in] Whether to restrict result to valid cursor locations
    *         (between grapheme clusters) - default TRUE maintains "normal" behavior,
    *         FALSE is used for selection by "code unit" (instead of "character")
-   * @return true: An appropriate offset was found within this frame,
+   * @return STOP: An appropriate offset was found within this frame,
    *         and is given by aOffset.
-   *         false: Not found within this frame, need to try the next frame.
+   *         CONTINUE: Not found within this frame, need to try the next frame.
+   *         see enum FrameSearchResult for more details.
    */
-  virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+  virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                      bool aRespectClusters = true) = 0;
   
   /**
    * Search the frame for the next word boundary
    * @param  aForward [in] Are we moving forward (or backward) in content order.
    * @param  aWordSelectEatSpace [in] true: look for non-whitespace following
    *         whitespace (in the direction of movement).
    *         false: look for whitespace following non-whitespace (in the
@@ -3107,17 +3122,17 @@ protected:
       if (aAfterWhitespace) {
         mSeenNonPunctuationSinceWhitespace = false;
       } else if (!aAfterPunctuation) {
         mSeenNonPunctuationSinceWhitespace = true;
       }
       mAtStart = false;
     }
   };
-  virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
+  virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
                                 int32_t* aOffset, PeekWordState* aState) = 0;
 
   /**
    * Search for the first paragraph boundary before or after the given position
    * @param  aPos See description in nsFrameSelection.h. The following fields are
    *              used by this method: 
    *              Input: mDirection
    *              Output: mResultContent, mContentOffset
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -150,31 +150,31 @@ nsInlineFrame::IsEmpty()
   for (nsIFrame *kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) {
     if (!kid->IsEmpty())
       return false;
   }
 
   return true;
 }
 
-bool
+nsIFrame::FrameSearchResult
 nsInlineFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                    bool aRespectClusters)
 {
   // Override the implementation in nsFrame, to skip empty inline frames
   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
   int32_t startOffset = *aOffset;
   if (startOffset < 0)
     startOffset = 1;
   if (aForward == (startOffset == 0)) {
     // We're before the frame and moving forward, or after it and moving backwards:
     // skip to the other side, but keep going.
     *aOffset = 1 - startOffset;
   }
-  return false;
+  return CONTINUE;
 }
 
 void
 nsInlineFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists)
 {
   BuildDisplayListForInline(aBuilder, aDirtyRect, aLists);
--- a/layout/generic/nsInlineFrame.h
+++ b/layout/generic/nsInlineFrame.h
@@ -54,17 +54,17 @@ public:
   }
 
   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
 
   virtual bool IsEmpty() MOZ_OVERRIDE;
   virtual bool IsSelfEmpty() MOZ_OVERRIDE;
 
-  virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+  virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                      bool aRespectClusters = true) MOZ_OVERRIDE;
   
   // nsIHTMLReflow overrides
   virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
                                  InlineMinWidthData *aData) MOZ_OVERRIDE;
   virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
                                   InlinePrefWidthData *aData) MOZ_OVERRIDE;
   virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -6500,29 +6500,29 @@ nsTextFrame::GetChildFrameContainingOffs
 
   // cache the frame we found
   Properties().Set(OffsetToFrameProperty(), f);
   f->AddStateBits(TEXT_IN_OFFSET_CACHE);
 
   return NS_OK;
 }
 
-bool
+nsIFrame::FrameSearchResult
 nsTextFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
 {
   NS_ASSERTION(aOffset && *aOffset <= GetContentLength(), "aOffset out of range");
 
   gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
   if (!mTextRun)
-    return false;
+    return CONTINUE_EMPTY;
 
   TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), true);
   // Check whether there are nonskipped characters in the trimmmed range
-  return iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
-         iter.ConvertOriginalToSkipped(trimmed.mStart);
+  return (iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
+         iter.ConvertOriginalToSkipped(trimmed.mStart)) ? FOUND : CONTINUE;
 }
 
 /**
  * This class iterates through the clusters before or after the given
  * aPosition (which is a content offset). You can test each cluster
  * to see if it's whitespace (as far as selection/caret movement is concerned),
  * or punctuation, or if there is a word break before the cluster. ("Before"
  * is interpreted according to aDirection, so if aDirection is -1, "before"
@@ -6570,70 +6570,70 @@ IsAcceptableCaretPosition(const gfxSkipC
     // so we'll return FALSE above.)
     if (aTextRun->CharIsLowSurrogate(index)) {
       return false;
     }
   }
   return true;
 }
 
-bool
+nsIFrame::FrameSearchResult
 nsTextFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                  bool aRespectClusters)
 {
   int32_t contentLength = GetContentLength();
   NS_ASSERTION(aOffset && *aOffset <= contentLength, "aOffset out of range");
 
   bool selectable;
   uint8_t selectStyle;  
   IsSelectable(&selectable, &selectStyle);
   if (selectStyle == NS_STYLE_USER_SELECT_ALL)
-    return false;
+    return CONTINUE_UNSELECTABLE;
 
   gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
   if (!mTextRun)
-    return false;
+    return CONTINUE_EMPTY;
 
   TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), false);
 
   // A negative offset means "end of frame".
   int32_t startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
 
   if (!aForward) {
     // If at the beginning of the line, look at the previous continuation
     for (int32_t i = std::min(trimmed.GetEnd(), startOffset) - 1;
          i >= trimmed.mStart; --i) {
       iter.SetOriginalOffset(i);
       if (IsAcceptableCaretPosition(iter, aRespectClusters, mTextRun, this)) {
         *aOffset = i - mContentOffset;
-        return true;
+        return FOUND;
       }
     }
     *aOffset = 0;
   } else {
     // If we're at the end of a line, look at the next continuation
     iter.SetOriginalOffset(startOffset);
     if (startOffset <= trimmed.GetEnd() &&
         !(startOffset < trimmed.GetEnd() &&
           StyleText()->NewlineIsSignificant() &&
           iter.GetSkippedOffset() < mTextRun->GetLength() &&
           mTextRun->CharIsNewline(iter.GetSkippedOffset()))) {
       for (int32_t i = startOffset + 1; i <= trimmed.GetEnd(); ++i) {
         iter.SetOriginalOffset(i);
         if (i == trimmed.GetEnd() ||
             IsAcceptableCaretPosition(iter, aRespectClusters, mTextRun, this)) {
           *aOffset = i - mContentOffset;
-          return true;
+          return FOUND;
         }
       }
     }
     *aOffset = contentLength;
   }
   
-  return false;
+  return CONTINUE;
 }
 
 bool
 ClusterIterator::IsWhitespace()
 {
   NS_ASSERTION(mCharIndex >= 0, "No cluster selected");
   return IsSelectionSpace(mFrag, mCharIndex);
 }
@@ -6741,34 +6741,34 @@ ClusterIterator::ClusterIterator(nsTextF
     int32_t indexInText = i + textStart;
     mWordBreaks[i] |=
       wordBreaker->BreakInBetween(aContext.get(), indexInText,
                                   aContext.get() + indexInText,
                                   aContext.Length() - indexInText);
   }
 }
 
-bool
+nsIFrame::FrameSearchResult
 nsTextFrame::PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
                             int32_t* aOffset, PeekWordState* aState)
 {
   int32_t contentLength = GetContentLength();
   NS_ASSERTION (aOffset && *aOffset <= contentLength, "aOffset out of range");
 
   bool selectable;
   uint8_t selectStyle;
   IsSelectable(&selectable, &selectStyle);
   if (selectStyle == NS_STYLE_USER_SELECT_ALL)
-    return false;
+    return CONTINUE_UNSELECTABLE;
 
   int32_t offset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
   ClusterIterator cIter(this, offset, aForward ? 1 : -1, aState->mContext);
 
   if (!cIter.NextCluster())
-    return false;
+    return CONTINUE_EMPTY;
 
   do {
     bool isPunctuation = cIter.IsPunctuation();
     bool isWhitespace = cIter.IsWhitespace();
     bool isWordBreakBefore = cIter.HaveWordBreakBefore();
     if (aWordSelectEatSpace == isWhitespace && !aState->mSawBeforeType) {
       aState->SetSawBeforeType();
       aState->Update(isPunctuation, isWhitespace);
@@ -6789,24 +6789,24 @@ nsTextFrame::PeekOffsetWord(bool aForwar
         // Japanese and Chinese.
         canBreak = true;
       } else {
         canBreak = isWordBreakBefore && aState->mSawBeforeType &&
           (aWordSelectEatSpace != isWhitespace);
       }
       if (canBreak) {
         *aOffset = cIter.GetBeforeOffset() - mContentOffset;
-        return true;
+        return FOUND;
       }
     }
     aState->Update(isPunctuation, isWhitespace);
   } while (cIter.NextCluster());
 
   *aOffset = cIter.GetAfterOffset() - mContentOffset;
-  return false;
+  return CONTINUE;
 }
 
  // TODO this needs to be deCOMtaminated with the interface fixed in
 // nsIFrame.h, but we won't do that until the old textframe is gone.
 nsresult
 nsTextFrame::CheckVisibility(nsPresContext* aContext, int32_t aStartIndex,
     int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *aRetval)
 {
@@ -6814,17 +6814,17 @@ nsTextFrame::CheckVisibility(nsPresConte
     return NS_ERROR_NULL_POINTER;
 
   // Text in the range is visible if there is at least one character in the range
   // that is not skipped and is mapped by this frame (which is the primary frame)
   // or one of its continuations.
   for (nsTextFrame* f = this; f;
        f = static_cast<nsTextFrame*>(GetNextContinuation())) {
     int32_t dummyOffset = 0;
-    if (f->PeekOffsetNoAmount(true, &dummyOffset)) {
+    if (f->PeekOffsetNoAmount(true, &dummyOffset) == FOUND) {
       *aRetval = true;
       return NS_OK;
     }
   }
 
   *aRetval = false;
   return NS_OK;
 }
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -135,20 +135,20 @@ public:
    * (Selection::Repaint depends on this).
    * @param aSelected true if the selection has been added to the range,
    * false otherwise
    * @param aType the type of selection added or removed
    */
   void SetSelectedRange(uint32_t aStart, uint32_t aEnd, bool aSelected,
                         SelectionType aType);
 
-  virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
-  virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+  virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
+  virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
                                      bool aRespectClusters = true) MOZ_OVERRIDE;
-  virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
+  virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
                                 int32_t* aOffset, PeekWordState* aState) MOZ_OVERRIDE;
 
   virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval) MOZ_OVERRIDE;
   
   // Flags for aSetLengthFlags
   enum { ALLOW_FRAME_CREATION_AND_DESTRUCTION = 0x01 };
 
   // Update offsets to account for new length. This may clear mTextRun.
--- a/layout/generic/test/mochitest.ini
+++ b/layout/generic/test/mochitest.ini
@@ -87,43 +87,45 @@ skip-if = (buildapp == 'b2g' && toolkit 
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug785324.html]
 [test_bug791616.html]
 skip-if = buildapp == 'b2g' # b2g(Target should not have scrolled - got 114.10000610351562, expected 115.39999389648438) b2g-debug(Target should not have scrolled - got 114.10000610351562, expected 115.39999389648438) b2g-desktop(Target should not have scrolled - got 114.10000610351562, expected 115.39999389648438)
 [test_bug831780.html]
 [test_bug841361.html]
 [test_bug904810.html]
 [test_bug938772.html]
+[test_bug970363.html]
 [test_contained_plugin_transplant.html]
-skip-if = os=='win'
+skip-if = os=='win' || e10s
 [test_image_selection.html]
 [test_image_selection_2.html]
 [test_invalidate_during_plugin_paint.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
 [test_movement_by_characters.html]
 [test_movement_by_words.html]
 # Disable the caret movement by word test on Linux because the shortcut keys
 # are defined in system level.  So, it depends on the environment.
 # Disable on Windows for too many intermittent failures (bug 916143).
 skip-if = (toolkit == "gtk2") || (toolkit == "gtk3") || (os == "win")
 [test_page_scroll_with_fixed_pos.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(opened window too small?) b2g-desktop(opened window too small?)
 support-files = page_scroll_with_fixed_pos_window.html
 [test_plugin_clipping.xhtml]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_plugin_clipping2.xhtml]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_plugin_clipping_transformed.xhtml]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_plugin_clipping_table.xhtml]
-skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 [test_plugin_focus.html]
-skip-if = buildapp == 'b2g' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
+skip-if = buildapp == 'b2g' || e10s # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
 [test_plugin_mouse_coords.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
 [test_plugin_position.xhtml]
+skip-if = e10s
 [test_selection_expanding.html]
 skip-if = buildapp == 'b2g' # b2g(mouse selection not working) b2g-debug(mouse selection not working) b2g-desktop(mouse selection not working)
 support-files = selection_expanding_xbl.xml
 [test_selection_splitText-normalize.html]
 [test_selection_touchevents.html]
 [test_taintedfilters.html]
 support-files = file_taintedfilters_feDisplacementMap-tainted-1.svg file_taintedfilters_feDisplacementMap-tainted-2.svg file_taintedfilters_feDisplacementMap-tainted-3.svg file_taintedfilters_feDisplacementMap-tainted-ref.svg file_taintedfilters_feDisplacementMap-untainted-ref.svg file_taintedfilters_feDisplacementMap-untainted-1.svg file_taintedfilters_feDisplacementMap-untainted-2.svg file_taintedfilters_red-flood-for-feImage-cors.svg file_taintedfilters_red-flood-for-feImage-cors.svg^headers^ file_taintedfilters_red-flood-for-feImage.svg
new file mode 100644
--- /dev/null
+++ b/layout/generic/test/test_bug970363.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=970363
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 970363</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=970363">Mozilla Bug 970363</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<div contenteditable="true" id='editablediv'>
+  <div id='t'>S<span contenteditable="false">readonly</span>E</div>
+</div>
+<pre id="test">
+
+ <script type="application/javascript">
+
+    /** Test for Bug 970363 **/
+
+    SimpleTest.waitForExplicitFinish();
+
+    SimpleTest.waitForFocus(function() {
+      var t = document.getElementById("t");
+      var editablediv = document.getElementById("editablediv");
+      var sel = window.getSelection();
+      editablediv.focus();
+      sel.collapse(t, 0);
+
+      // Move past the 'S' char.
+      synthesizeKey("VK_RIGHT", {});
+      // Move across the span.
+      synthesizeKey("VK_RIGHT", {});
+      // Insert an 'I' to show when IP currently is.
+      synthesizeKey("I", {});
+
+      is(t.textContent, "SreadonlyIE", "the 'I' char should be inserted between 'readonly' and 'E'");
+      SimpleTest.finish();
+    });
+
+  </script>
+
+</pre>
+</body>
+</html>
--- a/layout/reftests/bugs/359903-2-ref.html
+++ b/layout/reftests/bugs/359903-2-ref.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html>
 <body>
 <button style="width: 100px; border: 0;
                padding-left: 10px; padding-right: 10px">
-   <img src="mozilla-banner.gif" width="90">
+   <img src="blue-600x58.png" width="90">
 </button>
 </body>
 </html>
--- a/layout/reftests/bugs/359903-2.html
+++ b/layout/reftests/bugs/359903-2.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <html>
 <body>
 <button style="width: 100px; border: 0;
                padding-left: 0px; padding-right: 0px">
-   <img src="mozilla-banner.gif" width="90">
+   <img src="blue-600x58.png" width="90">
 </button>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/983084-1-ref.html
@@ -0,0 +1,6 @@
+<html>
+    <body>
+        <div id="one" style="width:50px; height:50px; background-color:blue; position:absolute"></div>
+        <div id="two" style="width:500px; height:500px; background-color:red"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/983084-1.html
@@ -0,0 +1,17 @@
+<html class="reftest-wait">
+    <head>
+        <script>
+            function showItem() {
+                var el = document.getElementById("two");
+                getComputedStyle(el).opacity; // flush styles
+                el.style.opacity = 1;
+                document.documentElement.removeAttribute("class");
+            }
+            window.addEventListener("MozReftestInvalidate", showItem, false);
+        </script>
+    </head>
+    <body>
+        <div id="one" style="width:50px; height:50px; background-color:blue; position:absolute"></div>
+        <div id="two" style="width:500px; height:500px; background-color:red; opacity:0.99"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/983084-2-ref.html
@@ -0,0 +1,6 @@
+<html>
+    <body>
+        <div id="one" style="width:50px; height:50px; background-color:blue; position:absolute"></div>
+        <div id="two" style="width:500px; height:500px; background-color:red; opacity:0.99"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/983084-2.html
@@ -0,0 +1,24 @@
+<html class="reftest-wait">
+    <head>
+        <style>
+          div {
+            transition: opacity 0.1s;
+          }
+        </style>
+        <script>
+            function showItem() {
+                var el = document.getElementById("two");
+                getComputedStyle(el).opacity; // flush styles
+                el.style.opacity = 0.99;
+                document.addEventListener("transitionend", function() {
+                  document.documentElement.removeAttribute("class");
+                }, false);
+            }
+            window.addEventListener("MozReftestInvalidate", showItem, false);
+        </script>
+    </head>
+    <body>
+        <div id="one" style="width:50px; height:50px; background-color:blue; position:absolute"></div>
+        <div id="two" style="width:500px; height:500px; background-color:red; opacity:0.5"></div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/983084-3.html
@@ -0,0 +1,24 @@
+<html class="reftest-wait">
+    <head>
+        <style>
+          div {
+            transition: opacity 0.1s;
+          }
+        </style>
+        <script>
+            function showItem() {
+                var el = document.getElementById("two");
+                getComputedStyle(el).opacity; // flush styles
+                el.style.opacity = 1;
+                document.addEventListener("transitionend", function() {
+                  document.documentElement.removeAttribute("class");
+                }, false);
+            }
+            window.addEventListener("MozReftestInvalidate", showItem, false);
+        </script>
+    </head>
+    <body>
+        <div id="one" style="width:50px; height:50px; background-color:blue; position:absolute"></div>
+        <div id="two" style="width:500px; height:500px; background-color:red; opacity:0.5"></div>
+    </body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1794,8 +1794,11 @@ fuzzy-if(OSX==10.6,2,30) skip-if(B2G&&br
 == 956513-1.svg 956513-1-ref.svg
 == 944291-1.html 944291-1-ref.html
 == 957770-1.svg 957770-1-ref.svg
 == 960277-1.html 960277-1-ref.html
 pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,10) == 966992-1.html 966992-1-ref.html
 skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed
 skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
 == 978911-1.svg 978911-1-ref.svg
+== 983084-1.html 983084-1-ref.html
+== 983084-2.html 983084-2-ref.html
+== 983084-3.html 983084-1-ref.html
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2488,17 +2488,25 @@ nsChangeHint nsStyleDisplay::CalcDiffere
       || mAppearance != aOther.mAppearance
       || mOrient != aOther.mOrient
       || mOverflowClipBox != aOther.mOverflowClipBox
       || mClipFlags != aOther.mClipFlags || !mClip.IsEqualInterior(aOther.mClip))
     NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AllReflowHints,
                                        nsChangeHint_RepaintFrame));
 
   if (mOpacity != aOther.mOpacity) {
-    NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer);
+    // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
+    // repaint the frame because DLBI will not catch the invalidation.  Otherwise,
+    // just update the opacity layer.
+    if ((mOpacity >= 0.99f && mOpacity < 1.0f && aOther.mOpacity == 1.0f) ||
+        (aOther.mOpacity >= 0.99f && aOther.mOpacity < 1.0f && mOpacity == 1.0f)) {
+      NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
+    } else {
+      NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer);
+    }
   }
 
   /* If we've added or removed the transform property, we need to reconstruct the frame to add
    * or remove the view object, and also to handle abs-pos and fixed-pos containers.
    */
   if (HasTransformStyle() != aOther.HasTransformStyle()) {
     // We do not need to apply nsChangeHint_UpdateTransformLayer since
     // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -155,17 +155,17 @@ skip-if = (toolkit == 'gonk' && debug) #
 [test_parser_diagnostics_unprintables.html]
 [test_pixel_lengths.html]
 [test_pointer-events.html]
 [test_position_sticky.html]
 support-files = file_position_sticky.html
 [test_priority_preservation.html]
 [test_property_syntax_errors.html]
 [test_pseudoelement_state.html]
-skip-if = (toolkit == 'gonk' && debug) #debug-only failure
+skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
 [test_pseudoelement_parsing.html]
 [test_redundant_font_download.html]
 support-files = redundant_font_download.sjs
 [test_rem_unit.html]
 [test_root_node_display.html]
 [test_rule_insertion.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(monospace and serif text have sufficiently different widths) b2g-desktop(monospace and serif text have sufficiently different widths)
 [test_rule_serialization.html]
--- a/media/libcubeb/src/Makefile.in
+++ b/media/libcubeb/src/Makefile.in
@@ -4,13 +4,8 @@
 
 
 include $(topsrcdir)/config/rules.mk
 
 CFLAGS += \
         $(MOZ_ALSA_CFLAGS) \
         $(MOZ_PULSEAUDIO_CFLAGS) \
         $(NULL)
-
-ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
-LOCAL_INCLUDES += -I$(ANDROID_SOURCE)/frameworks/wilhelm/include \
-                  -I$(ANDROID_SOURCE)/system/media/wilhelm/include
-endif
--- a/media/libcubeb/src/moz.build
+++ b/media/libcubeb/src/moz.build
@@ -54,8 +54,16 @@ if CONFIG['OS_TARGET'] == 'Android':
         DEFINES['USE_AUDIOTRACK'] = True
 
 MSVC_ENABLE_PGO = True
 
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+    CFLAGS += [
+        '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+            'frameworks/wilhelm/include',
+            'system/media/wilhelm/include',
+        ]
+    ]
--- a/media/mtransport/third_party/nICEr/src/ice/ice_socket.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c
@@ -76,17 +76,17 @@ static void nr_ice_socket_readable_cb(NR
     if (len_s > (size_t)INT_MAX)
       return;
 
     len = (int)len_s;
 
 #ifdef USE_TURN
   re_process:
 #endif /* USE_TURN */
-    r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Read %d bytes from %s",sock->ctx->label,len,addr.as_string);
+    r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Read %d bytes %sfrom %s",sock->ctx->label,len,(processed_indication ? "relayed " : ""),addr.as_string);
 
     /* First question: is this STUN or not? */
     is_stun=nr_is_stun_message(buf,len);
 
     if(is_stun){
       is_req=nr_is_stun_request_message(buf,len);
       is_ind=is_req?0:nr_is_stun_indication_message(buf,len);
 
--- a/mobile/android/base/background/announcements/AnnouncementsConstants.java.in
+++ b/mobile/android/base/background/announcements/AnnouncementsConstants.java.in
@@ -40,11 +40,11 @@ public class AnnouncementsConstants {
   // Stop reporting idle counts once they hit one year.
   public static long MAX_SANE_IDLE_DAYS = 365;
 
   // Don't track last launch if the timestamp is ridiculously out of range:
   // four years after build.
   public static long LATEST_ACCEPTED_LAUNCH_TIMESTAMP_MSEC = GlobalConstants.BUILD_TIMESTAMP_MSEC +
                                                              4 * 365 * MILLISECONDS_PER_DAY;
 
-  public static String ANNOUNCE_USER_AGENT = "Firefox Announcements " + GlobalConstants.MOZ_APP_VERSION;
+  public static String USER_AGENT = "Firefox Announcements " + GlobalConstants.MOZ_APP_VERSION;
   public static String ANNOUNCE_CHANNEL = GlobalConstants.MOZ_UPDATE_CHANNEL.replace("default", GlobalConstants.MOZ_OFFICIAL_BRANDING ? "release" : "dev");
 }
--- a/mobile/android/base/background/announcements/AnnouncementsFetchResourceDelegate.java
+++ b/mobile/android/base/background/announcements/AnnouncementsFetchResourceDelegate.java
@@ -42,21 +42,25 @@ public class AnnouncementsFetchResourceD
 
   public AnnouncementsFetchResourceDelegate(Resource resource, AnnouncementsFetchDelegate delegate) {
     super(resource);
     this.startTime = System.currentTimeMillis();
     this.delegate  = delegate;
   }
 
   @Override
+  public String getUserAgent() {
+    return delegate.getUserAgent();
+  }
+
+  @Override
   public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
     super.addHeaders(request, client);
 
     // The basics.
-    request.addHeader("User-Agent",      delegate.getUserAgent());
     request.addHeader("Accept-Language", delegate.getLocale().toString());
     request.addHeader("Accept",          ACCEPT_HEADER);
 
     // We never want to keep connections alive.
     request.addHeader("Connection", "close");
 
     // Set If-Modified-Since to avoid re-fetching content.
     final String ifModifiedSince = delegate.getLastDate();
@@ -171,9 +175,9 @@ public class AnnouncementsFetchResourceD
   /**
    * Be very thorough in case the superclass implementation changes.
    * We never want this to be an authenticated request.
    */
   @Override
   public AuthHeaderProvider getAuthHeaderProvider() {
     return null;
   }
-}
\ No newline at end of file
+}
--- a/mobile/android/base/background/announcements/AnnouncementsService.java
+++ b/mobile/android/base/background/announcements/AnnouncementsService.java
@@ -162,16 +162,17 @@ public class AnnouncementsService extend
   protected long getEarliestNextFetch() {
     return this.getSharedPreferences().getLong(AnnouncementsConstants.PREF_EARLIEST_NEXT_ANNOUNCE_FETCH, 0L);
   }
 
   protected void setLastFetch(final long fetch) {
     this.getSharedPreferences().edit().putLong(AnnouncementsConstants.PREF_LAST_FETCH_LOCAL_TIME, fetch).commit();
   }
 
+  @Override
   public long getLastFetch() {
     return this.getSharedPreferences().getLong(AnnouncementsConstants.PREF_LAST_FETCH_LOCAL_TIME, 0L);
   }
 
   protected String setLastDate(final String fetch) {
     if (fetch == null) {
       this.getSharedPreferences().edit().remove(AnnouncementsConstants.PREF_LAST_FETCH_SERVER_DATE).commit();
       return null;
@@ -220,17 +221,17 @@ public class AnnouncementsService extend
 
   @Override
   public Locale getLocale() {
     return Locale.getDefault();
   }
 
   @Override
   public String getUserAgent() {
-    return AnnouncementsConstants.ANNOUNCE_USER_AGENT;
+    return AnnouncementsConstants.USER_AGENT;
   }
 
   protected void persistTimes(long fetched, String date) {
     setLastFetch(fetched);
     if (date != null) {
       setLastDate(date);
     }
   }
--- a/mobile/android/base/background/bagheera/BagheeraClient.java
+++ b/mobile/android/base/background/bagheera/BagheeraClient.java
@@ -162,16 +162,21 @@ public class BagheeraClient {
                                     final BagheeraRequestDelegate delegate) {
       super(resource);
       this.namespace = namespace;
       this.id = id;
       this.delegate = delegate;
     }
 
     @Override
+    public String getUserAgent() {
+      return delegate.getUserAgent();
+    }
+
+    @Override
     public int socketTimeout() {
       return DEFAULT_SOCKET_TIMEOUT_MSEC;
     }
 
     @Override
     public void handleHttpResponse(HttpResponse response) {
       final int status = response.getStatusLine().getStatusCode();
       switch (status) {
--- a/mobile/android/base/background/bagheera/BagheeraRequestDelegate.java
+++ b/mobile/android/base/background/bagheera/BagheeraRequestDelegate.java
@@ -5,9 +5,11 @@
 package org.mozilla.gecko.background.bagheera;
 
 import ch.boye.httpclientandroidlib.HttpResponse;
 
 public interface BagheeraRequestDelegate {
   void handleSuccess(int status, String namespace, String id, HttpResponse response);
   void handleError(Exception e);
   void handleFailure(int status, String namespace, HttpResponse response);
+
+  public String getUserAgent();
 }
--- a/mobile/android/base/background/fxa/FxAccountClient10.java
+++ b/mobile/android/base/background/fxa/FxAccountClient10.java
@@ -15,16 +15,17 @@ import java.util.Arrays;
 import java.util.Locale;
 import java.util.concurrent.Executor;
 
 import javax.crypto.Mac;
 
 import org.json.simple.JSONObject;
 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientMalformedResponseException;
 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
+import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.crypto.HKDF;
 import org.mozilla.gecko.sync.net.AuthHeaderProvider;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 import org.mozilla.gecko.sync.net.HawkAuthHeaderProvider;
 import org.mozilla.gecko.sync.net.Resource;
@@ -201,16 +202,21 @@ public class FxAccountClient10 {
     public AuthHeaderProvider getAuthHeaderProvider() {
       if (tokenId != null && reqHMACKey != null) {
         return new HawkAuthHeaderProvider(Utils.byte2Hex(tokenId), reqHMACKey, payload, skewHandler.getSkewInSeconds());
       }
       return super.getAuthHeaderProvider();
     }
 
     @Override
+    public String getUserAgent() {
+      return FxAccountConstants.USER_AGENT;
+    }
+
+    @Override
     public void handleHttpResponse(HttpResponse response) {
       try {
         final int status = validateResponse(response);
         skewHandler.updateSkew(response, now());
         invokeHandleSuccess(status, response);
       } catch (FxAccountClientRemoteException e) {
         if (!skewHandler.updateSkew(response, now())) {
           // If we couldn't update skew, but we got a failure, let's try clearing the skew.
--- a/mobile/android/base/background/fxa/FxAccountUtils.java
+++ b/mobile/android/base/background/fxa/FxAccountUtils.java
@@ -7,22 +7,26 @@ package org.mozilla.gecko.background.fxa
 import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 
+import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.background.nativecode.NativeCrypto;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.crypto.HKDF;
 import org.mozilla.gecko.sync.crypto.KeyBundle;
 import org.mozilla.gecko.sync.crypto.PBKDF2;
 
 public class FxAccountUtils {
+  private static final String LOG_TAG = FxAccountUtils.class.getSimpleName();
+
   public static final int SALT_LENGTH_BYTES = 32;
   public static final int SALT_LENGTH_HEX = 2 * SALT_LENGTH_BYTES;
 
   public static final int HASH_LENGTH_BYTES = 16;
   public static final int HASH_LENGTH_HEX = 2 * HASH_LENGTH_BYTES;
 
   public static final int CRYPTO_KEY_LENGTH_BYTES = 32;
   public static final int CRYPTO_KEY_LENGTH_HEX = 2 * CRYPTO_KEY_LENGTH_BYTES;
@@ -101,17 +105,23 @@ public class FxAccountUtils {
    * the plain-text password for any amount of time. Equivalent, but slightly
    * more secure, is the quickly client-side stretched password.
    * <p>
    * We separate this since multiple login-time operations want it, and the
    * PBKDF2 operation is computationally expensive.
    */
   public static byte[] generateQuickStretchedPW(byte[] emailUTF8, byte[] passwordUTF8) throws GeneralSecurityException, UnsupportedEncodingException {
     byte[] S = FxAccountUtils.KWE("quickStretch", emailUTF8);
-    return PBKDF2.pbkdf2SHA256(passwordUTF8, S, NUMBER_OF_QUICK_STRETCH_ROUNDS, 32);
+    try {
+      return NativeCrypto.pbkdf2SHA256(passwordUTF8, S, NUMBER_OF_QUICK_STRETCH_ROUNDS, 32);
+    } catch (Throwable t) {
+      // Important to catch Throwable's; we expressly want to catch UnsatisfiedLinkError instances.
+      Logger.warn(LOG_TAG, "Got throwable stretching password using native pbkdf2SHA256 implementation; ignoring and using Java implementation.", t);
+      return PBKDF2.pbkdf2SHA256(passwordUTF8, S, NUMBER_OF_QUICK_STRETCH_ROUNDS, 32);
+    }
   }
 
   /**
    * The password-derived credential used to authenticate to the Firefox Account
    * auth server.
    */
   public static byte[] generateAuthPW(byte[] quickStretchedPW) throws GeneralSecurityException, UnsupportedEncodingException {
     return HKDF.derive(quickStretchedPW, new byte[0], FxAccountUtils.KW("authPW"), 32);
--- a/mobile/android/base/background/healthreport/HealthReportConstants.java.in
+++ b/mobile/android/base/background/healthreport/HealthReportConstants.java.in
@@ -6,16 +6,18 @@
 package org.mozilla.gecko.background.healthreport;
 
 import org.mozilla.gecko.background.common.GlobalConstants;
 
 public class HealthReportConstants {
   public static final String HEALTH_AUTHORITY = "@ANDROID_PACKAGE_NAME@.health";
   public static final String GLOBAL_LOG_TAG = "GeckoHealth";
 
+  public static final String USER_AGENT = "Firefox-Android-HealthReport/ (" + GlobalConstants.MOZ_APP_DISPLAYNAME + " " + GlobalConstants.MOZ_APP_VERSION + ")";
+
   /**
    * The earliest allowable value for the last ping time, corresponding to May 2nd 2013.
    * Used for sanity checks.
    */
   public static final long EARLIEST_LAST_PING = 1367500000000L;
 
   // Not `final` so we have the option to turn this on at runtime with a magic addon.
   public static boolean UPLOAD_FEATURE_DISABLED = false;
--- a/mobile/android/base/background/healthreport/upload/AndroidSubmissionClient.java
+++ b/mobile/android/base/background/healthreport/upload/AndroidSubmissionClient.java
@@ -200,16 +200,21 @@ public class AndroidSubmissionClient imp
       this.delegate = delegate;
       this.localTime = localTime;
       this.isUpload = isUpload;
       this.methodString = this.isUpload ? "upload" : "delete";
       this.id = id;
     }
 
     @Override
+    public String getUserAgent() {
+      return HealthReportConstants.USER_AGENT;
+    }
+
+    @Override
     public void handleSuccess(int status, String namespace, String id, HttpResponse response) {
       BaseResource.consumeEntity(response);
       if (isUpload) {
         setLastUploadLocalTimeAndDocumentId(localTime, id);
       }
       Logger.debug(LOG_TAG, "Successful " + methodString + " at " + localTime + ".");
       delegate.onSuccess(localTime, id);
     }
--- a/mobile/android/base/browserid/verifier/BrowserIDRemoteVerifierClient.java
+++ b/mobile/android/base/browserid/verifier/BrowserIDRemoteVerifierClient.java
@@ -4,17 +4,16 @@
 
 package org.mozilla.gecko.browserid.verifier;
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierErrorResponseException;
 import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierMalformedResponseException;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.sync.net.BaseResource;
@@ -33,16 +32,21 @@ public class BrowserIDRemoteVerifierClie
     private final BrowserIDVerifierDelegate delegate;
 
     protected RemoteVerifierResourceDelegate(Resource resource, BrowserIDVerifierDelegate delegate) {
       super(resource);
       this.delegate = delegate;
     }
 
     @Override
+    public String getUserAgent() {
+      return null;
+    }
+
+    @Override
     public void handleHttpResponse(HttpResponse response) {
       SyncResponse res = new SyncResponse(response);
       int statusCode = res.getStatusCode();
       Logger.debug(LOG_TAG, "Got response with status code " + statusCode + ".");
 
       if (statusCode != 200) {
         delegate.handleError(new BrowserIDVerifierErrorResponseException("Expected status code 200."));
         return;
--- a/mobile/android/base/fxa/FxAccountConstants.java.in
+++ b/mobile/android/base/fxa/FxAccountConstants.java.in
@@ -1,15 +1,16 @@
 #filter substitution
 /* 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.fxa;
 
+import org.mozilla.gecko.background.common.GlobalConstants;
 import org.mozilla.gecko.background.common.log.Logger;
 
 public class FxAccountConstants {
   public static final String GLOBAL_LOG_TAG = "FxAccounts";
   public static final String ACCOUNT_TYPE = "@MOZ_ANDROID_SHARED_FXACCOUNT_TYPE@";
 
   public static final String DEFAULT_AUTH_SERVER_ENDPOINT = "https://api.accounts.firefox.com/v1";
   public static final String DEFAULT_TOKEN_SERVER_ENDPOINT = "https://token.services.mozilla.com/1.0/sync/1.5";
@@ -26,9 +27,11 @@ public class FxAccountConstants {
     }
   }
 
   // You must be at least 14 years old to create a Firefox Account.
   public static final int MINIMUM_AGE_TO_CREATE_AN_ACCOUNT = 14;
 
   // You must wait 15 minutes after failing an age check before trying to create a different account.
   public static final long MINIMUM_TIME_TO_WAIT_AFTER_AGE_CHECK_FAILED_IN_MILLISECONDS = 15 * 60 * 1000;
+
+  public static final String USER_AGENT = "Firefox-Android-FxAccounts/ (" + GlobalConstants.MOZ_APP_DISPLAYNAME + " " + GlobalConstants.MOZ_APP_VERSION + ")";
 }
--- a/mobile/android/base/fxa/activities/FxAccountAbstractSetupActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountAbstractSetupActivity.java
@@ -9,29 +9,29 @@ import java.util.Map;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
 import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
 import org.mozilla.gecko.background.fxa.FxAccountUtils;
 import org.mozilla.gecko.background.fxa.PasswordStretcher;
+import org.mozilla.gecko.background.fxa.QuickPasswordStretcher;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.ProgressDisplay;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.fxa.login.Engaged;
 import org.mozilla.gecko.fxa.login.State;
 import org.mozilla.gecko.sync.SyncConfiguration;
 import org.mozilla.gecko.sync.setup.Constants;
 import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
 
 import android.accounts.AccountManager;
 import android.content.Intent;
 import android.text.Editable;
-import android.text.InputType;
 import android.text.TextWatcher;
 import android.text.method.PasswordTransformationMethod;
 import android.text.method.SingleLineTransformationMethod;
 import android.util.Patterns;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnFocusChangeListener;
@@ -298,9 +298,18 @@ abstract public class FxAccountAbstractS
       setResult(RESULT_OK, intent);
 
       // Show success activity depending on verification status.
       Intent successIntent = makeSuccessIntent(email, result);
       startActivity(successIntent);
       finish();
     }
   }
+
+  /**
+   * Factory function that produces a new PasswordStretcher instance.
+   *
+   * @return PasswordStretcher instance.
+   */
+  protected PasswordStretcher makePasswordStretcher(String password) {
+    return new QuickPasswordStretcher(password);
+  }
 }
--- a/mobile/android/base/fxa/activities/FxAccountCreateAccountActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountCreateAccountActivity.java
@@ -15,17 +15,16 @@ import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
 import org.mozilla.gecko.background.fxa.FxAccountClient;
 import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
 import org.mozilla.gecko.background.fxa.FxAccountClient20;
 import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
 import org.mozilla.gecko.background.fxa.PasswordStretcher;
-import org.mozilla.gecko.background.fxa.QuickPasswordStretcher;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.FxAccountCreateAccountTask;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
@@ -191,27 +190,27 @@ public class FxAccountCreateAccountActiv
           public void onClick(DialogInterface dialog, int which) {
             yearEdit.setText(yearItems[which]);
             updateButtonState();
           }
         };
         final AlertDialog dialog = new AlertDialog.Builder(FxAccountCreateAccountActivity.this)
         .setTitle(R.string.fxaccount_create_account_year_of_birth)
         .setItems(yearItems, listener)
-        .setIcon(R.drawable.fxaccount_icon)
+        .setIcon(R.drawable.icon)
         .create();
 
         dialog.show();
       }
     });
   }
 
   public void createAccount(String email, String password, Map<String, Boolean> engines) {
     String serverURI = FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT;
-    PasswordStretcher passwordStretcher = new QuickPasswordStretcher(password);
+    PasswordStretcher passwordStretcher = makePasswordStretcher(password);
     // This delegate creates a new Android account on success, opens the
     // appropriate "success!" activity, and finishes this activity.
     RequestDelegate<LoginResponse> delegate = new AddAccountDelegate(email, passwordStretcher, serverURI, engines) {
       @Override
       public void handleError(Exception e) {
         showRemoteError(e, R.string.fxaccount_create_account_unknown_error);
       }
 
--- a/mobile/android/base/fxa/activities/FxAccountSignInActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountSignInActivity.java
@@ -10,17 +10,16 @@ import java.util.concurrent.Executors;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountClient;
 import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
 import org.mozilla.gecko.background.fxa.FxAccountClient20;
 import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
 import org.mozilla.gecko.background.fxa.PasswordStretcher;
-import org.mozilla.gecko.background.fxa.QuickPasswordStretcher;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.FxAccountSignInTask;
 import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
 
 import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -98,17 +97,17 @@ public class FxAccountSignInActivity ext
       return;
     }
     this.setResult(resultCode, data);
     this.finish();
   }
 
   public void signIn(String email, String password) {
     String serverURI = FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT;
-    PasswordStretcher passwordStretcher = new QuickPasswordStretcher(password);
+    PasswordStretcher passwordStretcher = makePasswordStretcher(password);
     // This delegate creates a new Android account on success, opens the
     // appropriate "success!" activity, and finishes this activity.
     RequestDelegate<LoginResponse> delegate = new AddAccountDelegate(email, passwordStretcher, serverURI) {
       @Override
       public void handleError(Exception e) {
         showRemoteError(e, R.string.fxaccount_sign_in_unknown_error);
       }
 
--- a/mobile/android/base/fxa/activities/FxAccountUpdateCredentialsActivity.java
+++ b/mobile/android/base/fxa/activities/FxAccountUpdateCredentialsActivity.java
@@ -11,17 +11,16 @@ import org.mozilla.gecko.R;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.fxa.FxAccountClient;
 import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
 import org.mozilla.gecko.background.fxa.FxAccountClient20;
 import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
 import org.mozilla.gecko.background.fxa.FxAccountUtils;
 import org.mozilla.gecko.background.fxa.PasswordStretcher;
-import org.mozilla.gecko.background.fxa.QuickPasswordStretcher;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.FxAccountSignInTask;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.fxa.login.Engaged;
 import org.mozilla.gecko.fxa.login.State;
 import org.mozilla.gecko.fxa.login.State.StateLabel;
 import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
 
@@ -152,17 +151,17 @@ public class FxAccountUpdateCredentialsA
       redirectToActivity(FxAccountStatusActivity.class);
     }
   }
 
   public void updateCredentials(String email, String password) {
     String serverURI = fxAccount.getAccountServerURI();
     Executor executor = Executors.newSingleThreadExecutor();
     FxAccountClient client = new FxAccountClient20(serverURI, executor);
-    PasswordStretcher passwordStretcher = new QuickPasswordStretcher(password);
+    PasswordStretcher passwordStretcher = makePasswordStretcher(password);
     try {
       hideRemoteError();
       RequestDelegate<LoginResponse> delegate = new UpdateCredentialsDelegate(email, passwordStretcher, serverURI);
       new FxAccountSignInTask(this, this, email, passwordStretcher, client, delegate).execute();
     } catch (Exception e) {
       Logger.warn(LOG_TAG, "Got exception updating credentials for account.", e);
       showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
     }
--- a/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java
+++ b/mobile/android/base/fxa/sync/FxAccountSyncAdapter.java
@@ -293,16 +293,21 @@ public class FxAccountSyncAdapter extend
                                    final KeyBundle syncKeyBundle,
                                    final String clientState,
                                    final SessionCallback callback,
                                    final Bundle extras) {
     final TokenServerClientDelegate delegate = new TokenServerClientDelegate() {
       private boolean didReceiveBackoff = false;
 
       @Override
+      public String getUserAgent() {
+        return FxAccountConstants.USER_AGENT;
+      }
+
+      @Override
       public void handleSuccess(final TokenServerToken token) {
         FxAccountConstants.pii(LOG_TAG, "Got token! uid is " + token.uid + " and endpoint is " + token.endpoint + ".");
 
         if (!didReceiveBackoff) {
           // We must be OK to touch this token server.
           tokenBackoffHandler.setEarliestNextRequest(0L);
         }
 
--- a/mobile/android/base/locales/en-US/sync_strings.dtd
+++ b/mobile/android/base/locales/en-US/sync_strings.dtd
@@ -100,59 +100,64 @@
 <!ENTITY sync.title.send.tab.label 'Send Tab To Devices'>
 <!ENTITY sync.button.send.label 'Send'>
 <!ENTITY sync.button.set.up.sync.label 'Set up &syncBrand.shortName.label;'>
 <!ENTITY sync.title.redirect.to.set.up.sync.label 'Set up &syncBrand.shortName.label; to send tabs'>
 <!ENTITY sync.text.redirect.to.set.up.sync.label 'Set up &syncBrand.fullName.label; on your device to send tabs to other devices.'>
 <!ENTITY sync.text.tab.sent.label 'Your tab was sent!'>
 <!ENTITY sync.text.tab.not.sent.label 'There was a problem sending your tab.'>
 
-<!-- Firefox account strings. -->
+<!-- Firefox Account strings. -->
 
 <!-- Localization note: these are shown in all screens that query the
      user for an email address and password. Hide and show are button
      labels. -->
 <!ENTITY fxaccount_email_hint 'Email'>
 <!ENTITY fxaccount_password_hint 'Password'>
 <!ENTITY fxaccount_password_hide 'Hide'>
 <!ENTITY fxaccount_password_show 'Show'>
 
 <!-- Localization note: these are shown in screens after the user has
      created or signed in to an account, and take the user back to
      Firefox. -->
 <!ENTITY fxaccount_back_to_browsing 'Back to browsing'>
 
+<!-- Localization note: the following two strings are interpolated
+     into fxaccount_create_account_policy_text2; see note for that
+     string as well.  Compare fxaccount_status_{linktos,linkprivacy}:
+     these strings are separated to accommodate languages that decline
+     the two uses differently. -->
 <!ENTITY fxaccount_policy_linktos 'Terms of Service'>
 <!ENTITY fxaccount_policy_linkprivacy 'Privacy Notice'>
 
 <!ENTITY fxaccount_getting_started_welcome_to_sync 'Welcome to &syncBrand.shortName.label;'>
 <!ENTITY fxaccount_getting_started_description 'Sign in to sync your tabs, bookmarks, passwords &amp; more.'>
 <!ENTITY fxaccount_getting_started_get_started 'Get started'>
 <!ENTITY fxaccount_getting_started_old_firefox 'Using an older version of &syncBrand.shortName.label;?'>
 
 <!-- Localization note: the Firefox below should not change with the
      particular version of Firefox installed (Release, Beta, Aurora,
-     etc).  The account remains a "Firefox" account. -->
-<!ENTITY fxaccount_create_account_header 'Create a Firefox account'>
+     etc).  The account remains a "Firefox Account". -->
+<!ENTITY fxaccount_create_account_header2 'Create a Firefox Account'>
 <!ENTITY fxaccount_create_account_password_length_restriction 'Must be at least 8 characters'>
 <!ENTITY fxaccount_create_account_year_of_birth 'Year of birth'>
 <!-- Localization note: &formatS1; is fxaccount_policy_linktos, &formatS2; is fxaccount_policy_linkprivacy, both hyperlinked. -->
-<!ENTITY fxaccount_create_account_policy_text 'By proceeding, I agree to the &formatS1; and &formatS2; of Firefox online services.'>
+<!ENTITY fxaccount_create_account_policy_text2 'By proceeding, I agree to the &formatS1; and &formatS2; of Firefox cloud services.'>
 <!ENTITY fxaccount_create_account_button 'Next'>
 <!ENTITY fxaccount_create_account_choose_what_to_sync 'Choose what to sync'>
 <!ENTITY fxaccount_create_account_sign_in_instead 'Already have an account? Sign in'>
 <!ENTITY fxaccount_create_account_1990_or_earlier '1990 or earlier'>
 <!ENTITY fxaccount_create_account_unknown_error 'Could not create account'>
 
 <!ENTITY fxaccount_account_create_not_allowed 'Cannot create account'>
 <!ENTITY fxaccount_account_create_not_allowed_you_must_meet_certain_age_requirements 'You must meet certain age requirements to create an account.'>
 <!ENTITY fxaccount_account_create_not_allowed_learn_more 'Learn more'>
 
 <!ENTITY fxaccount_confirm_account_header 'Confirm your account'>
-<!-- Localization note: &formatS; is the Firefox account's email address. -->
+<!-- Localization note: &formatS; is the Firefox Account's email address. -->
 <!ENTITY fxaccount_confirm_account_verification_link 'A verification link has been sent to &formatS;'>
 <!ENTITY fxaccount_confirm_account_resend_email 'Resend email'>
 <!ENTITY fxaccount_confirm_account_verification_link_sent2 'Verification email sent'>
 <!ENTITY fxaccount_confirm_account_verification_link_not_sent2 'Couldn\&apos;t send verification email'>
 
 <!ENTITY fxaccount_sign_in_sub_header 'Sign in'>
 <!ENTITY fxaccount_sign_in_button_label 'Sign in'>
 <!ENTITY fxaccount_sign_in_forgot_password 'Forgot password?'>
@@ -161,38 +166,44 @@
 
 <!ENTITY fxaccount_account_verified_sub_header 'Account verified'>
 <!ENTITY fxaccount_account_verified_description2 'Your data will begin syncing momentarily.'>
 
 <!ENTITY fxaccount_update_credentials_header 'Sign in'>
 <!ENTITY fxaccount_update_credentials_button_label 'Sign in'>
 <!ENTITY fxaccount_update_credentials_unknown_error 'Could not sign in'>
 
-<!ENTITY fxaccount_status_header 'Firefox account'>
+<!ENTITY fxaccount_status_header2 'Firefox Account'>
 <!ENTITY fxaccount_status_signed_in_as 'Signed in as'>
 <!ENTITY fxaccount_status_sync '&syncBrand.shortName.label;'>
 <!ENTITY fxaccount_status_sync_enabled '&syncBrand.shortName.label;: enabled'>
 <!ENTITY fxaccount_status_needs_verification2 'Your account needs to be verified. Tap to resend verification email.'>
 <!ENTITY fxaccount_status_needs_credentials 'Cannot connect. Tap to sign in.'>
 <!ENTITY fxaccount_status_needs_upgrade 'You need to upgrade &brandShortName; to sign in.'>
 <!ENTITY fxaccount_status_bookmarks 'Bookmarks'>
 <!ENTITY fxaccount_status_history 'History'>
 <!ENTITY fxaccount_status_passwords 'Passwords'>
 <!ENTITY fxaccount_status_tabs 'Open tabs'>
 <!ENTITY fxaccount_status_legal 'Legal' >
+<!-- Localization note: when tapped, the following two strings link to
+     external web pages.  Compare fxaccount_policy_{linktos,linkprivacy}:
+     these strings are separated to accommodate languages that decline
+     the two uses differently. -->
+<!ENTITY fxaccount_status_linktos 'Terms of Service'>
+<!ENTITY fxaccount_status_linkprivacy 'Privacy Notice'>
 
 <!-- Localization note: this is the name shown by the Android system
-     itself for a Firefox account. Don't localize this. -->
+     itself for a Firefox Account. Don't localize this. -->
 <!ENTITY fxaccount_account_type_label 'Firefox'>
 
 <!-- Localization note: these are shown by the Android system itself,
      when the user navigates to the Android > Accounts > [Firefox
-     Account] Screen. The link takes the user to the Firefox account
+     Account] Screen. The link takes the user to the Firefox Account
      status activity, which lets them manage their Firefox
-     account. -->
+     Account. -->
 <!ENTITY fxaccount_options_title '&syncBrand.shortName.label; Options'>
 <!ENTITY fxaccount_options_configure_title 'Configure &syncBrand.shortName.label;'>
 
 <!-- Localization note: these error messages are shown after a request
      has been made to the remote server, and an error of some type has
      been returned. -->
 <!ENTITY fxaccount_remote_error_UPGRADE_REQUIRED 'You need to upgrade Firefox'>
 
@@ -203,10 +214,10 @@
 <!ENTITY fxaccount_remote_error_ATTEMPT_TO_OPERATE_ON_AN_UNVERIFIED_ACCOUNT 'Account is not verified'>
 <!ENTITY fxaccount_remote_error_CLIENT_HAS_SENT_TOO_MANY_REQUESTS 'Server busy, try again soon'>
 <!ENTITY fxaccount_remote_error_SERVICE_TEMPORARILY_UNAVAILABLE_TO_DUE_HIGH_LOAD 'Server busy, try again soon'>
 <!ENTITY fxaccount_remote_error_UNKNOWN_ERROR 'There was a problem'>
 <!ENTITY fxaccount_remote_error_COULD_NOT_CONNECT 'Cannot connect to network'>
 
 <!ENTITY fxaccount_sync_sign_in_error_notification_title2 '&syncBrand.shortName.label; is not connected'>
 <!-- Note to translators: the format string below will be replaced
-     with the Firefox account's email address. -->
+     with the Firefox Account's email address. -->
 <!ENTITY fxaccount_sync_sign_in_error_notification_text2 'Tap to sign in as &formatS;'>
deleted file mode 100755
index 131f05dd288a4af90f7f0f99decea7de30ab9974..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
old mode 100755
new mode 100644
index dba656bd09b8129980ba9bf9f238f23c7e59c345..2f3868bb9dc4a5a10cb5f1e93c65783eaf59506e
GIT binary patch
literal 3773
zc${rkX*`te+a9|_MAil)QA*i0WmgzNLMW9|SxaM-lB`*>WQk!ylI207kUjgJB@MH$
z%w~-+mMH)GdEZa}-}~MluIoOJ^E!^>JkQ_t;YxCHv=I|g5CMTeVz#gg&cHqd0`c$*
z^8tU?NGUjA<M*|2umFK-)A#S*764+N5N8`pP|Y}a4g}&Yak6){0zk?PvuET74o}5m
zsdNU1&YGJdQ2~4cL!2VdU}?0LmX`7H2?B`;WND090)<YUnWZu32s8#94lge+$CIga
zCXiwQSsH@_5UI>r44Fou(P&H#8cU|kuxT^wQ38p=n4Q27{^uBbib$o;%;6|>G@gnh
z(I*KMES^dQEC4Q^f+11>$|Qk0i6{TSlFF;=r-+m(98K5Q8n6adZ6hlkV=EPXBMgB;
zV*wPP_&F+LmO3*>XR>LGISi2o5P<>!K{TF3o0$dhDLe&OfB*iy#^vtq?VUbrMV)5p
znpn{p>>vM@&HjcXqVZ%v6QE2HsB3GRKbKbkqtoZC0T)1u%KBFXXmfdG1yERBThq`p
z0qW5*u>jfxKq8HSAy5fa1~AFx<z-z{8_;v?_bCE!cwupoNMi<tMlLNaQ-D!3I9L)L
zN1o=1!UC+Nr6mGo8We%O<sXclo;_>jNS<apmQ$3|2%_;gV5*ky$sIVhO)15+h}=)&
ze5bI9GqX=x>94Z$fM(aZT=!f4I3h_t1^>FAp`JxNl0lG6#Fve+gkx~^O>G1U1C1pa
z=97?vjOdP;%I_=<B(V+4K3hP>5{No)NYY7o_m9+HzgBO3qEFIh!LJCzWKRAN^Bb8{
z_>GCik;B?%f}5vney|=iPD>=<aMQD2CfQ9G_9%t@8O`#or`@TgCHF8sOt1{i?OZCU
zr*ep%HPp&aU#19@lFFJMJSXrAt!RX~w7ing#W26<y1o57y^rxEDxsjbJRl@o&lJYy
z%mFtfJ*VK(HSgArp3L00XY4%Hfb00^k+Y)<2)17x%>DC<=dY%UkhmUa0Qzv-n@`|s
z)#K8_KhD|`gjwGlx$vF2n3og_M=ylUYFC`;=b+)0P3MZSmDOkSVv+L!=$RyJ%hRp2
zI?U$i#EY#ti}Ut7#p{eij81A@{5s7tZ#tlOiE23~kF?pPa90P-Qxt!LK>MM#7c5+#
z5|;`#y|QhT29>`dqD5e}JVzj4bS9f%a3aoQaxw2@l5Gtw@RoAAQI2FT)q?**jFgpY
zz-QUT+FOneh?bECGgjm0#h;T;3*QiYecQKpOWVGWkLHJU=+Sh)_iCp(zx0~QNp(<;
zQusnKI|jMqzNI-J-Jq|1MjF2E@7LTGczN`I;~H-)`fhVro2d1LRI?1H=X7vx7fQBS
zVYFx}er<>YPZ84n()S83y6FdT@l=JeS8nj$J()<yZ1uVpng5L}MO+Buu|k(-4C{EQ
zB*w%Ioekd4o6NdY^mY^j5<aC8v~=yOg1N>6!`nB9eL$5acVjd`6W3spHj>6d!mDbD
zcgC&xB|fXh$!3lPzjoO^VD9|6K`p&vmOM7_*x2um`K+ZG^1Q6LmVU;V%gJ1?b<^=P
zRkF?T6~dAt65OO85C7iHS}Bw-xhBV!j}xiuGdgN#Tyb5o9DTE101}8(AO6I+vai>2
zH-^z*B~br_FTk&gu?7ow<>AQ(|2)1^#m8%S4*K+$K!88ZnS7^7@2fe++#F;&c+ZVq
ztZ0UfUiy1hUMJ{hK;BE+_bBgj=nf`wCl=oO&Mz?;0+C2O#S{s%y<Be)5X&D1X;XQB
zB<;PK)0LK&;BE!;ml*}p%cr8{1d5LS)5IH_4f2W*fh6&19--vEe(Mwes$Pb-=aA@J
zX?Ug}Z|;wL*-HvSD~Y`O_?i3EwSyDKzf#)5>pAl+HtDV7HzEmoIyae26CKB3EwLL-
zAA|yf78=0ZLgUAc-Ts9oO}dvpa0up~+^&~vj|~|~^dG)wlFAi_!Ts6_WRb@=Yl95u
z`k{`Dx=ev@76?dd3;Z&FDUDq`D1L3)LN{Be5w7@31Tj1KkJiMi`38f{E9;G>ar2z!
zm9fX6zhjdvr0{%rwX@fx&r}sh{$mt4T6d(NI@<nF)#XnAii7oBnGrR&!wP;eytdAw
ztNZ&S$g&ihjxW~{y&JtgauQ~PHb=yotj=UwkEoS3zAKDFNohSv{62)tnrXXjwmhKg
z@6^(N{=$;TgVNdTzDCpA9c<mrwSay|@B#4y4{hPu^P?Yk8|bah87-+VHZ%8^NkUv2
zsanw$6Z8;B!4}-g#2AT?)5<&DGI{DZ^1g=YuW9-E3zvo5%b;Jrk5*ZfOw>d<z8OIk
zRTRh-R_V{d-TZbjT=2za2%L~%DYVMCQRhO4{1$?EBB1TK5sl>u(nPeoqP23$^{>iw
z>K{5H;5x>U)BhRjo?yQhdB1)2xmE(KKQNs$nv~@#-1NR7XYlev>OxSSPgkga9{mQ1
zFDp1Ti#qMA6^mew|DuGB6#gM@nHlLl9X8ljuP|kl9e5UI>4ttf9zOPVZaG0LKYkrs
znHVx_Fg-&M9O88qz{OrXcK>>AIq}-g$m8-%w_8<ZeMy@A`#y7?KYfDrS}GX+`Ch(8
zIU$Ya%P?LQ>EavjYF)-hM06zV@TEmv<$LFR5G8eKtH(!5hzWf{;{2s2c<jDZiA^7h
z2@-|#W}<7~L~4&;Z65F4RP1#~|EIg@%6s>(1&G~ko2?UOmxUc1j;HHD&oEBKQJY9D
zHw!C;9VpD`Ay|jWm%V<eY;Ztcb+;<AC>#pW<^9C~M+s^i1`8ZMAKahR7arrCVO{#y
zrQBpFV+<ztn2<i-h{y;i{ad~7_cn-=YJX4RC|7h6Ys#wfSXBH4?-fXUHB?a>e5C(!
zU!JYL>%HW1qvSvrs{#~La7I|4ZBrnlV#pVOr2Zni_TQU2h<bf;CsVvBguEK`R~qd5
zA(Kxx?Obex%241Zr@rydrbQgiC+(6;iZQPXudYH1av2KY`+Cx@t+Y$%hlMvJuy8|R
z^1HU0G*KlVzVS6wuu0jnWy0W6rMWH1WWcki+Oyx}=JtE}2>!gVQH0_%J+egR!th}?
zjdnG51(cN``TSgn1m95eO(-dFA#(~9VrjK&xyuKJ=#0jk5FJ}dX%T<W8L8VI(PX%K
zab*l@ZuzD?UM??8)5-A5usO=P>$lQ*QFW&c#lCJHGzxzQN|cwd_x3cF453zq?<P1I
z%pR1<c&fh0pBAdLKihPjE48sueT&=LD7}BkdZ1kV;(1K$F{jh0j>E_kyf+5XCKKAG
z9}n1^Kh-e9;wn_G`JFR{bl&U1TWX$aXN%WuCa*XK8ToGhf=AQzY8UqzJDB`PZdQ6F
z3F$>ayOdGw_Z15Xr)FeA%Mq$#&w|ss-R!}w#_IX~j~>Q^pWi67iO2i+8)WEQmqMuL
z6Nc-uP}kZ5Jz<|7$T-pnKGUA?;OM|al&a>4+wFj#fmL_H!vn-M&Yg->DwaQNqY{qV
zXBb`3g`rE2d`?v81K$bs^Ws@?5Z*DYpAuqZN7t(Fn1!aJ%5ag1;=S4`i{1l%OZbm{
zMUgL55m@g&v4$gH%9z~QM-lf6Ri;etgSs2wZ$w#h757Y(_ndd_Z=CE<8u2h30loI-
zpPS^_Z8bW|%GbY@pK&f{Okcfm)uUkJz|q){a3QvVdYWyHn4U?-SF~_X&h#;j*6R_T
zB4u+*X*caW*53AOUvz+Mxt%t0AU7X>ME$t2-apN7_gwkt@$pjY*_8H4erJxHWJ${2
z>Q?VDu7d;j6{c7GA@`lpo<WDr^ADneJ=Ts$X><hGeg^smif__H7HY1IVcc1HV4;tR
zV?7?Z1z8`W>I`MPrw)eN#n<#*_EQSUS?W%N?H|_3?VdoQYzllgw`y!q@pqj$N18AO
zYfmF2m%hV~?s&lF(^^2uHF#YzlFYC;N$}@p25Ge3d7M)l#8Aec^HaP133<@?<Q26^
zxkaA$?!^!4Rc<dN4_{Ayd@sweWK_mjf8lLEvGP-MswV0~-ArJpYU-iz_*pyUoRZdI
zseUzIksq!;ReC;(^&jHOy=xrp9XBw+g9AZQQTY>s*vHHekNM-Fc7;{&zVQ_>t>CTc
zX&pt9Pb9_7`{*_}GpSAqGEBZ`I6$>0EX%-5FD#15G=_B4C4Nl1D>Wn;?kC@ua$xhA
za;m6mUt{lTooanf$=Abp${C#yLV8idXc0^B0siy!gOb--S$e>u<v0`y)zI+oxNN3#
zTt`PoO-)TjMa3lIC%GjuGDTKvgUel6K^crp7X1;G{;v;tbpcm%&4q4XeYGLfL@-Sp
zD-HEph)f%=ZHwk#vR1p=SraW<eg113Rwkpk!4FdPlILo?U|oV-hJhbMfcY}kNkXJp
z0oE~J3^~Mat-4K9ipRFSi#TK<I0V~SOS5}A`DxMP7nO4~I+dAQa{3O->`wtGV*{}+
z(6ZYuT>c`}c(AtN<JQo&9y*4vl%ZGt;<;xMU+L<N@)zKKMkBZka)>!5WP#{DE-dgK
zawzU!KTC`M4K65VWV$cusX0d-%YmuwyIZ=pOdEogc3e6K+v)tPqLumElmMv<$zpXL
zRk+JUE@o3jiY<tpx$j_V3QP=*dCWOUaC`0D#C#{93wtqyxcUE>{GR|Pu&ru(R+hiy
zzw<8{>w>XEQ(oE86<c;<08${Zdd1V%m*j3N5hnB<#_PY+Q`C3{R5~e)-rhS<N5TYE
zuU^cJyUFg}wKvJwu!|q~dwmwPR<^r)(NYK%RjmYjhi-y@iO@P+`eGaTOzYn6^8R?U
ztxa(x;$gM4=-Oe7`H9DNG}krD)2(y0DdMhrS*yz5ki|_JVG`Eu?!!3?H;;$sPoCLJ
fLT>w^_dqh|<8Y;)t*3xDJjm9{@j{K|t=Rtn^L)ZN
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5599f931a917147f9e6737579d994d36ccba0eea
GIT binary patch
literal 2018
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
AR{#J2
deleted file mode 100644
index b6e7595e0bf7d65c88a5dc18f1d4c201ea22b273..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
index 983d8a654a4d06dd66e8dee5888aa93f1235dd25..89caec5c1311077196b308e83d7f748cc0d321a1
GIT binary patch
literal 2810
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d734d8be45d0fdbc122800fc4ed72ab2b2b31ee1
GIT binary patch
literal 5061
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
AQvd(}
--- a/mobile/android/base/resources/layout/fxaccount_create_account.xml
+++ b/mobile/android/base/resources/layout/fxaccount_create_account.xml
@@ -38,34 +38,32 @@
             android:hint="@string/fxaccount_create_account_year_of_birth"
             android:inputType="none" />
 
         <TextView
             android:id="@+id/policy"
             style="@style/FxAccountLinkifiedItem"
             android:layout_marginBottom="0dp"
             android:layout_marginTop="10dp"
+            android:layout_marginLeft="10dp"
+            android:layout_marginRight="10dp"
             android:text="@string/fxaccount_create_account_policy_text"
             android:textColorLink="@color/fxaccount_linkified_textColorLinkSubdued" />
 
         <TextView
             android:id="@+id/remote_error"
             style="@style/FxAccountErrorItem" />
 
         <RelativeLayout
             style="@style/FxAccountButtonLayout"
             android:layout_marginBottom="10dp" >
 
             <ProgressBar
                 android:id="@+id/progress"
-                style="@style/FxAccountProgress"
-                android:layout_alignBottom="@id/button"
-                android:layout_alignLeft="@id/button"
-                android:layout_alignRight="@id/button"
-                android:layout_alignTop="@id/button" />
+                style="@style/FxAccountProgress" />
 
             <Button
                 android:id="@+id/button"
                 style="@style/FxAccountButton"
                 android:text="@string/fxaccount_create_account_button" />
         </RelativeLayout>
 
         <CheckBox
@@ -86,9 +84,9 @@
 
         <LinearLayout style="@style/FxAccountSpacer" />
 
         <ImageView
             style="@style/FxAccountIcon"
             android:contentDescription="@string/fxaccount_empty_contentDescription" />
     </LinearLayout>
 
-</ScrollView>
+</ScrollView>
\ No newline at end of file
--- a/mobile/android/base/resources/layout/fxaccount_sign_in.xml
+++ b/mobile/android/base/resources/layout/fxaccount_sign_in.xml
@@ -25,21 +25,17 @@
         <TextView
             android:id="@+id/remote_error"
             style="@style/FxAccountErrorItem" />
 
         <RelativeLayout style="@style/FxAccountButtonLayout" >
 
             <ProgressBar
                 android:id="@+id/progress"
-                style="@style/FxAccountProgress"
-                android:layout_alignBottom="@id/button"
-                android:layout_alignLeft="@id/button"
-                android:layout_alignRight="@id/button"
-                android:layout_alignTop="@id/button" />
+                style="@style/FxAccountProgress" />
 
             <Button
                 android:id="@+id/button"
                 style="@style/FxAccountButton"
                 android:text="@string/fxaccount_sign_in_button_label" />
         </RelativeLayout>
 
         <LinearLayout
@@ -64,16 +60,18 @@
                 android:gravity="right"
                 android:text="@string/fxaccount_sign_in_create_account_instead" />
         </LinearLayout>
 
         <TextView
             android:id="@+id/policy"
             style="@style/FxAccountLinkifiedItem"
             android:layout_marginTop="10dp"
+            android:layout_marginLeft="10dp"
+            android:layout_marginRight="10dp"
             android:text="@string/fxaccount_create_account_policy_text"
             android:textColorLink="@color/fxaccount_linkified_textColorLinkSubdued" />
 
         <LinearLayout style="@style/FxAccountSpacer" />
 
         <ImageView
             style="@style/FxAccountIcon"
             android:contentDescription="@string/fxaccount_empty_contentDescription" />
--- a/mobile/android/base/resources/layout/fxaccount_update_credentials.xml
+++ b/mobile/android/base/resources/layout/fxaccount_update_credentials.xml
@@ -25,21 +25,17 @@
         <TextView
             android:id="@+id/remote_error"
             style="@style/FxAccountErrorItem" />
 
         <RelativeLayout style="@style/FxAccountButtonLayout" >
 
             <ProgressBar
                 android:id="@+id/progress"
-                style="@style/FxAccountProgress"
-                android:layout_alignBottom="@id/button"
-                android:layout_alignLeft="@id/button"
-                android:layout_alignRight="@id/button"
-                android:layout_alignTop="@id/button" />
+                style="@style/FxAccountProgress" />
 
             <Button
                 android:id="@+id/button"
                 style="@style/FxAccountButton"
                 android:text="@string/fxaccount_update_credentials_button_label" />
         </RelativeLayout>
 
         <TextView
--- a/mobile/android/base/resources/values/fxaccount_colors.xml
+++ b/mobile/android/base/resources/values/fxaccount_colors.xml
@@ -1,36 +1,35 @@
 <?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/. -->
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
   <color name="fxaccount_textColor">#424f59</color>
-  <color name="fxaccount_textColorSubdued">#c0c9d0</color>
+  <color name="fxaccount_textColorSubdued">#8a9ba8</color>
 
-  <color name="fxaccount_linkified_textColor">#c0c9d0</color>
-  <color name="fxaccount_linkified_textColorLink">#0096dd</color>
-  <color name="fxaccount_linkified_textColorLinkSubdued">#c0c9d0</color>
+  <color name="fxaccount_linkified_textColor">#8a9ba8</color>
+  <color name="fxaccount_linkified_textColorLink">#0095dd</color>
+  <color name="fxaccount_linkified_textColorLinkSubdued">#8a9ba8</color>
 
   <color name="fxaccount_error">#d63920</color>
 
   <color name="fxaccount_error_preference_backgroundcolor">#fad4d2</color>
 
   <color name="fxaccount_button_textColor">#ffffff</color>
-  <color name="fxaccount_button_background_active">#e66000</color>
-  <color name="fxaccount_button_background_hit">#fd9500</color>
-  <color name="fxaccount_button_background_loading">#424f59</color>
-  <color name="fxaccount_button_background_inactive">#c0c9d0</color>
+  <color name="fxaccount_button_background_active">#0095dd</color>
+  <color name="fxaccount_button_background_hit">#0088cc</color>
+  <color name="fxaccount_button_background_inactive">#8a9ba8</color>
   <color name="fxaccount_input_textColor">#424f59</color>
   <color name="fxaccount_input_textColor_pressed">#424f59</color>
-  <color name="fxaccount_input_textColor_inactive">#c0c9d0</color>
-  <color name="fxaccount_input_textColorHint">#c0c9d0</color>
-  <color name="fxaccount_link_textColor">#0096dd</color>
-  <color name="fxaccount_link_textColor_pressed">#00767d</color>
-  <color name="fxaccount_link_textColor_inactive">#c0c9d0</color>
-  <color name="fxaccount_input_borderActive">#6a7b86</color>
-  <color name="fxaccount_input_borderInactive">#c0c9d0</color>
-  <color name="fxaccount_password_show_textcolor">#c0c9d0</color>
+  <color name="fxaccount_input_textColor_inactive">#8a9ba8</color>
+  <color name="fxaccount_input_textColorHint">#8a9ba8</color>
+  <color name="fxaccount_link_textColor">#0095dd</color>
+  <color name="fxaccount_link_textColor_pressed">#0088cc</color>
+  <color name="fxaccount_link_textColor_inactive">#8a9ba8</color>
+  <color name="fxaccount_input_borderActive">#0095dd</color>
+  <color name="fxaccount_input_borderInactive">#8a9ba8</color>
+  <color name="fxaccount_password_show_textcolor">#8a9ba8</color>
   <color name="fxaccount_password_show_backgroundcolor">#ffffff</color>
   <color name="fxaccount_password_hide_textcolor">#ffffff</color>
-  <color name="fxaccount_password_hide_backgroundcolor">#424f59</color>
+  <color name="fxaccount_password_hide_backgroundcolor">#8a9ba8</color>
 </resources>
--- a/mobile/android/base/resources/values/fxaccount_dimens.xml
+++ b/mobile/android/base/resources/values/fxaccount_dimens.xml
@@ -1,17 +1,23 @@
 <?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/. -->
 
 <resources>
   <dimen name="fxaccount_stroke_width">1dp</dimen>
   <dimen name="fxaccount_corner_radius">5dp</dimen>
-  <dimen name="fxaccount_input_padding">10dp</dimen>
+
+  <!-- The amount of horizontal padding that appears inside the email,
+       password, etc input fields. -->
+  <dimen name="fxaccount_input_padding_horizontal">20dp</dimen>
+  <!-- And the amount of vertical padding that appears inside input
+       fields. -->
+  <dimen name="fxaccount_input_padding_vertical">10dp</dimen>
 
   <!-- Preference fragment padding, bottom -->
   <dimen name="preference_fragment_padding_bottom">0dp</dimen>
   <!-- Preference fragment padding, sides -->
   <dimen name="preference_fragment_padding_side">16dp</dimen>
 
   <integer name="preference_fragment_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
 </resources>
--- a/mobile/android/base/resources/values/fxaccount_styles.xml
+++ b/mobile/android/base/resources/values/fxaccount_styles.xml
@@ -5,17 +5,17 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/.
 -->
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
     <style name="FxAccountTheme" parent="@style/Gecko" />
 
     <style name="FxAccountTheme.FxAccountStatusActivity" parent="@style/FxAccountTheme">
-         <item name="android:windowNoTitle">false</item>
+        <item name="android:windowNoTitle">false</item>
     </style>
 
     <style name="FxAccountMiddle">
         <item name="android:background">@android:color/white</item>
         <item name="android:orientation">vertical</item>
         <item name="android:layout_width">fill_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_weight">1</item>
@@ -59,17 +59,20 @@
         <item name="android:padding">20dp</item>
         <item name="android:layout_width">fill_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginBottom">10dp</item>
     </style>
 
     <style name="FxAccountEditItem" parent="@android:style/Widget.EditText">
         <item name="android:textSize">20sp</item>
-        <item name="android:padding">@dimen/fxaccount_input_padding</item>
+        <item name="android:paddingLeft">@dimen/fxaccount_input_padding_horizontal</item>
+        <item name="android:paddingRight">@dimen/fxaccount_input_padding_horizontal</item>
+        <item name="android:paddingTop">@dimen/fxaccount_input_padding_vertical</item>
+        <item name="android:paddingBottom">@dimen/fxaccount_input_padding_vertical</item>
         <item name="android:background">@drawable/fxaccount_textfield_background</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:singleLine">true</item>
         <item name="android:textColor">@color/fxaccount_input_textColor</item>
         <item name="android:textColorHint">@color/fxaccount_input_textColorHint</item>
     </style>
 
@@ -83,17 +86,17 @@
         <item name="android:gravity">center</item>
     </style>
 
     <style name="FxAccountIcon">
         <item name="android:layout_marginTop">20dp</item>
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_gravity">center_horizontal</item>
-        <item name="android:src">@drawable/fxaccount_icon</item>
+        <item name="android:src">@drawable/icon</item>
     </style>
 
     <style name="FxAccountErrorItem">
         <item name="android:layout_width">fill_parent</item>
         <item name="android:layout_marginBottom">10dp</item>
         <item name="android:layout_marginTop">10dp</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:gravity">center_horizontal</item>
@@ -102,28 +105,29 @@
         <item name="android:text">Error</item>
         <item name="android:textColor">@android:color/white</item>
         <item name="android:textColorLink">@android:color/white</item>
         <item name="android:textSize">18sp</item>
         <item name="android:visibility">invisible</item>
     </style>
 
     <style name="FxAccountProgress">
-        <item name="android:layout_width">fill_parent</item>
-        <item name="android:layout_height">fill_parent</item>
-        <item name="android:background">@drawable/fxaccount_button_background</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_centerInParent">true</item>
         <item name="android:visibility">invisible</item>
     </style>
 
     <style name="FxAccountButtonLayout">
         <item name="android:orientation">vertical</item>
         <item name="android:layout_width">fill_parent</item>
         <item name="android:layout_height">wrap_content</item>
+        <item name="android:background">@drawable/fxaccount_button_background</item>
     </style>
 
     <style name="FxAccountCheckBox">
         <item name="android:layout_width">fill_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_marginBottom">10dp</item>
         <item name="android:textColor">@drawable/fxaccount_checkbox_textcolor</item>
     </style>
 
-</resources>
+</resources>
\ No newline at end of file
--- a/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
+++ b/mobile/android/base/resources/xml/fxaccount_status_prefscreen.xml
@@ -51,24 +51,24 @@
         <CheckBoxPreference
             android:key="passwords"
             android:persistent="false"
             android:title="@string/fxaccount_status_passwords" />
     </PreferenceCategory>
     <PreferenceCategory
         android:key="legal_category"
         android:title="@string/fxaccount_status_legal" >
-        <Preference android:title="@string/fxaccount_policy_linktos" >
+        <Preference android:title="@string/fxaccount_status_linktos" >
             <intent
                 android:action="android.intent.action.VIEW"
                 android:data="@string/fxaccount_link_tos"
                 android:targetClass="@string/browser_intent_class"
                 android:targetPackage="@string/browser_intent_package" />
         </Preference>
-        <Preference android:title="@string/fxaccount_policy_linkprivacy" >
+        <Preference android:title="@string/fxaccount_status_linkprivacy" >
             <intent
                 android:action="android.intent.action.VIEW"
                 android:data="@string/fxaccount_link_pn"
                 android:targetClass="@string/browser_intent_class"
                 android:targetPackage="@string/browser_intent_package" />
         </Preference>
     </PreferenceCategory>
     <PreferenceCategory
--- a/mobile/android/base/sync/SyncConstants.java.in
+++ b/mobile/android/base/sync/SyncConstants.java.in
@@ -13,19 +13,19 @@ import org.mozilla.gecko.background.comm
 public class SyncConstants {
   public static final String GLOBAL_LOG_TAG = "FxSync";
   public static final String SYNC_MAJOR_VERSION  = "1";
   public static final String SYNC_MINOR_VERSION  = "0";
   public static final String SYNC_VERSION_STRING = SYNC_MAJOR_VERSION + "." +
                                                    GlobalConstants.MOZ_APP_VERSION + "." +
                                                    SYNC_MINOR_VERSION;
 
-  public static final String SYNC_USER_AGENT = "Firefox AndroidSync " +
-                                               SYNC_VERSION_STRING + " (" +
-                                               GlobalConstants.MOZ_APP_DISPLAYNAME + ")";
+  public static final String USER_AGENT = "Firefox AndroidSync " +
+                                          SYNC_VERSION_STRING + " (" +
+                                          GlobalConstants.MOZ_APP_DISPLAYNAME + ")";
 
   public static final String ACCOUNTTYPE_SYNC = "@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@";
 
   /**
    * Bug 790931: this action is broadcast when an Android Sync Account is
    * deleted.  This allows each installed Firefox to delete any Sync Account
    * pickle file and to (try to) wipe its client record from the Sync server.
    * <p>
--- a/mobile/android/base/sync/jpake/stage/DeleteChannel.java
+++ b/mobile/android/base/sync/jpake/stage/DeleteChannel.java
@@ -4,16 +4,17 @@
 
 package org.mozilla.gecko.sync.jpake.stage;
 
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 
 import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.jpake.JPakeClient;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 import org.mozilla.gecko.sync.setup.auth.AccountAuthenticator;
 
 import ch.boye.httpclientandroidlib.HttpResponse;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
 import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
@@ -31,16 +32,20 @@ public class DeleteChannel {
     try {
       httpResource = new BaseResource(jClient.channelUrl);
     } catch (URISyntaxException e) {
       Logger.debug(LOG_TAG, "Encountered URISyntax exception, displaying abort anyway.");
       jClient.displayAbort(reason);
       return;
     }
     httpResource.delegate = new BaseResourceDelegate(httpResource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       @Override
       public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
         request.setHeader(new BasicHeader(KEYEXCHANGE_ID_HEADER,  jClient.clientId));
         request.setHeader(new BasicHeader(KEYEXCHANGE_CID_HEADER, jClient.channel));
       }
 
       @Override
--- a/mobile/android/base/sync/jpake/stage/GetChannelStage.java
+++ b/mobile/android/base/sync/jpake/stage/GetChannelStage.java
@@ -5,16 +5,17 @@
 package org.mozilla.gecko.sync.jpake.stage;
 
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 
 import org.json.simple.parser.JSONParser;
 import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.jpake.JPakeClient;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 import org.mozilla.gecko.sync.net.SyncResponse;
 import org.mozilla.gecko.sync.setup.Constants;
 
 import ch.boye.httpclientandroidlib.HttpResponse;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
@@ -75,16 +76,20 @@ public class GetChannelStage extends JPa
       jClient.abort(Constants.JPAKE_ERROR_CHANNEL);
       return;
     }
   }
 
   private void makeChannelRequest(final GetChannelStageDelegate callbackDelegate, String getChannelUrl, final String clientId) throws URISyntaxException {
     final BaseResource httpResource = new BaseResource(getChannelUrl);
     httpResource.delegate = new BaseResourceDelegate(httpResource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       @Override
       public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
         request.setHeader(new BasicHeader("X-KeyExchange-Id", clientId));
       }
 
       @Override
       public void handleHttpResponse(HttpResponse response) {
--- a/mobile/android/base/sync/jpake/stage/GetRequestStage.java
+++ b/mobile/android/base/sync/jpake/stage/GetRequestStage.java
@@ -6,16 +6,17 @@ package org.mozilla.gecko.sync.jpake.sta
 
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 import java.util.Timer;
 import java.util.TimerTask;
 
 import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.jpake.JPakeClient;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 import org.mozilla.gecko.sync.net.Resource;
 import org.mozilla.gecko.sync.net.SyncResponse;
 import org.mozilla.gecko.sync.setup.Constants;
 
 import ch.boye.httpclientandroidlib.Header;
@@ -96,16 +97,20 @@ public class GetRequestStage extends JPa
     Logger.debug(LOG_TAG, "Scheduling GET request.");
     getStepTimerTask = new GetStepTimerTask(httpRequest);
     timerScheduler.schedule(getStepTimerTask, jClient.jpakePollInterval);
   }
 
   private Resource createGetRequest(final GetRequestStageDelegate callbackDelegate, final JPakeClient jpakeClient) throws URISyntaxException {
     BaseResource httpResource = new BaseResource(jpakeClient.channelUrl);
     httpResource.delegate = new BaseResourceDelegate(httpResource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       @Override
       public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
         request.setHeader(new BasicHeader("X-KeyExchange-Id", jpakeClient.clientId));
         if (jpakeClient.myEtag != null) {
           request.setHeader(new BasicHeader("If-None-Match", jpakeClient.myEtag));
         }
       }
--- a/mobile/android/base/sync/jpake/stage/PutRequestStage.java
+++ b/mobile/android/base/sync/jpake/stage/PutRequestStage.java
@@ -7,20 +7,21 @@ package org.mozilla.gecko.sync.jpake.sta
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 import java.util.Timer;
 import java.util.TimerTask;
 
 import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.jpake.JPakeClient;
 import org.mozilla.gecko.sync.net.BaseResource;
+import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 import org.mozilla.gecko.sync.net.Resource;
-import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 import org.mozilla.gecko.sync.setup.Constants;
 
 import ch.boye.httpclientandroidlib.Header;
 import ch.boye.httpclientandroidlib.HttpResponse;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
 import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
 import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
 import ch.boye.httpclientandroidlib.message.BasicHeader;
@@ -87,16 +88,20 @@ public class PutRequestStage extends JPa
       return;
     }
     Logger.debug(LOG_TAG, "Outgoing message: " + jClient.jOutgoing.toJSONString());
   }
 
   private Resource createPutRequest(final PutRequestStageDelegate callbackDelegate, final JPakeClient jpakeClient) throws URISyntaxException {
     BaseResource httpResource = new BaseResource(jpakeClient.channelUrl);
     httpResource.delegate = new BaseResourceDelegate(httpResource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       @Override
       public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
         request.setHeader(new BasicHeader("X-KeyExchange-Id", jpakeClient.clientId));
         if (jpakeClient.theirEtag != null) {
           request.setHeader(new BasicHeader("If-Match", jpakeClient.theirEtag));
         } else {
           request.setHeader(new BasicHeader("If-None-Match", "*"));
--- a/mobile/android/base/sync/net/BaseResource.java
+++ b/mobile/android/base/sync/net/BaseResource.java
@@ -172,16 +172,20 @@ public class BaseResource implements Res
     addAuthCacheToContext(request, context);
 
     HttpParams params = client.getParams();
     HttpConnectionParams.setConnectionTimeout(params, delegate.connectionTimeout());
     HttpConnectionParams.setSoTimeout(params, delegate.socketTimeout());
     HttpConnectionParams.setStaleCheckingEnabled(params, false);
     HttpProtocolParams.setContentCharset(params, charset);
     HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
+    final String userAgent = delegate.getUserAgent();
+    if (userAgent != null) {
+      HttpProtocolParams.setUserAgent(params, userAgent);
+    }
     delegate.addHeaders(request, client);
   }
 
   private static Object connManagerMonitor = new Object();
   private static ClientConnectionManager connManager;
 
   // Call within a synchronized block on connManagerMonitor.
   private static ClientConnectionManager enableTLSConnectionManager() throws KeyManagementException, NoSuchAlgorithmException  {
--- a/mobile/android/base/sync/net/ResourceDelegate.java
+++ b/mobile/android/base/sync/net/ResourceDelegate.java
@@ -21,16 +21,23 @@ import ch.boye.httpclientandroidlib.impl
  * @author rnewman
  *
  */
 public interface ResourceDelegate {
   // Request augmentation.
   AuthHeaderProvider getAuthHeaderProvider();
   void addHeaders(HttpRequestBase request, DefaultHttpClient client);
 
+  /**
+   * The value of the User-Agent header to include with the request.
+   *
+   * @return User-Agent header value; null means do not set User-Agent header.
+   */
+  public String getUserAgent();
+
   // Response handling.
 
   /**
    * Override this to handle an HttpResponse.
    *
    * ResourceDelegate implementers <b>must</b> ensure that HTTP responses are
    * fully consumed to ensure that connections are returned to the pool, for
    * example by calling <code>EntityUtils.consume(response.getEntity())</code>.
--- a/mobile/android/base/sync/net/SyncStorageRequest.java
+++ b/mobile/android/base/sync/net/SyncStorageRequest.java
@@ -13,17 +13,16 @@ import java.util.HashMap;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.sync.SyncConstants;
 
 import ch.boye.httpclientandroidlib.HttpEntity;
 import ch.boye.httpclientandroidlib.HttpResponse;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
 import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
 import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
-import ch.boye.httpclientandroidlib.params.CoreProtocolPNames;
 
 public class SyncStorageRequest implements Resource {
   public static HashMap<String, String> SERVER_ERROR_MESSAGES;
   static {
     HashMap<String, String> errors = new HashMap<String, String>();
 
     // Sync protocol errors.
     errors.put("1", "Illegal method/protocol");
@@ -106,16 +105,21 @@ public class SyncStorageRequest implemen
     }
 
     @Override
     public AuthHeaderProvider getAuthHeaderProvider() {
       return request.delegate.getAuthHeaderProvider();
     }
 
     @Override
+    public String getUserAgent() {
+      return SyncConstants.USER_AGENT;
+    }
+
+    @Override
     public void handleHttpResponse(HttpResponse response) {
       Logger.debug(LOG_TAG, "SyncStorageResourceDelegate handling response: " + response.getStatusLine() + ".");
       SyncStorageRequestDelegate d = this.request.delegate;
       SyncStorageResponse res = new SyncStorageResponse(response);
       // It is the responsibility of the delegate handlers to completely consume the response.
       if (res.wasSuccessful()) {
         d.handleRequestSuccess(res);
       } else {
@@ -141,18 +145,16 @@ public class SyncStorageRequest implemen
 
     @Override
     public void handleTransportException(GeneralSecurityException e) {
       this.request.delegate.handleRequestError(e);
     }
 
     @Override
     public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
-      client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, SyncConstants.SYNC_USER_AGENT);
-
       // Clients can use their delegate interface to specify X-If-Unmodified-Since.
       String ifUnmodifiedSince = this.request.delegate.ifUnmodifiedSince();
       if (ifUnmodifiedSince != null) {
         Logger.debug(LOG_TAG, "Making request with X-If-Unmodified-Since = " + ifUnmodifiedSince);
         request.setHeader("x-if-unmodified-since", ifUnmodifiedSince);
       }
       if (request.getMethod().equalsIgnoreCase("DELETE")) {
         request.addHeader("x-confirm-delete", "1");
@@ -168,24 +170,28 @@ public class SyncStorageRequest implemen
     super();
   }
 
   // Default implementation. Override this.
   protected BaseResourceDelegate makeResourceDelegate(SyncStorageRequest request) {
     return new SyncStorageResourceDelegate(request);
   }
 
+  @Override
   public void get() {
     this.resource.get();
   }
 
+  @Override
   public void delete() {
     this.resource.delete();
   }
 
+  @Override
   public void post(HttpEntity body) {
     this.resource.post(body);
   }
 
+  @Override
   public void put(HttpEntity body) {
     this.resource.put(body);
   }
 }
--- a/mobile/android/base/sync/setup/auth/AuthenticateAccountStage.java
+++ b/mobile/android/base/sync/setup/auth/AuthenticateAccountStage.java
@@ -91,23 +91,26 @@ public class AuthenticateAccountStage im
    * @param authRequestUrl
    * @param authHeader
    * @throws URISyntaxException
    */
   // Made public for testing.
   public void authenticateAccount(final AuthenticateAccountStageDelegate callbackDelegate, final String authRequestUrl, final String authHeader) throws URISyntaxException {
     final BaseResource httpResource = new BaseResource(authRequestUrl);
     httpResource.delegate = new BaseResourceDelegate(httpResource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       @Override
       public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
         // Make reference to request, to abort if necessary.
         httpRequest = request;
         client.log.enableDebug(true);
-        request.setHeader(new BasicHeader("User-Agent", SyncConstants.SYNC_USER_AGENT));
         // Host header is not set for some reason, so do it explicitly.
         try {
           URI authServerUri = new URI(authRequestUrl);
           request.setHeader(new BasicHeader("Host", authServerUri.getHost()));
         } catch (URISyntaxException e) {
           Logger.error(LOG_TAG, "Malformed uri, will be caught elsewhere.", e);
         }
         request.setHeader(new BasicHeader("Authorization", authHeader));
--- a/mobile/android/base/sync/setup/auth/EnsureUserExistenceStage.java
+++ b/mobile/android/base/sync/setup/auth/EnsureUserExistenceStage.java
@@ -8,16 +8,17 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 
 import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 
 import ch.boye.httpclientandroidlib.HttpResponse;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
 
 public class EnsureUserExistenceStage implements AuthenticatorStage {
   private final String LOG_TAG = "EnsureUserExistence";
@@ -51,16 +52,20 @@ public class EnsureUserExistenceStage im
       }
 
     };
 
     // This is not the same as Utils.nodeWeaveURL: it's missing the trailing node/weave.
     String userRequestUrl = aa.nodeServer + "user/1.0/" + aa.username;
     final BaseResource httpResource = new BaseResource(userRequestUrl);
     httpResource.delegate = new BaseResourceDelegate(httpResource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       @Override
       public void handleHttpResponse(HttpResponse response) {
         int statusCode = response.getStatusLine().getStatusCode();
         switch(statusCode) {
         case 200:
           try {
             InputStream content = response.getEntity().getContent();
--- a/mobile/android/base/sync/setup/auth/FetchUserNodeStage.java
+++ b/mobile/android/base/sync/setup/auth/FetchUserNodeStage.java
@@ -7,16 +7,17 @@ package org.mozilla.gecko.sync.setup.aut
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 
 import org.mozilla.gecko.background.common.log.Logger;
+import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 
 import ch.boye.httpclientandroidlib.HttpResponse;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
 
 public class FetchUserNodeStage implements AuthenticatorStage {
@@ -73,16 +74,20 @@ public class FetchUserNodeStage implemen
       }
     });
   }
 
   private BaseResource makeFetchNodeRequest(final FetchNodeStageDelegate callbackDelegate, String fetchNodeUrl) throws URISyntaxException {
     // Fetch node containing user.
     final BaseResource httpResource = new BaseResource(fetchNodeUrl);
     httpResource.delegate = new BaseResourceDelegate(httpResource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       @Override
       public void handleHttpResponse(HttpResponse response) {
         int statusCode = response.getStatusLine().getStatusCode();
         switch(statusCode) {
         case 200:
           try {
             InputStream content = response.getEntity().getContent();
--- a/mobile/android/base/sync/stage/EnsureClusterURLStage.java
+++ b/mobile/android/base/sync/stage/EnsureClusterURLStage.java
@@ -10,16 +10,17 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.security.GeneralSecurityException;
 
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.sync.NodeAuthenticationException;
 import org.mozilla.gecko.sync.NullClusterURLException;
+import org.mozilla.gecko.sync.SyncConstants;
 import org.mozilla.gecko.sync.ThreadPool;
 import org.mozilla.gecko.sync.delegates.NodeAssignmentCallback;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.BaseResourceDelegate;
 
 import ch.boye.httpclientandroidlib.HttpEntity;
 import ch.boye.httpclientandroidlib.HttpResponse;
 import ch.boye.httpclientandroidlib.client.ClientProtocolException;
@@ -71,16 +72,20 @@ public class EnsureClusterURLStage exten
    * @throws URISyntaxException
    */
   public static void fetchClusterURL(final String nodeWeaveURL,
                                      final ClusterURLFetchDelegate delegate) throws URISyntaxException {
     Logger.info(LOG_TAG, "In fetchClusterURL: node/weave is " + nodeWeaveURL);
 
     BaseResource resource = new BaseResource(nodeWeaveURL);
     resource.delegate = new BaseResourceDelegate(resource) {
+      @Override
+      public String getUserAgent() {
+        return SyncConstants.USER_AGENT;
+      }
 
       /**
        * Handle the response for GET https://server/pathname/version/username/node/weave.
        *
        * Returns the Sync Node that the client is located on.
        * Storage operations should be directed to that node.
        *
        * Return value: the node URL, an unadorned (not JSON) string.
@@ -174,16 +179,17 @@ public class EnsureClusterURLStage exten
       public void handleTransportException(GeneralSecurityException e) {
         delegate.handleError(e);
       }
     };
 
     resource.get();
   }
 
+  @Override
   public void execute() throws NoSuchStageException {
     final URI oldClusterURL = session.config.getClusterURL();
     final boolean wantNodeAssignment = callback.wantNodeAssignment();
 
     if (!wantNodeAssignment && oldClusterURL != null) {
       Logger.info(LOG_TAG, "Cluster URL is already set and not stale. Continuing with sync.");
       session.advance();
       return;
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -118,10 +118,12 @@ skip-if = android_version == "10"
 #[testBrowserProviderPerf]
 
 # Using UITest
 #[testAboutHomePageNavigation] # see bug 947550, bug 979038 and bug 977952
 [testAboutHomeVisibility]
 # disabled on Android 2.3; bug 979597
 skip-if = android_version == "10"
 [testInputConnection]
+# disabled on Android 2.3; bug 983440
+skip-if = android_version == "10"
 [testNativeCrypto]
 [testSessionHistory]
--- a/mobile/android/base/tokenserver/TokenServerClient.java
+++ b/mobile/android/base/tokenserver/TokenServerClient.java
@@ -252,16 +252,21 @@ public class TokenServerClient {
       this.delegate = delegate;
       this.assertion = assertion;
       this.clientState = clientState;
       this.resource = resource;
       this.conditionsAccepted = conditionsAccepted;
     }
 
     @Override
+    public String getUserAgent() {
+      return delegate.getUserAgent();
+    }
+
+    @Override
     public void handleHttpResponse(HttpResponse response) {
       // Skew.
       SkewHandler skewHandler = SkewHandler.getSkewHandlerForResource(resource);
       skewHandler.updateSkew(response, System.currentTimeMillis());
 
       // Extract backoff regardless of whether this was an error response, and
       // Retry-After for 503 responses. The error will be handled elsewhere.)
       SyncResponse res = new SyncResponse(response);
--- a/mobile/android/base/tokenserver/TokenServerClientDelegate.java
+++ b/mobile/android/base/tokenserver/TokenServerClientDelegate.java
@@ -1,16 +1,19 @@
 /* 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.tokenserver;
 
+
 public interface TokenServerClientDelegate {
   void handleSuccess(TokenServerToken token);
   void handleFailure(TokenServerException e);
   void handleError(Exception e);
 
   /**
    * Might be called multiple times, in addition to the other terminating handler methods.
    */
   void handleBackoff(int backoffSeconds);
-}
\ No newline at end of file
+
+  public String getUserAgent();
+}
--- a/mobile/android/services/strings.xml.in
+++ b/mobile/android/services/strings.xml.in
@@ -96,19 +96,19 @@
   <string name="sync_title_redirect_to_set_up_sync">&sync.title.redirect.to.set.up.sync.label;</string>
   <string name="sync_text_redirect_to_set_up_sync">&sync.text.redirect.to.set.up.sync.label;</string>
   <string name="sync_text_tab_sent">&sync.text.tab.sent.label;</string>
   <string name="sync_text_tab_not_sent">&sync.text.tab.not.sent.label;</string>
 
 <string name="browser_intent_package">@ANDROID_PACKAGE_NAME@</string>
 <string name="browser_intent_class">@ANDROID_PACKAGE_NAME@.App</string>
 
-<!-- Firefox account strings. -->
+<!-- Firefox Account strings. -->
 
-<!-- Firefox account links. -->
+<!-- Firefox Account links. -->
 <!-- https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/old-sync -->
 <string name="fxaccount_link_old_firefox">https://support.mozilla.org/1/mobile/&formatS1;/&formatS2;/&formatS3;/old-sync</string>
 <string name="fxaccount_link_create_not_allowed">http://www.consumer.ftc.gov/articles/0031-protecting-your-childs-privacy-online</string>
 <string name="fxaccount_link_tos">https://accounts.firefox.com/legal/terms</string>
 <string name="fxaccount_link_pn">https://accounts.firefox.com/legal/privacy</string>
 <string name="fxaccount_link_forgot_password">https://accounts.firefox.com/reset_password</string>
 
 <!-- Per Bug 974627, decorative images should not have non-empty
@@ -125,21 +125,21 @@
 <string name="fxaccount_policy_linktos">&fxaccount_policy_linktos;</string>
 <string name="fxaccount_policy_linkprivacy">&fxaccount_policy_linkprivacy;</string>
 
 <string name="fxaccount_getting_started_welcome_to_sync">&fxaccount_getting_started_welcome_to_sync;</string>
 <string name="fxaccount_getting_started_description">&fxaccount_getting_started_description;</string>
 <string name="fxaccount_getting_started_get_started">&fxaccount_getting_started_get_started;</string>
 <string name="fxaccount_getting_started_old_firefox">&fxaccount_getting_started_old_firefox;</string>
 
-<string name="fxaccount_create_account_header">&fxaccount_create_account_header;</string>
+<string name="fxaccount_create_account_header">&fxaccount_create_account_header2;</string>
 <string name="fxaccount_create_account_password_length_restriction">&fxaccount_create_account_password_length_restriction;</string>
 <string name="fxaccount_create_account_year_of_birth">&fxaccount_create_account_year_of_birth;</string>
 
-<string name="fxaccount_create_account_policy_text">&fxaccount_create_account_policy_text;</string>
+<string name="fxaccount_create_account_policy_text">&fxaccount_create_account_policy_text2;</string>
 <string name="fxaccount_create_account_button">&fxaccount_create_account_button;</string>
 <string name="fxaccount_create_account_choose_what_to_sync">&fxaccount_create_account_choose_what_to_sync;</string>
 <string name="fxaccount_create_account_sign_in_instead">&fxaccount_create_account_sign_in_instead;</string>
 <string name="fxaccount_create_account_1990_or_earlier">&fxaccount_create_account_1990_or_earlier;</string>
 <string name="fxaccount_create_account_unknown_error">&fxaccount_create_account_unknown_error;</string>
 
 <string name="fxaccount_account_create_not_allowed">&fxaccount_account_create_not_allowed;</string>
 <string name="fxaccount_account_create_not_allowed_you_must_meet_certain_age_requirements">&fxaccount_account_create_not_allowed_you_must_meet_certain_age_requirements;</string>
@@ -160,28 +160,30 @@
 <string name="fxaccount_account_verified_sub_header">&fxaccount_account_verified_sub_header;</string>
 <string name="fxaccount_account_verified_description">&fxaccount_account_verified_description2;</string>
 
 <string name="fxaccount_update_credentials_header">&fxaccount_update_credentials_header;</string>
 <string name="fxaccount_update_credentials_button_label">&fxaccount_update_credentials_button_label;</string>
 <string name="fxaccount_update_credentials_unknown_error">&fxaccount_update_credentials_unknown_error;</string>
 
 <string name="fxaccount_status_activity_label">&syncBrand.shortName.label;</string>
-<string name="fxaccount_status_header">&fxaccount_status_header;</string>
+<string name="fxaccount_status_header">&fxaccount_status_header2;</string>
 <string name="fxaccount_status_signed_in_as">&fxaccount_status_signed_in_as;</string>
 <string name="fxaccount_status_sync">&fxaccount_status_sync;</string>
 <string name="fxaccount_status_sync_enabled">&fxaccount_status_sync_enabled;</string>
 <string name="fxaccount_status_needs_verification">&fxaccount_status_needs_verification2;</string>
 <string name="fxaccount_status_needs_credentials">&fxaccount_status_needs_credentials;</string>
 <string name="fxaccount_status_needs_upgrade">&fxaccount_status_needs_upgrade;</string>
 <string name="fxaccount_status_bookmarks">&fxaccount_status_bookmarks;</string>
 <string name="fxaccount_status_history">&fxaccount_status_history;</string>
 <string name="fxaccount_status_passwords">&fxaccount_status_passwords;</string>
 <string name="fxaccount_status_tabs">&fxaccount_status_tabs;</string>
 <string name="fxaccount_status_legal">&fxaccount_status_legal;</string>
+<string name="fxaccount_status_linktos">&fxaccount_status_linktos;</string>
+<string name="fxaccount_status_linkprivacy">&fxaccount_status_linkprivacy;</string>
 
 <string name="fxaccount_label">&fxaccount_account_type_label;</string>
 
 <string name="fxaccount_options_title">&fxaccount_options_title;</string>
 <string name="fxaccount_options_configure_title">&fxaccount_options_configure_title;</string>
 
 <string name="fxaccount_remote_error_UPGRADE_REQUIRED">&fxaccount_remote_error_UPGRADE_REQUIRED;</string>
 <string name="fxaccount_remote_error_ATTEMPT_TO_CREATE_AN_ACCOUNT_THAT_ALREADY_EXISTS">&fxaccount_remote_error_ATTEMPT_TO_CREATE_AN_ACCOUNT_THAT_ALREADY_EXISTS_2;</string>
--- a/netwerk/base/src/nsURLParsers.cpp
+++ b/netwerk/base/src/nsURLParsers.cpp
@@ -142,22 +142,23 @@ nsBaseURLParser::ParseURL(const char *sp
         // spec = <path-with-colon>
         //
         // or
         //
         // spec = <authority-no-port-or-password>
         // spec = <path-no-slashes-or-colon>
         //
         SET_RESULT(scheme, 0, -1);
-        if (authorityLen || pathLen)
+        if (authorityLen || pathLen) {
             ParseAfterScheme(spec, specLen,
                              authorityPos, authorityLen,
                              pathPos, pathLen);
             OFFSET_RESULT(authority, offset);
             OFFSET_RESULT(path, offset);
+        }
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseURLParser::ParseAuthority(const char *auth, int32_t authLen,
                                 uint32_t *usernamePos, int32_t *usernameLen,
                                 uint32_t *passwordPos, int32_t *passwordLen,
--- a/netwerk/test/mochitests/mochitest.ini
+++ b/netwerk/test/mochitests/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 support-files =
   partial_content.sjs
   user_agent.sjs
   user_agent_update.sjs
 
 [test_partially_cached_content.html]
 [test_uri_scheme.html]
 [test_user_agent_overrides.html]
--- a/parser/htmlparser/tests/mochitest/mochitest.ini
+++ b/parser/htmlparser/tests/mochitest/mochitest.ini
@@ -120,17 +120,17 @@ support-files =
 [test_bug715112.html]
 [test_bug715739.html]
 [test_bug716579.html]
 [test_bug717180.html]
 [test_compatmode.html]
 [test_html5_tree_construction.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_html5_tree_construction_part2.html]
-skip-if = toolkit == 'android' #TIMED_OUT
+skip-if = toolkit == 'android' || e10s #TIMED_OUT
 [test_viewsource.html]
 [test_xml_mislabeled.html]
 # Disabled test due to orange on Linux
 #		test_bug568470.html
 #		file_bug568470.sjs
 #		file_bug568470-script.sjs
 # Disable test due to frequent orange on Mac
 #		test_bug534293.html
--- a/security/manager/ssl/tests/mochitest/bugs/mochitest-legacy.ini
+++ b/security/manager/ssl/tests/mochitest/bugs/mochitest-legacy.ini
@@ -1,1 +1,2 @@
 [test_generateCRMFRequest.html]
+skip-if = e10s
\ No newline at end of file
--- a/security/manager/ssl/tests/mochitest/bugs/mochitest.ini
+++ b/security/manager/ssl/tests/mochitest/bugs/mochitest.ini
@@ -1,9 +1,9 @@
 [DEFAULT]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 
 [test_bug480509.html]
 skip-if = toolkit == 'android'
 [test_bug483440.html]
 skip-if = toolkit == 'android'
 [test_bug484111.html]
 skip-if = toolkit == 'android'
--- a/security/manager/ssl/tests/mochitest/mixedcontent/mochitest.ini
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT
 support-files =
   alloworigin.sjs
   backward.html
   bug329869.js
   bug383369step2.html
   bug383369step3.html
   download.auto
   download.auto^headers^
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/mochitest.ini
+++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = buildapp == 'b2g'
+skip-if = buildapp == 'b2g' || e10s
 support-files =
   nosts_bootstrap.html
   nosts_bootstrap.html^headers^
   plain_bootstrap.html
   plain_bootstrap.html^headers^
   subdom_bootstrap.html
   subdom_bootstrap.html^headers^
   verify.sjs
new file mode 100644
--- /dev/null
+++ b/services/common/tests/unit/test_utils_sets.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+Cu.import("resource://services-common/utils.js");
+
+const EMPTY = new Set();
+const A = new Set(["a"]);
+const ABC = new Set(["a", "b", "c"]);
+const ABCD = new Set(["a", "b", "c", "d"]);
+const BC = new Set(["b", "c"]);
+const BCD = new Set(["b", "c", "d"]);
+const FGH = new Set(["f", "g", "h"]);
+const BCDFGH = new Set(["b", "c", "d", "f", "g", "h"]);
+
+let union = CommonUtils.union;
+let difference = CommonUtils.difference;
+let intersection = CommonUtils.intersection;
+let setEqual = CommonUtils.setEqual;
+
+function do_check_setEqual(a, b) {
+  do_check_true(setEqual(a, b));
+}
+
+function do_check_not_setEqual(a, b) {
+  do_check_false(setEqual(a, b));
+}
+
+function run_test() {
+  run_next_test();
+}
+
+add_test(function test_setEqual() {
+  do_check_setEqual(EMPTY, EMPTY);
+  do_check_setEqual(EMPTY, new Set());
+  do_check_setEqual(A, A);
+  do_check_setEqual(A, new Set(["a"]));
+  do_check_setEqual(new Set(["a"]), A);
+  do_check_not_setEqual(A, EMPTY);
+  do_check_not_setEqual(EMPTY, A);
+  do_check_not_setEqual(ABC, A);
+  run_next_test();
+});
+
+add_test(function test_union() {
+  do_check_setEqual(EMPTY, union(EMPTY, EMPTY));
+  do_check_setEqual(ABC, union(EMPTY, ABC));
+  do_check_setEqual(ABC, union(ABC, ABC));
+  do_check_setEqual(ABCD, union(ABC, BCD));
+  do_check_setEqual(ABCD, union(BCD, ABC));
+  do_check_setEqual(BCDFGH, union(BCD, FGH));
+  run_next_test();
+});
+
+add_test(function test_difference() {
+  do_check_setEqual(EMPTY, difference(EMPTY, EMPTY));
+  do_check_setEqual(EMPTY, difference(EMPTY, A));
+  do_check_setEqual(EMPTY, difference(A, A));
+  do_check_setEqual(ABC, difference(ABC, EMPTY));
+  do_check_setEqual(ABC, difference(ABC, FGH));
+  do_check_setEqual(A, difference(ABC, BCD));
+  run_next_test();
+});
+
+add_test(function test_intersection() {
+  do_check_setEqual(EMPTY, intersection(EMPTY, EMPTY));
+  do_check_setEqual(EMPTY, intersection(ABC, EMPTY));
+  do_check_setEqual(EMPTY, intersection(ABC, FGH));
+  do_check_setEqual(BC, intersection(ABC, BCD));
+  run_next_test();
+});
--- a/services/common/tests/unit/xpcshell.ini
+++ b/services/common/tests/unit/xpcshell.ini
@@ -12,16 +12,17 @@ firefox-appdir = browser
 [test_utils_deepCopy.js]
 [test_utils_encodeBase32.js]
 [test_utils_encodeBase64URL.js]
 [test_utils_ensureMillisecondsTimestamp.js]
 [test_utils_exceptionStr.js]
 [test_utils_json.js]
 [test_utils_makeURI.js]
 [test_utils_namedTimer.js]
+[test_utils_sets.js]
 [test_utils_stackTrace.js]
 [test_utils_utf8.js]
 [test_utils_uuid.js]
 
 [test_async_chain.js]
 [test_async_querySpinningly.js]
 [test_bagheera_server.js]
 [test_bagheera_client.js]
--- a/services/common/utils.js
+++ b/services/common/utils.js
@@ -8,16 +8,72 @@ this.EXPORTED_SYMBOLS = ["CommonUtils"];
 
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/osfile.jsm")
 Cu.import("resource://gre/modules/Log.jsm");
 
 this.CommonUtils = {
+  /*
+   * Set manipulation methods. These should be lifted into toolkit, or added to
+   * `Set` itself.
+   */
+
+  /**
+   * Return elements of `a` or `b`.
+   */
+  union: function (a, b) {
+    let out = new Set(a);
+    for (let x of b) {
+      out.add(x);
+    }
+    return out;
+  },
+
+  /**
+   * Return elements of `a` that are not present in `b`.
+   */
+  difference: function (a, b) {
+    let out = new Set(a);
+    for (let x of b) {
+      out.delete(x);
+    }
+    return out;
+  },
+
+  /**
+   * Return elements of `a` that are also in `b`.
+   */
+  intersection: function (a, b) {
+    let out = new Set();
+    for (let x of a) {
+      if (b.has(x)) {
+        out.add(x);
+      }
+    }
+    return out;
+  },
+
+  /**
+   * Return true if `a` and `b` are the same size, and
+   * every element of `a` is in `b`.
+   */
+  setEqual: function (a, b) {
+    if (a.size != b.size) {
+      return false;
+    }
+    for (let x of a) {
+      if (!b.has(x)) {
+        return false;
+      }
+    }
+    return true;
+  },
+
   exceptionStr: function exceptionStr(e) {
     if (!e) {
       return "" + e;
     }
     let message = e.message ? e.message : e;
     return message + " " + CommonUtils.stackTrace(e);
   },
 
--- a/services/healthreport/HealthReportComponents.manifest
+++ b/services/healthreport/HealthReportComponents.manifest
@@ -1,12 +1,14 @@
 # Register Firefox Health Report providers.
 category healthreport-js-provider-default AddonsProvider resource://gre/modules/HealthReport.jsm
 category healthreport-js-provider-default AppInfoProvider resource://gre/modules/HealthReport.jsm
+#ifdef MOZ_CRASHREPORTER
 category healthreport-js-provider-default CrashesProvider resource://gre/modules/HealthReport.jsm
+#endif
 category healthreport-js-provider-default HealthReportProvider resource://gre/modules/HealthReport.jsm
 category healthreport-js-provider-default PlacesProvider resource://gre/modules/HealthReport.jsm
 category healthreport-js-provider-default ProfileMetadataProvider resource://gre/modules/HealthReport.jsm
 category healthreport-js-provider-default SearchesProvider resource://gre/modules/HealthReport.jsm
 category healthreport-js-provider-default SessionsProvider resource://gre/modules/HealthReport.jsm
 category healthreport-js-provider-default SysInfoProvider resource://gre/modules/HealthReport.jsm
 
 # No Aurora or Beta providers yet; use the categories
--- a/services/healthreport/docs/dataformat.rst
+++ b/services/healthreport/docs/dataformat.rst
@@ -1019,34 +1019,53 @@ Example
       ]
     }
 
 org.mozilla.crashes.crashes
 ---------------------------
 
 This measurement contains a historical record of application crashes.
 
+Version 2
+^^^^^^^^^
+
+The switch to version 2 coincides with the introduction of the
+:ref:`crashes_crashmanager`, which provides a more robust source of
+crash data.
+
+This measurement will be reported on each day there was a crash. The
+following fields may be present in each record:
+
+mainCrash
+   The number of main process crashes that occurred on the given day.
+
+Yes, version 2 does not track submissions like version 1. It is very
+likely submissions will be re-added later.
+
+Also absent from version 2 are plugin crashes and hangs. These will be
+re-added, likely in version 3.
+
 Version 1
 ^^^^^^^^^
 
 This measurement will be reported on each day there was a crash. The
 following properties are reported:
 
 pending
     The number of crash reports that haven't been submitted.
 submitted
     The number of crash reports that were submitted.
 
 Notes
 ^^^^^
 
-Crashes are typically submitted immediately after they occur (by checking
-a box in the crash reporter, which should appear automatically after a
-crash). If the crash reporter submits the crash successfully, we get a
-submitted crash. Else, we leave it as pending.
+Main process crashes are typically submitted immediately after they
+occur (by checking a box in the crash reporter, which should appear
+automatically after a crash). If the crash reporter submits the crash
+successfully, we get a submitted crash. Else, we leave it as pending.
 
 A pending crash does not mean it will eventually be submitted.
 
 Pending crash reports can be submitted post-crash by going to
 about:crashes.
 
 If a pending crash is submitted via about:crashes, the submitted count
 increments but the pending count does not decrement. This is because FHR
@@ -1057,16 +1076,20 @@ Example
 ^^^^^^^
 
 ::
 
     "org.mozilla.crashes.crashes": {
       "_v": 1,
       "pending": 1,
       "submitted": 2
+    },
+    "org.mozilla.crashes.crashes": {
+      "_v": 2,
+      "mainCrash": 2
     }
 
 org.mozilla.healthreport.submissions
 ------------------------------------
 
 This measurement contains a history of FHR's own data submission activity.
 It was added in Firefox 23 in early May 2013.
 
--- a/services/healthreport/moz.build
+++ b/services/healthreport/moz.build
@@ -3,11 +3,11 @@
 # 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/.
 
 SPHINX_TREES['healthreport'] = 'docs'
 
 TEST_DIRS += ['tests']
 
-EXTRA_COMPONENTS += [
+EXTRA_PP_COMPONENTS += [
     'HealthReportComponents.manifest',
 ]
--- a/services/healthreport/providers.jsm
+++ b/services/healthreport/providers.jsm
@@ -14,18 +14,19 @@
 
 "use strict";
 
 #ifndef MERGED_COMPARTMENT
 
 this.EXPORTED_SYMBOLS = [
   "AddonsProvider",
   "AppInfoProvider",
-  "CrashDirectoryService",
+#ifdef MOZ_CRASHREPORTER
   "CrashesProvider",
+#endif
   "HealthReportProvider",
   "PlacesProvider",
   "SearchesProvider",
   "SessionsProvider",
   "SysInfoProvider",
 ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
@@ -987,199 +988,96 @@ AddonsProvider.prototype = Object.freeze
     }
 
     data.counts["plugin"] = pluginTags.length;
 
     return data;
   },
 });
 
+#ifdef MOZ_CRASHREPORTER
 
-function DailyCrashesMeasurement() {
+function DailyCrashesMeasurement1() {
   Metrics.Measurement.call(this);
 }
 
-DailyCrashesMeasurement.prototype = Object.freeze({
+DailyCrashesMeasurement1.prototype = Object.freeze({
   __proto__: Metrics.Measurement.prototype,
 
   name: "crashes",
   version: 1,
 
   fields: {
     pending: DAILY_COUNTER_FIELD,
     submitted: DAILY_COUNTER_FIELD,
   },
 });
 
+function DailyCrashesMeasurement2() {
+  Metrics.Measurement.call(this);
+}
+
+DailyCrashesMeasurement2.prototype = Object.freeze({
+  __proto__: Metrics.Measurement.prototype,
+
+  name: "crashes",
+  version: 2,
+
+  fields: {
+    mainCrash: DAILY_LAST_NUMERIC_FIELD,
+  },
+});
+
 this.CrashesProvider = function () {
   Metrics.Provider.call(this);
+
+  // So we can unit test.
+  this._manager = Services.crashmanager;
 };
 
 CrashesProvider.prototype = Object.freeze({
   __proto__: Metrics.Provider.prototype,
 
   name: "org.mozilla.crashes",
 
-  measurementTypes: [DailyCrashesMeasurement],
+  measurementTypes: [
+    DailyCrashesMeasurement1,
+    DailyCrashesMeasurement2,
+  ],
 
   pullOnly: true,
 
-  collectConstantData: function () {
+  collectDailyData: function () {
     return this.storage.enqueueTransaction(this._populateCrashCounts.bind(this));
   },
 
   _populateCrashCounts: function () {
-    let now = new Date();
-    let service = new CrashDirectoryService();
-
-    let pending = yield service.getPendingFiles();
-    let submitted = yield service.getSubmittedFiles();
-
-    function getAgeLimit() {
-      return 0;
-    }
-
-    let lastCheck = yield this.getState("lastCheck");
-    if (!lastCheck) {
-      lastCheck = getAgeLimit();
-    } else {
-      lastCheck = parseInt(lastCheck, 10);
-      if (Number.isNaN(lastCheck)) {
-        lastCheck = getAgeLimit();
-      }
-    }
-
-    let m = this.getMeasurement("crashes", 1);
-
-    // Aggregate counts locally to avoid excessive storage interaction.
-    let counts = {
-      pending: new Metrics.DailyValues(),
-      submitted: new Metrics.DailyValues(),
+    this._log.info("Grabbing crash counts from crash manager.");
+    let crashCounts = yield this._manager.getCrashCountsByDay();
+    let fields = {
+      "main-crash": "mainCrash",
     };
 
-    // FUTURE detect mtimes in the future and react more intelligently.
-    for (let filename in pending) {
-      let modified = pending[filename].modified;
-
-      if (modified.getTime() < lastCheck) {
-        continue;
-      }
-
-      counts.pending.appendValue(modified, 1);
-    }
-
-    for (let filename in submitted) {
-      let modified = submitted[filename].modified;
+    let m = this.getMeasurement("crashes", 2);
 
-      if (modified.getTime() < lastCheck) {
-        continue;
-      }
-
-      counts.submitted.appendValue(modified, 1);
-    }
+    for (let [day, types] of crashCounts) {
+      let date = Metrics.daysToDate(day);
+      for (let [type, count] of types) {
+        if (!(type in fields)) {
+          this._log.warn("Unknown crash type encountered: " + type);
+          continue;
+        }
 
-    for (let [date, values] in counts.pending) {
-      yield m.incrementDailyCounter("pending", date, values.length);
+        yield m.setDailyLastNumeric(fields[type], count, date);
+      }
     }
-
-    for (let [date, values] in counts.submitted) {
-      yield m.incrementDailyCounter("submitted", date, values.length);
-    }
-
-    yield this.setState("lastCheck", "" + now.getTime());
   },
 });
 
-
-/**
- * Helper for interacting with the crashes directory.
- *
- * FUTURE Extract to JSM alongside crashreporter. Use in about:crashes.
- */
-this.CrashDirectoryService = function () {
-  let base = Cc["@mozilla.org/file/directory_service;1"]
-               .getService(Ci.nsIProperties)
-               .get("UAppData", Ci.nsIFile);
-
-  let cr = base.clone();
-  cr.append("Crash Reports");
-
-  let submitted = cr.clone();
-  submitted.append("submitted");
-
-  let pending = cr.clone();
-  pending.append("pending");
-
-  this._baseDir = base.path;
-  this._submittedDir = submitted.path;
-  this._pendingDir = pending.path;
-};
-
-CrashDirectoryService.prototype = Object.freeze({
-  RE_SUBMITTED_FILENAME: /^bp-.+\.txt$/,
-  RE_PENDING_FILENAME: /^.+\.dmp$/,
-
-  getPendingFiles: function () {
-    return this._getDirectoryEntries(this._pendingDir,
-                                     this.RE_PENDING_FILENAME);
-  },
-
-  getSubmittedFiles: function () {
-    return this._getDirectoryEntries(this._submittedDir,
-                                     this.RE_SUBMITTED_FILENAME);
-  },
-
-  _getDirectoryEntries: function (path, re) {
-    let files = {};
-
-    return Task.spawn(function iterateDirectory() {
-      // If the directory doesn't exist, exit immediately. Else, re-throw
-      // any errors.
-      try {
-        yield OS.File.stat(path);
-      } catch (ex if ex instanceof OS.File.Error) {
-        if (ex.becauseNoSuchFile) {
-          throw new Task.Result({});
-        }
-
-        throw ex;
-      }
-
-      let iterator = new OS.File.DirectoryIterator(path);
-
-      try {
-        while (true) {
-          let entry;
-          try {
-            entry = yield iterator.next();
-          } catch (ex if ex == StopIteration) {
-            break;
-          }
-
-          if (!entry.name.match(re)) {
-            continue;
-          }
-
-          let info = yield OS.File.stat(entry.path);
-
-          files[entry.name] = {
-            // Last modified should be adequate, because crash files aren't
-            // modified after they're first written.
-            modified: info.lastModificationDate,
-            size: info.size,
-          };
-        }
-
-        throw new Task.Result(files);
-      } finally {
-        iterator.close();
-      }
-    });
-  },
-});
+#endif
 
 
 /**
  * Holds basic statistics about the Places database.
  */
 function PlacesMeasurement() {
   Metrics.Measurement.call(this);
 }
--- a/services/healthreport/tests/xpcshell/test_provider_crashes.js
+++ b/services/healthreport/tests/xpcshell/test_provider_crashes.js
@@ -3,154 +3,86 @@
 
 "use strict";
 
 const {utils: Cu} = Components;
 
 
 Cu.import("resource://gre/modules/Metrics.jsm");
 Cu.import("resource://gre/modules/services/healthreport/providers.jsm");
+Cu.import("resource://testing-common/AppData.jsm");
 Cu.import("resource://testing-common/services/healthreport/utils.jsm");
-Cu.import("resource://testing-common/AppData.jsm");
-
-
-const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+Cu.import("resource://testing-common/CrashManagerTest.jsm");
 
 
 function run_test() {
   run_next_test();
 }
 
-// run_test() needs to finish synchronously, so we do async init here.
-add_task(function test_init() {
+add_task(function* init() {
+  do_get_profile();
   yield makeFakeAppDir();
 });
 
-let gPending = {};
-let gSubmitted = {};
-
-add_task(function test_directory_service() {
-  let d = new CrashDirectoryService();
-
-  let entries = yield d.getPendingFiles();
-  do_check_eq(typeof(entries), "object");
-  do_check_eq(Object.keys(entries).length, 0);
-
-  entries = yield d.getSubmittedFiles();
-  do_check_eq(typeof(entries), "object");
-  do_check_eq(Object.keys(entries).length, 0);
-
-  let now = new Date();
-
-  // We lose granularity when writing to filesystem.
-  now.setUTCMilliseconds(0);
-  let dates = [];
-  for (let i = 0; i < 10; i++) {
-    dates.push(new Date(now.getTime() - i * MILLISECONDS_PER_DAY));
-  }
-
-  let pending = {};
-  let submitted = {};
-  for (let date of dates) {
-    pending[createFakeCrash(false, date)] = date;
-    submitted[createFakeCrash(true, date)] = date;
-  }
-
-  entries = yield d.getPendingFiles();
-  do_check_eq(Object.keys(entries).length, Object.keys(pending).length);
-  for (let id in pending) {
-    let filename = id + ".dmp";
-    do_check_true(filename in entries);
-    do_check_eq(entries[filename].modified.getTime(), pending[id].getTime());
-  }
-
-  entries = yield d.getSubmittedFiles();
-  do_check_eq(Object.keys(entries).length, Object.keys(submitted).length);
-  for (let id in submitted) {
-    let filename = "bp-" + id + ".txt";
-    do_check_true(filename in entries);
-    do_check_eq(entries[filename].modified.getTime(), submitted[id].getTime());
-  }
-
-  gPending = pending;
-  gSubmitted = submitted;
+add_task(function test_constructor() {
+  let provider = new CrashesProvider();
 });
 
-add_test(function test_constructor() {
-  let provider = new CrashesProvider();
-
-  run_next_test();
-});
-
-add_task(function test_init() {
+add_task(function* test_init() {
   let storage = yield Metrics.Storage("init");
   let provider = new CrashesProvider();
   yield provider.init(storage);
   yield provider.shutdown();
 
   yield storage.close();
 });
 
-add_task(function test_collect() {
+add_task(function* test_collect() {
   let storage = yield Metrics.Storage("collect");
   let provider = new CrashesProvider();
   yield provider.init(storage);
 
-  // FUTURE Don't rely on state from previous test.
-  yield provider.collectConstantData();
+  // Install custom manager so we don't interfere with other tests.
+  let manager = yield getManager();
+  provider._manager = manager;
+
+  let day1 = new Date(2014, 0, 1, 0, 0, 0);
+  let day2 = new Date(2014, 0, 3, 0, 0, 0);
 
-  let m = provider.getMeasurement("crashes", 1);
-  let values = yield m.getValues();
-  do_check_eq(values.days.size, Object.keys(gPending).length);
-  for each (let date in gPending) {
-    do_check_true(values.days.hasDay(date));
+  // FUTURE Bug 982836 CrashManager will grow public APIs for adding crashes.
+  // Switch to that here.
+  let store = yield manager._getStore();
+  store.addMainProcessCrash("id1", day1);
+  store.addMainProcessCrash("id2", day1);
+  store.addMainProcessCrash("id3", day2);
+
+  // Flush changes (this may not be needed but it doesn't hurt).
+  yield store.save();
+
+  yield provider.collectDailyData();
 
-    let value = values.days.getDay(date);
-    do_check_true(value.has("pending"));
-    do_check_true(value.has("submitted"));
-    do_check_eq(value.get("pending"), 1);
-    do_check_eq(value.get("submitted"), 1);
-  }
+  let m = provider.getMeasurement("crashes", 2);
+  let values = yield m.getValues();
+  do_check_eq(values.days.size, 2);
+  do_check_true(values.days.hasDay(day1));
+  do_check_true(values.days.hasDay(day2));
+
+  let value = values.days.getDay(day1);
+  do_check_true(value.has("mainCrash"));
+  do_check_eq(value.get("mainCrash"), 2);
 
-  let currentState = yield provider.getState("lastCheck");
-  do_check_eq(typeof(currentState), "string");
-  do_check_true(currentState.length > 0);
-  let lastState = currentState;
+  value = values.days.getDay(day2);
+  do_check_eq(value.get("mainCrash"), 1);
 
-  // If we collect again, we should get no new data.
-  yield provider.collectConstantData();
+  // Check that adding a new crash increments counter on next collect.
+  store = yield manager._getStore();
+  store.addMainProcessCrash("id4", day2);
+  yield store.save();
+
+  yield provider.collectDailyData();
   values = yield m.getValues();
-  for each (let date in gPending) {
-    let day = values.days.getDay(date);
-    do_check_eq(day.get("pending"), 1);
-    do_check_eq(day.get("submitted"), 1);
-  }
-
-  currentState = yield provider.getState("lastCheck");
-  do_check_neq(currentState, lastState);
-  do_check_true(currentState > lastState);
-
-  let now = new Date();
-  let tomorrow = new Date(now.getTime() + MILLISECONDS_PER_DAY);
-  let yesterday = new Date(now.getTime() - MILLISECONDS_PER_DAY);
-
-  createFakeCrash(false, yesterday);
-
-  // Create multiple to test that multiple are handled properly.
-  createFakeCrash(false, tomorrow);
-  createFakeCrash(false, tomorrow);
-  createFakeCrash(false, tomorrow);
-
-  yield provider.collectConstantData();
-  values = yield m.getValues();
-  do_check_eq(values.days.size, 11);
-  do_check_eq(values.days.getDay(tomorrow).get("pending"), 3);
-
-  for each (let date in gPending) {
-    let day = values.days.getDay(date);
-    do_check_eq(day.get("pending"), 1);
-    do_check_eq(day.get("submitted"), 1);
-  }
+  value = values.days.getDay(day2);
+  do_check_eq(value.get("mainCrash"), 2);
 
   yield provider.shutdown();
   yield storage.close();
 });
 
--- a/services/healthreport/tests/xpcshell/xpcshell.ini
+++ b/services/healthreport/tests/xpcshell/xpcshell.ini
@@ -3,13 +3,14 @@ head = head.js
 tail =
 
 [test_load_modules.js]
 [test_profile.js]
 [test_healthreporter.js]
 [test_provider_addons.js]
 [test_provider_appinfo.js]
 [test_provider_crashes.js]
+run-if = crashreporter
 [test_provider_places.js]
 [test_provider_searches.js]
 [test_provider_sysinfo.js]
 [test_provider_sessions.js]
 
--- a/services/sync/Makefile.in
+++ b/services/sync/Makefile.in
@@ -46,16 +46,17 @@ sync_engine_modules := \
   history.js \
   passwords.js \
   prefs.js \
   tabs.js \
   $(NULL)
 
 sync_stage_modules := \
   cluster.js \
+  declined.js \
   enginesync.js \
   $(NULL)
 
 sync_testing_modules := \
   fakeservices.js \
   rotaryengine.js \
   utils.js \
   $(NULL)
--- a/services/sync/modules/browserid_identity.js
+++ b/services/sync/modules/browserid_identity.js
@@ -157,16 +157,29 @@ this.BrowserIDManager.prototype = {
     for (let topic of OBSERVER_TOPICS) {
       Services.obs.removeObserver(this, topic);
     }
     this.resetCredentials();
     this._signedInUser = null;
     return Promise.resolve();
   },
 
+  offerSyncOptions: function () {
+    // If the user chose to "Customize sync options" when signing
+    // up with Firefox Accounts, ask them to choose what to sync.
+    const url = "chrome://browser/content/sync/customize.xul";
+    const features = "centerscreen,chrome,modal,dialog,resizable=no";
+    let win = Services.wm.getMostRecentWindow("navigator:browser");
+
+    let data = {accepted: false};
+    win.openDialog(url, "_blank", features, data);
+
+    return data;
+  },
+
   initializeWithCurrentIdentity: function(isInitialSync=false) {
     // While this function returns a promise that resolves once we've started
     // the auth process, that process is complete when
     // this.whenReadyToAuthenticate.promise resolves.
     this._log.trace("initializeWithCurrentIdentity");
 
     // Reset the world before we do anything async.
     this.whenReadyToAuthenticate = Promise.defer();
@@ -188,27 +201,22 @@ this.BrowserIDManager.prototype = {
       // The user must be verified before we can do anything at all; we kick
       // this and the rest of initialization off in the background (ie, we
       // don't return the promise)
       this._log.info("Waiting for user to be verified.");
       this._fxaService.whenVerified(accountData).then(accountData => {
         this._updateSignedInUser(accountData);
         this._log.info("Starting fetch for key bundle.");
         if (this.needsCustomization) {
-          // If the user chose to "Customize sync options" when signing
-          // up with Firefox Accounts, ask them to choose what to sync.
-          const url = "chrome://browser/content/sync/customize.xul";
-          const features = "centerscreen,chrome,modal,dialog,resizable=no";
-          let win = Services.wm.getMostRecentWindow("navigator:browser");
-
-          let data = {accepted: false};
-          win.openDialog(url, "_blank", features, data);
-
+          let data = this.offerSyncOptions();
           if (data.accepted) {
             Services.prefs.clearUserPref(PREF_SYNC_SHOW_CUSTOMIZATION);
+
+            // Mark any non-selected engines as declined.
+            Weave.Service.engineManager.declineDisabled();
           } else {
             // Log out if the user canceled the dialog.
             return this._fxaService.signOut();
           }
         }
       }).then(() => {
         return this._fetchSyncKeyBundle();
       }).then(() => {
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -440,19 +440,21 @@ Store.prototype = {
     throw "override wipe in a subclass";
   }
 };
 
 this.EngineManager = function EngineManager(service) {
   this.service = service;
 
   this._engines = {};
+
+  // This will be populated by Service on startup.
+  this._declined = new Set();
   this._log = Log.repository.getLogger("Sync.EngineManager");
-  this._log.level = Log.Level[Svc.Prefs.get(
-    "log.logger.service.engines", "Debug")];
+  this._log.level = Log.Level[Svc.Prefs.get("log.logger.service.engines", "Debug")];
 }
 EngineManager.prototype = {
   get: function (name) {
     // Return an array of engines if we have an array of names
     if (Array.isArray(name)) {
       let engines = [];
       name.forEach(function(name) {
         let engine = this.get(name);
@@ -472,20 +474,79 @@ EngineManager.prototype = {
     }
     return engine;
   },
 
   getAll: function () {
     return [engine for ([name, engine] in Iterator(this._engines))];
   },
 
+  /**
+   * N.B., does not pay attention to the declined list.
+   */
   getEnabled: function () {
     return this.getAll().filter(function(engine) engine.enabled);
   },
 
+  get enabledEngineNames() {
+    return [e.name for each (e in this.getEnabled())];
+  },
+
+  persistDeclined: function () {
+    Svc.Prefs.set("declinedEngines", [...this._declined].join(","));
+  },
+
+  /**
+   * Returns an array.
+   */
+  getDeclined: function () {
+    return [...this._declined];
+  },
+
+  setDeclined: function (engines) {
+    this._declined = new Set(engines);
+    this.persistDeclined();
+  },
+
+  isDeclined: function (engineName) {
+    return this._declined.has(engineName);
+  },
+
+  /**
+   * Accepts a Set or an array.
+   */
+  decline: function (engines) {
+    for (let e of engines) {
+      this._declined.add(e);
+    }
+    this.persistDeclined();
+  },
+
+  undecline: function (engines) {
+    for (let e of engines) {
+      this._declined.delete(e);
+    }
+    this.persistDeclined();
+  },
+
+  /**
+   * Mark any non-enabled engines as declined.
+   *
+   * This is useful after initial customization during setup.
+   */
+  declineDisabled: function () {
+    for (let e of this.getAll()) {
+      if (!e.enabled) {
+        this._log.debug("Declining disabled engine " + e.name);
+        this._declined.add(e.name);
+      }
+    }
+    this.persistDeclined();
+  },
+
   /**
    * Register an Engine to the service. Alternatively, give an array of engine
    * objects to register.
    *
    * @param engineObject
    *        Engine object used to get an instance of the engine
    * @return The engine object if anything failed
    */
@@ -633,26 +694,26 @@ SyncEngine.kRecoveryStrategy = {
   retry:  "retry",
   error:  "error"
 };
 
 SyncEngine.prototype = {
   __proto__: Engine.prototype,
   _recordObj: CryptoWrapper,
   version: 1,
-  
+
   // How many records to pull in a single sync. This is primarily to avoid very
   // long first syncs against profiles with many history records.
   downloadLimit: null,
-  
+
   // How many records to pull at one time when specifying IDs. This is to avoid
   // URI length limitations.
   guidFetchBatchSize: DEFAULT_GUID_FETCH_BATCH_SIZE,
   mobileGUIDFetchBatchSize: DEFAULT_MOBILE_GUID_FETCH_BATCH_SIZE,
-  
+
   // How many records to process in a single batch.
   applyIncomingBatchSize: DEFAULT_STORE_BATCH_SIZE,
 
   get storageURL() this.service.storageURL,
 
   get engineURL() this.storageURL + this.name,
 
   get cryptoKeysURL() this.storageURL + "crypto/keys",
@@ -858,17 +919,17 @@ SyncEngine.prototype = {
     }
 
     if (isMobile) {
       batchSize = MOBILE_BATCH_SIZE;
     }
     newitems.newer = this.lastSync;
     newitems.full  = true;
     newitems.limit = batchSize;
-    
+
     // applied    => number of items that should be applied.
     // failed     => number of items that failed in this sync.
     // newFailed  => number of items that failed for the first time in this sync.
     // reconciled => number of items that were reconciled.
     let count = {applied: 0, failed: 0, newFailed: 0, reconciled: 0};
     let handled = [];
     let applyBatch = [];
     let failed = [];
--- a/services/sync/modules/identity.js
+++ b/services/sync/modules/identity.js
@@ -548,10 +548,15 @@ IdentityManager.prototype = {
   onRESTRequestBasic: function onRESTRequestBasic(request) {
     let up = this.username + ":" + this.basicPassword;
     request.setHeader("authorization", "Basic " + btoa(up));
   },
 
   createClusterManager: function(service) {
     Cu.import("resource://services-sync/stages/cluster.js");
     return new ClusterManager(service);
-  }
+  },
+
+  offerSyncOptions: function () {
+    // Do nothing for Sync 1.1.
+    return {accepted: true};
+  },
 };
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -26,16 +26,17 @@ Cu.import("resource://services-sync/cons
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/clients.js");
 Cu.import("resource://services-sync/identity.js");
 Cu.import("resource://services-sync/policies.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/rest.js");
 Cu.import("resource://services-sync/stages/enginesync.js");
+Cu.import("resource://services-sync/stages/declined.js");
 Cu.import("resource://services-sync/status.js");
 Cu.import("resource://services-sync/userapi.js");
 Cu.import("resource://services-sync/util.js");
 
 const ENGINE_MODULES = {
   Addons: "addons.js",
   Bookmarks: "bookmarks.js",
   Form: "forms.js",
@@ -60,20 +61,16 @@ Sync11Service.prototype = {
   _locked: false,
   _loggedIn: false,
 
   infoURL: null,
   storageURL: null,
   metaURL: null,
   cryptoKeyURL: null,
 
-  get enabledEngineNames() {
-    return [e.name for each (e in this.engineManager.getEnabled())];
-  },
-
   get serverURL() Svc.Prefs.get("serverURL"),
   set serverURL(value) {
     if (!value.endsWith("/")) {
       value += "/";
     }
 
     // Only do work if it's actually changing
     if (value == this.serverURL)
@@ -425,16 +422,22 @@ Sync11Service.prototype = {
     let engines = [];
     // Applications can provide this preference (comma-separated list)
     // to specify which engines should be registered on startup.
     let pref = Svc.Prefs.get("registerEngines");
     if (pref) {
       engines = pref.split(",");
     }
 
+    let declined = [];
+    pref = Svc.Prefs.get("declinedEngines");
+    if (pref) {
+      declined = pref.split(",");
+    }
+
     this.clientsEngine = new ClientEngine(this);
 
     for (let name of engines) {
       if (!name in ENGINE_MODULES) {
         this._log.info("Do not know about engine: " + name);
         continue;
       }
 
@@ -443,22 +446,24 @@ Sync11Service.prototype = {
         Cu.import("resource://services-sync/engines/" + ENGINE_MODULES[name], ns);
 
         let engineName = name + "Engine";
         if (!(engineName in ns)) {
           this._log.warn("Could not find exported engine instance: " + engineName);
           continue;
         }
 
-        this.engineManager.register(ns[engineName], this);
+        this.engineManager.register(ns[engineName]);
       } catch (ex) {
         this._log.warn("Could not register engine " + name + ": " +
                        CommonUtils.exceptionStr(ex));
       }
     }
+
+    this.engineManager.setDeclined(declined);
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
   // nsIObserver
 
   observe: function observe(subject, topic, data) {
@@ -1057,16 +1062,17 @@ Sync11Service.prototype = {
       // ... fetch the current record from the server, and COPY THE FLAGS.
       let newMeta = this.recordManager.get(this.metaURL);
 
       if (!this.recordManager.response.success || !newMeta) {
         this._log.debug("No meta/global record on the server. Creating one.");
         newMeta = new WBORecord("meta", "global");
         newMeta.payload.syncID = this.syncID;
         newMeta.payload.storageVersion = STORAGE_VERSION;
+        newMeta.payload.declined = this.engineManager.getDeclined();
 
         newMeta.isNew = true;
 
         this.recordManager.set(this.metaURL, newMeta);
         if (!newMeta.upload(this.resource(this.metaURL)).success) {
           this._log.warn("Unable to upload new meta/global. Failing remote setup.");
           return false;
         }
@@ -1240,20 +1246,54 @@ Sync11Service.prototype = {
       let synchronizer = new EngineSynchronizer(this);
       let cb = Async.makeSpinningCallback();
       synchronizer.onComplete = cb;
 
       synchronizer.sync();
       // wait() throws if the first argument is truthy, which is exactly what
       // we want.
       let result = cb.wait();
+
+      // We successfully synchronized. Now let's update our declined engines.
+      let meta = this.recordManager.get(this.metaURL);
+      if (!meta) {
+        this._log.warn("No meta/global; can't update declined state.");
+        return;
+      }
+
+      let declinedEngines = new DeclinedEngines(this);
+      let didChange = declinedEngines.updateDeclined(meta, this.engineManager);
+      if (!didChange) {
+        this._log.info("No change to declined engines. Not reuploading meta/global.");
+        return;
+      }
+
+      this.uploadMetaGlobal(meta);
     }))();
   },
 
   /**
+   * Upload meta/global, throwing the response on failure.
+   */
+  uploadMetaGlobal: function (meta) {
+    this._log.debug("Uploading meta/global: " + JSON.stringify(meta));
+
+    // It would be good to set the X-If-Unmodified-Since header to `timestamp`
+    // for this PUT to ensure at least some level of transactionality.
+    // Unfortunately, the servers don't support it after a wipe right now
+    // (bug 693893), so we're going to defer this until bug 692700.
+    let res = this.resource(this.metaURL);
+    let response = res.put(meta);
+    if (!response.success) {
+      throw response;
+    }
+    this.recordManager.set(this.metaURL, meta);
+  },
+
+  /**
    * If we have a passphrase, rather than a 25-alphadigit sync key,
    * use the provided sync ID to bootstrap it using PBKDF2.
    *
    * Store the new 'passphrase' back into the identity manager.
    *
    * We can check this as often as we want, because once it's done the
    * check will no longer succeed. It only matters that it happens after
    * we decide to bump the server storage version.
@@ -1298,36 +1338,29 @@ Sync11Service.prototype = {
 
     // Wipe the server.
     let wipeTimestamp = this.wipeServer();
 
     // Upload a new meta/global record.
     let meta = new WBORecord("meta", "global");
     meta.payload.syncID = this.syncID;
     meta.payload.storageVersion = STORAGE_VERSION;
+    meta.payload.declined = this.engineManager.getDeclined();
     meta.isNew = true;
 
-    this._log.debug("New metadata record: " + JSON.stringify(meta.payload));
-    let res = this.resource(this.metaURL);
-    // It would be good to set the X-If-Unmodified-Since header to `timestamp`
-    // for this PUT to ensure at least some level of transactionality.
-    // Unfortunately, the servers don't support it after a wipe right now
-    // (bug 693893), so we're going to defer this until bug 692700.
-    let resp = res.put(meta);
-    if (!resp.success) {
-      // If we got into a race condition, we'll abort the sync this way, too.
-      // That's fine. We'll just wait till the next sync. The client that we're
-      // racing is probably busy uploading stuff right now anyway.
-      throw resp;
-    }
-    this.recordManager.set(this.metaURL, meta);
+    // uploadMetaGlobal throws on failure -- including race conditions.
+    // If we got into a race condition, we'll abort the sync this way, too.
+    // That's fine. We'll just wait till the next sync. The client that we're
+    // racing is probably busy uploading stuff right now anyway.
+    this.uploadMetaGlobal(meta);
 
     // Wipe everything we know about except meta because we just uploaded it
     let engines = [this.clientsEngine].concat(this.engineManager.getAll());
     let collections = [engine.name for each (engine in engines)];
+    // TODO: there's a bug here. We should be calling resetClient, no?
 
     // Generate, upload, and download new keys. Do this last so we don't wipe
     // them...
     this.generateNewSymmetricKeys();
   },
 
   /**
    * Wipe user data from the server.
--- a/services/sync/modules/stages/cluster.js
+++ b/services/sync/modules/stages/cluster.js
@@ -1,11 +1,11 @@
 /* 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/. */
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 this.EXPORTED_SYMBOLS = ["ClusterManager"];
 
 const {utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/policies.js");
new file mode 100644
--- /dev/null
+++ b/services/sync/modules/stages/declined.js
@@ -0,0 +1,76 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This file contains code for maintaining the set of declined engines,
+ * in conjunction with EngineManager.
+ */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["DeclinedEngines"];
+
+const {utils: Cu} = Components;
+
+Cu.import("resource://services-sync/constants.js");
+Cu.import("resource://gre/modules/Log.jsm");
+Cu.import("resource://services-common/utils.js&q