merge mozilla-central to b2g-inbound on a CLOSED TREE
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 24 Jan 2014 15:34:03 +0100
changeset 181156 fff3070d4541bdf7bb63dc7a745033d334e4df4e
parent 181155 833ec557c4cc0f50450cf9871c3cf0e3b4b0ac13 (current diff)
parent 181051 bfe4ed6d47cec0efbc671cf48175e3a36b012b11 (diff)
child 181157 ebf0b4902bdde5d7d6ecbe1563498205f4bc568c
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.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 on a CLOSED TREE
configure.in
mobile/android/base/resources/drawable-hdpi/copy.png
mobile/android/base/resources/drawable-hdpi/cut.png
mobile/android/base/resources/drawable-hdpi/paste.png
mobile/android/base/resources/drawable-hdpi/select_all.png
mobile/android/base/resources/drawable-mdpi/copy.png
mobile/android/base/resources/drawable-mdpi/cut.png
mobile/android/base/resources/drawable-mdpi/paste.png
mobile/android/base/resources/drawable-mdpi/select_all.png
mobile/android/base/resources/drawable-xhdpi/copy.png
mobile/android/base/resources/drawable-xhdpi/cut.png
mobile/android/base/resources/drawable-xhdpi/paste.png
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-JS build system changes are apparently requiring clobbers.
+Bug 948583, first part, apparently requires a clobber.  (Ideas for fixing this involve removing jsopcode.tbl, which is a bit too big to do while holding up this patch.)
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -773,37 +773,41 @@ PrefCache.prototype = {
 
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference])
 };
 
 this.SettingCache = function SettingCache(aName, aCallback, aOptions = {}) {
   this.value = aOptions.defaultValue;
   let runCallback = () => {
-    if (aCallback && aOptions.callbackNow) {
+    if (aCallback) {
       aCallback(aName, this.value);
       if (aOptions.callbackOnce) {
         runCallback = () => {};
       }
     }
   };
 
   let settings = Utils.win.navigator.mozSettings;
   if (!settings) {
-    runCallback();
+    if (aOptions.callbackNow) {
+      runCallback();
+    }
     return;
   }
 
 
   let lock = settings.createLock();
   let req = lock.get(aName);
 
   req.addEventListener('success', () => {
     this.value = req.result[aName] == undefined ? aOptions.defaultValue : req.result[aName];
-    runCallback();
+    if (aOptions.callbackNow) {
+      runCallback();
+    }
   });
 
   settings.addObserver(aName,
                        (evt) => {
                          this.value = evt.settingValue;
                          runCallback();
                        });
 };
--- a/browser/base/content/browser-feeds.js
+++ b/browser/base/content/browser-feeds.js
@@ -29,18 +29,22 @@ var FeedHandler = {
       // set (because it thinks it's already open).  onpopupshowing gets
       // called after the attribute is unset, and it doesn't get unset
       // if we return false.  so we unset it here; otherwise, the menu
       // refuses to work past this point.
       container.parentNode.removeAttribute("open");
       return false;
     }
 
-    while (container.firstChild)
-      container.removeChild(container.firstChild);
+    for (let i = container.childNodes.length - 1; i >= 0; --i) {
+      let node = container.childNodes[i];
+      if (isSubview && node.localName == "label")
+        continue;
+      container.removeChild(node);
+    }
 
     if (!feeds || feeds.length <= 1)
       return false;
 
     // Build the menu showing the available feed choices for viewing.
     var itemNodeType = isSubview ? "toolbarbutton" : "menuitem";
     for (let feedInfo of feeds) {
       var item = document.createElement(itemNodeType);
--- a/browser/base/content/browser-syncui.js
+++ b/browser/base/content/browser-syncui.js
@@ -278,17 +278,23 @@ let gSyncUI = {
    *          "reset" -- reset sync
    */
 
   openSetup: function SUI_openSetup(wizardType) {
     let xps = Components.classes["@mozilla.org/weave/service;1"]
                                 .getService(Components.interfaces.nsISupports)
                                 .wrappedJSObject;
     if (xps.fxAccountsEnabled) {
-      switchToTabHavingURI("about:accounts", true);
+      fxAccounts.getSignedInUser().then(userData => {
+        if (userData) {
+          this.openPrefs();
+        } else {
+          switchToTabHavingURI("about:accounts", true);
+        }
+      });
     } else {
       let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
       if (win)
         win.focus();
       else {
         window.openDialog("chrome://browser/content/sync/setup.xul",
                           "weaveSetup", "centerscreen,chrome,resizable=no",
                           wizardType);
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -118,17 +118,19 @@
                    tooltip="bhTooltip">
         <!-- bookmarks menu items -->
       </toolbaritem>
 
     </panelview>
 
     <panelview id="PanelUI-socialapi" flex="1"/>
 
-    <panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);"></panelview>
+    <panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
+      <label value="&feedsMenu.label;" class="panel-subview-header"/>
+    </panelview>
 
     <panelview id="PanelUI-helpView" flex="1">
       <label value="&helpMenu.label;" class="panel-subview-header"/>
       <vbox id="PanelUI-helpItems"/>
     </panelview>
 
     <panelview id="PanelUI-developer" flex="1">
       <label value="&webDeveloperMenu.label;" class="panel-subview-header"/>
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -79,40 +79,39 @@
         // Make sure we rebuild the popup in onpopupshowing
         this._needToBuildPopup = true;
 
         var os =
                Components.classes["@mozilla.org/observer-service;1"]
                          .getService(Components.interfaces.nsIObserverService);
         os.addObserver(this, "browser-search-engine-modified", false);
 
-        this._addedObserver = true;
+        this._initialized = true;
 
         this.searchService.init((function search_init_cb(aStatus) {
           // Bail out if the binding's been destroyed
-          if (this._destroyed)
+          if (!this._initialized)
             return;
 
           if (Components.isSuccessCode(aStatus)) {
             // Refresh the display (updating icon, etc)
             this.updateDisplay();
           } else {
             Components.utils.reportError("Cannot initialize search service, bailing out: " + aStatus);
           }
         }).bind(this));
       ]]></constructor>
 
       <destructor><![CDATA[
-        this._destroyed = true;
+        if (this._initialized) {
+          this._initialized = false;
 
-        if (this._addedObserver) {
           var os = Components.classes["@mozilla.org/observer-service;1"]
                              .getService(Components.interfaces.nsIObserverService);
           os.removeObserver(this, "browser-search-engine-modified");
-          this._addedObserver = false;
         }
 
         // Make sure to break the cycle from _textbox to us. Otherwise we leak
         // the world. But make sure it's actually pointing to us.
         if (this._textbox.mController.input == this)
           this._textbox.mController.input = null;
       ]]></destructor>
 
--- a/browser/config/mozconfigs/whitelist
+++ b/browser/config/mozconfigs/whitelist
@@ -1,30 +1,30 @@
 # 'nightly' contains things that are in nightly mozconfigs and allowed to be missing from release builds.
 # Other keys in whitelist contain things are in that branches mozconfigs and allowed to be missing from nightly builds.
 whitelist = {
     'release': {},
     'nightly': {},
     }
 
-all_platforms = ['win32', 'linux32', 'linux64', 'macosx-universal']
+all_platforms = ['win64', 'win32', 'linux32', 'linux64', 'macosx-universal']
 
 for platform in all_platforms:
     whitelist['nightly'][platform] = [
         'ac_add_options --enable-update-channel=nightly',
         'ac_add_options --enable-profiling',
         'mk_add_options CLIENT_PY_ARGS="--hg-options=\'--verbose --time\' --hgtool=../tools/buildfarm/utils/hgtool.py --skip-chatzilla --skip-comm --skip-inspector --skip-venkman --tinderbox-print"'
     ]
 
 for platform in ['linux32', 'linux64', 'macosx-universal']:
     whitelist['nightly'][platform] += [
         'mk_add_options MOZ_MAKE_FLAGS="-j4"',
     ]
 
-for platform in ['linux32', 'linux64', 'macosx-universal', 'win32']:
+for platform in ['linux32', 'linux64', 'macosx-universal', 'win32', 'win64']:
     whitelist['nightly'][platform] += ['ac_add_options --enable-signmar']
     whitelist['nightly'][platform] += ['ac_add_options --enable-js-diagnostics']
 
 whitelist['nightly']['linux32'] += [
     'CXX=$REAL_CXX',
     'CXX="ccache $REAL_CXX"',
     'CC="ccache $REAL_CC"',
     'mk_add_options PROFILE_GEN_SCRIPT=@TOPSRCDIR@/build/profile_pageloader.pl',
@@ -57,25 +57,31 @@ whitelist['nightly']['macosx-universal']
 whitelist['nightly']['win32'] += [
     '. $topsrcdir/configs/mozilla2/win32/include/choose-make-flags',
     'mk_add_options MOZ_MAKE_FLAGS=-j1',
     'if test "$IS_NIGHTLY" != ""; then',
     'ac_add_options --disable-auto-deps',
     'fi',
     'ac_add_options --enable-metro',
 ]
+whitelist['nightly']['win64'] += [
+    '. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"',
+    'ac_add_options --enable-metro',
+]
 
 for platform in all_platforms:
     whitelist['release'][platform] = [
         'ac_add_options --enable-update-channel=release',
         'ac_add_options --enable-official-branding',
         'mk_add_options MOZ_MAKE_FLAGS="-j4"',
         'export BUILDING_RELEASE=1',
     ]
 whitelist['release']['win32'] += ['mk_add_options MOZ_PGO=1']
+whitelist['release']['win64'] += ['mk_add_options MOZ_PGO=1']
+
 whitelist['release']['linux32'] += [
     'export MOZILLA_OFFICIAL=1',
     'export MOZ_TELEMETRY_REPORTING=1',
     'mk_add_options MOZ_PGO=1',
     "mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'",
 ]
 whitelist['release']['linux64'] += [
     'export MOZILLA_OFFICIAL=1',
--- a/browser/config/mozconfigs/win64/beta
+++ b/browser/config/mozconfigs/win64/beta
@@ -1,7 +1,9 @@
+. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
 . "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
 
 mk_add_options MOZ_PGO=1
 
 ac_add_options --enable-official-branding
+. $topsrcdir/build/win64/mozconfig.vs2010
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/release
+++ b/browser/config/mozconfigs/win64/release
@@ -1,13 +1,15 @@
 # This make file should be identical to the beta mozconfig, apart from the
 # safeguard below
+. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
 . "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
 
 mk_add_options MOZ_PGO=1
 
 ac_add_options --enable-official-branding
 
 # safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
 # defines.sh during the beta cycle
 export BUILDING_RELEASE=1
+. $topsrcdir/build/win64/mozconfig.vs2010
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/devtools/webconsole/hudservice.js
+++ b/browser/devtools/webconsole/hudservice.js
@@ -6,19 +6,19 @@
 
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 
 let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
 let Heritage = require("sdk/core/heritage");
 
+loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
 loader.lazyGetter(this, "Telemetry", () => require("devtools/shared/telemetry"));
 loader.lazyGetter(this, "WebConsoleFrame", () => require("devtools/webconsole/webconsole").WebConsoleFrame);
-loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
 loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
 loader.lazyImporter(this, "devtools", "resource://gre/modules/devtools/Loader.jsm");
 loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
 loader.lazyImporter(this, "DebuggerServer", "resource://gre/modules/devtools/dbg-server.jsm");
 loader.lazyImporter(this, "DebuggerClient", "resource://gre/modules/devtools/dbg-client.jsm");
 
 const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
 let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
@@ -105,17 +105,16 @@ HUD_SERVICE.prototype =
    *        The window of the browser console owner.
    * @return object
    *         A promise object for the opening of the new BrowserConsole instance.
    */
   openBrowserConsole:
   function HS_openBrowserConsole(aTarget, aIframeWindow, aChromeWindow)
   {
     let hud = new BrowserConsole(aTarget, aIframeWindow, aChromeWindow);
-    this._browserConsoleID = hud.hudId;
     this.consoles.set(hud.hudId, hud);
     return hud.init();
   },
 
   /**
    * Returns the Web Console object associated to a content window.
    *
    * @param nsIDOMWindow aContentWindow
@@ -237,16 +236,17 @@ HUD_SERVICE.prototype =
       });
 
       return deferred.promise;
     }
 
     connect().then(getTarget).then(openWindow).then((aWindow) => {
       this.openBrowserConsole(target, aWindow, aWindow)
         .then((aBrowserConsole) => {
+          this._browserConsoleID = aBrowserConsole.hudId;
           this._browserConsoleDefer.resolve(aBrowserConsole);
           this._browserConsoleDefer = null;
         })
     }, console.error);
 
     return this._browserConsoleDefer.promise;
   },
 
--- a/browser/devtools/webconsole/panel.js
+++ b/browser/devtools/webconsole/panel.js
@@ -1,17 +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/. */
 
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 
-loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
+loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
 loader.lazyGetter(this, "HUDService", () => require("devtools/webconsole/hudservice"));
 loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
 
 /**
  * A DevToolPanel that controls the Web Console.
  */
 function WebConsolePanel(iframeWindow, toolbox)
 {
--- a/browser/devtools/webconsole/test/browser_console_dead_objects.js
+++ b/browser/devtools/webconsole/test/browser_console_dead_objects.js
@@ -44,20 +44,17 @@ function test()
           "dead object found");
 
     hud.jsterm.setInputValue("foobarzTezt");
 
     for (let c of ".hello") {
       EventUtils.synthesizeKey(c, {}, hud.iframeWindow);
     }
 
-    hud.jsterm.execute(null, () => {
-      // executeSoon() is needed to get out of the execute() event loop.
-      executeSoon(onReadProperty.bind(null, msg));
-    });
+    hud.jsterm.execute(null, onReadProperty.bind(null, msg));
   }
 
   function onReadProperty(deadObjectMessage)
   {
     isnot(hud.outputNode.textContent.indexOf("can't access dead object"), -1,
           "'cannot access dead object' message found");
 
     // Click the second execute output.
@@ -67,17 +64,16 @@ function test()
           "message text check");
 
     hud.jsterm.once("variablesview-fetched", onFetched);
     EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow);
   }
 
   function onFetched()
   {
-    ok(true, "variables view fetched");
     hud.jsterm.execute("delete window.foobarzTezt; 2013-26", onCalcResult);
   }
 
   function onCalcResult()
   {
     isnot(hud.outputNode.textContent.indexOf("1987"), -1, "result message found");
 
     // executeSoon() is needed to get out of the execute() event loop.
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613642_maintain_scroll.js
@@ -90,34 +90,47 @@ function testGen() {
       // Wait for scroll to bottom.
       return;
     }
     scrollBox.onscroll = null;
     isnot(scrollBox.scrollTop, 0, "scroll location updated (moved to bottom)");
     testNext();
   };
   EventUtils.synthesizeKey("VK_END", {});
-  yield undefined;
+  yield;
 
   let oldScrollTop = scrollBox.scrollTop;
 
   content.console.log("test message 151");
 
-  scrollBox.onscroll = () => {
-    if (scrollBox.scrollTop == oldScrollTop) {
-      // Wait for scroll to change.
-      return;
-    }
-    scrollBox.onscroll = null;
-    isnot(scrollBox.scrollTop, oldScrollTop, "scroll location updated (moved to bottom again)");
-    hud = testDriver = null;
-    finishTest();
-  };
+  waitForMessages({
+    webconsole: hud,
+    messages: [{
+      text: "test message 151",
+      category: CATEGORY_WEBDEV,
+      severity: SEVERITY_LOG,
+    }],
+  }).then(() => {
+    scrollBox.onscroll = () => {
+      if (scrollBox.scrollTop == oldScrollTop) {
+        // Wait for scroll to change.
+        return;
+      }
+      scrollBox.onscroll = null;
+      isnot(scrollBox.scrollTop, oldScrollTop, "scroll location updated (moved to bottom again)");
+      testNext();
+    };
+  });
 
   yield undefined;
+
+  hud = testDriver = null;
+  finishTest();
+  
+  yield undefined;
 }
 
 function test() {
   addTab("data:text/html;charset=utf-8,Web Console test for bug 613642: remember scroll location");
   browser.addEventListener("load", function tabLoad(aEvent) {
     browser.removeEventListener(aEvent.type, tabLoad, true);
     openConsole(null, function(aHud) {
       hud = aHud;
--- a/browser/devtools/webconsole/test/head.js
+++ b/browser/devtools/webconsole/test/head.js
@@ -1,17 +1,17 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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 WebConsoleUtils, TargetFactory, require;
 let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
 let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
-let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
+let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
 let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
 
 (() => {
   let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
   let utils = devtools.require("devtools/toolkit/webconsole/utils");
   TargetFactory = devtools.TargetFactory;
   WebConsoleUtils = utils.Utils;
   require = devtools.require;
--- a/browser/devtools/webconsole/webconsole.js
+++ b/browser/devtools/webconsole/webconsole.js
@@ -9,17 +9,17 @@
 const {Cc, Ci, Cu} = require("chrome");
 
 let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
 
 loader.lazyServiceGetter(this, "clipboardHelper",
                          "@mozilla.org/widget/clipboardhelper;1",
                          "nsIClipboardHelper");
 loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
-loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
+loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
 loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
 loader.lazyGetter(this, "AutocompletePopup",
                   () => require("devtools/shared/autocomplete-popup").AutocompletePopup);
 loader.lazyGetter(this, "ToolSidebar",
                   () => require("devtools/framework/sidebar").ToolSidebar);
 loader.lazyGetter(this, "NetworkPanel",
                   () => require("devtools/webconsole/network-panel").NetworkPanel);
 loader.lazyGetter(this, "ConsoleOutput",
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -124,16 +124,17 @@ These should match what Safari and other
 <!ENTITY shareLinkCmd.label "Share This Link">
 <!ENTITY shareLinkCmd.accesskey "s">
 <!ENTITY shareImageCmd.label "Share This Image">
 <!ENTITY shareImageCmd.accesskey "s">
 <!ENTITY shareSelectCmd.label "Share Selection">
 <!ENTITY shareSelectCmd.accesskey "s">
 <!ENTITY shareVideoCmd.label "Share This Video">
 <!ENTITY shareVideoCmd.accesskey "s">
+<!ENTITY feedsMenu.label "Subscribe">
 <!ENTITY subscribeToPageMenupopup.label "Subscribe to This Page">
 <!ENTITY subscribeToPageMenuitem.label "Subscribe to This Page…">
 <!ENTITY addCurPagesCmd.label "Bookmark All Tabs…">
 <!ENTITY showAllBookmarks2.label "Show All Bookmarks">
 <!ENTITY unsortedBookmarksCmd.label "Unsorted Bookmarks">
 <!ENTITY bookmarksToolbarChevron.tooltip "Show more bookmarks">
 
 <!ENTITY backCmd.label                "Back">
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -156,21 +156,16 @@ var BrowserUI = {
         FindHelperUI.init();
 #ifdef NIGHTLY_BUILD
         PdfJs.init();
 #endif
       } catch(ex) {
         Util.dumpLn("Exception in delay load module:", ex.message);
       }
 
-      if (WindowsPrefSync) {
-        // Pulls in Desktop controlled prefs and pushes out Metro controlled prefs
-        WindowsPrefSync.init();
-      }
-
       // check for left over crash reports and submit them if found.
       BrowserUI.startupCrashCheck();
 
       Util.dumpLn("* delay load complete.");
     }, false);
 
 #ifndef MOZ_OFFICIAL_BRANDING
     setTimeout(function() {
--- a/browser/metro/base/content/browser.js
+++ b/browser/metro/base/content/browser.js
@@ -180,18 +180,17 @@ var Browser = {
           let uri = commandURL || Browser.getHomePage();
           self.addTab(uri, true);
         }
       }
 
       // Should we restore the previous session (crash or some other event)
       let ss = Cc["@mozilla.org/browser/sessionstore;1"]
                .getService(Ci.nsISessionStore);
-      let shouldRestore = ss.shouldRestore()
-                       || (3 == Services.prefs.getIntPref("browser.startup.page"));
+      let shouldRestore = ss.shouldRestore();
       if (shouldRestore) {
         let bringFront = false;
         // First open any commandline URLs, except the homepage
         if (activationURI && activationURI != kStartURI) {
           this.addTab(activationURI, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP });
         } else if (commandURL && commandURL != kStartURI) {
           this.addTab(commandURL, true);
         } else {
--- a/browser/metro/components/SessionStore.js
+++ b/browser/metro/components/SessionStore.js
@@ -4,16 +4,17 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/WindowsPrefSync.jsm");
 
 #ifdef MOZ_CRASHREPORTER
 XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
   "@mozilla.org/xre/app-info;1", "nsICrashReporter");
 #endif
 
 XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
   "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
@@ -194,16 +195,20 @@ SessionStore.prototype = {
         observerService.addObserver(this, "browser-lastwindow-close-granted", true);
         observerService.addObserver(this, "browser:purge-session-history", true);
         observerService.addObserver(this, "quit-application-requested", true);
         observerService.addObserver(this, "quit-application-granted", true);
         observerService.addObserver(this, "quit-application", true);
         break;
       case "final-ui-startup":
         observerService.removeObserver(this, "final-ui-startup");
+        if (WindowsPrefSync) {
+          // Pulls in Desktop controlled prefs and pushes out Metro controlled prefs
+          WindowsPrefSync.init();
+        }
         this.init();
         break;
       case "domwindowopened":
         let window = aSubject;
         window.addEventListener("load", function() {
           self.onWindowOpen(window);
           window.removeEventListener("load", arguments.callee, false);
         }, false);
@@ -335,19 +340,22 @@ SessionStore.prototype = {
     this._windows[aWindow.__SSID] = { tabs: [], selected: 0, _closedTabs: [] };
 
     // Perform additional initialization when the first window is loading
     if (this._loadState == STATE_STOPPED) {
       this._loadState = STATE_RUNNING;
       this._lastSaveTime = Date.now();
 
       // Nothing to restore, notify observers things are complete
-      if (!this._shouldRestore) {
+      if (!this.shouldRestore()) {
         this._clearCache();
         Services.obs.notifyObservers(null, "sessionstore-windows-restored", "");
+
+        // If nothing is being restored, we only have our single Metro window.
+        this._orderedWindows.push(aWindow.__SSID);
       }
     }
 
     // Add tab change listeners to all already existing tabs
     let tabs = aWindow.Browser.tabs;
     for (let i = 0; i < tabs.length; i++)
       this.onTabAdd(aWindow, tabs[i].browser, true);
 
@@ -721,17 +729,17 @@ SessionStore.prototype = {
     let browser = aTab.linkedBrowser;
     if (browser.__SS_extdata && browser.__SS_extdata[aKey])
       delete browser.__SS_extdata[aKey];
     else
       throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
   },
 
   shouldRestore: function ss_shouldRestore() {
-    return this._shouldRestore;
+    return this._shouldRestore || (3 == Services.prefs.getIntPref("browser.startup.page"));
   },
 
   restoreLastSession: function ss_restoreLastSession(aBringToFront) {
     let self = this;
     function notifyObservers(aMessage) {
       self._clearCache();
       Services.obs.notifyObservers(null, "sessionstore-windows-restored", aMessage || "");
     }
--- a/build/autoconf/hooks.m4
+++ b/build/autoconf/hooks.m4
@@ -29,17 +29,17 @@ case "$host" in
     fi
     ;;
 esac
 
 if test -d "$1"; then
     (cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py dump "$_CONFIG_SHELL")
 fi
 $2
-(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py adjust)
+(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py adjust $ac_sub_configure)
 ])
 
 define([AC_OUTPUT_SUBDIRS],
 [trap '' EXIT
 for moz_config_dir in $1; do
   MOZ_SUBCONFIGURE_WRAP([$moz_config_dir],[
     _MOZ_AC_OUTPUT_SUBDIRS($moz_config_dir)
   ])
--- a/build/subconfigure.py
+++ b/build/subconfigure.py
@@ -13,16 +13,24 @@ import pickle
 
 class File(object):
     def __init__(self, path):
         self._path = path
         self._content = open(path, 'rb').read()
         stat = os.stat(path)
         self._times = (stat.st_atime, stat.st_mtime)
 
+    @property
+    def path(self):
+        return self._path
+
+    @property
+    def mtime(self):
+        return self._times[1]
+
     def update_time(self):
         '''If the file hasn't changed since the instance was created,
            restore its old modification time.'''
         if not os.path.exists(self._path):
             return
         if open(self._path, 'rb').read() == self._content:
             os.utime(self._path, self._times)
 
@@ -92,33 +100,38 @@ def dump(dump_file, shell):
             for f in (couple.split(':')[0] for couple in line.split()):
                 if os.path.isfile(f):
                     config_files.append(File(f))
 
     with open(dump_file, 'wb') as f:
         pickle.dump(config_files, f)
 
 
-def adjust(dump_file):
+def adjust(dump_file, configure):
     if not os.path.exists(dump_file):
         return
 
     config_files = []
 
     try:
         with open(dump_file, 'rb') as f:
             config_files = pickle.load(f)
     except Exception:
         pass
 
     for f in config_files:
+        # Still touch config.status if configure is newer than its original
+        # mtime.
+        if configure and os.path.basename(f.path) == 'config.status' and \
+                os.path.getmtime(configure) > f.mtime:
+            continue
         f.update_time()
 
     os.remove(dump_file)
 
 
 CONFIG_DUMP = 'config_files.pkl'
 
 if __name__ == '__main__':
     if sys.argv[1] == 'dump':
         dump(CONFIG_DUMP, sys.argv[2])
     elif sys.argv[1] == 'adjust':
-        adjust(CONFIG_DUMP)
+        adjust(CONFIG_DUMP, sys.argv[2] if len(sys.argv) > 2 else None)
--- a/configure.in
+++ b/configure.in
@@ -1153,16 +1153,20 @@ x86_64 | ia64)
 
 arm*)
     CPU_ARCH=arm
     ;;
 
 mips|mipsel)
     CPU_ARCH="mips"
     ;;
+
+aarch64*)
+    CPU_ARCH=aarch64
+    ;;
 esac
 
 if test -z "$OS_TARGET"; then
     OS_TARGET=$OS_ARCH
 fi
 OS_CONFIG="${OS_TARGET}${OS_RELEASE}"
 
 dnl Set INTEL_ARCHITECTURE if we're compiling for x86-32 or x86-64.
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -155,35 +155,16 @@ nsJSUtils::CompileFunction(JSContext* aC
     ReportPendingException(aCx);
     return NS_ERROR_FAILURE;
   }
 
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
 
-class MOZ_STACK_CLASS AutoDontReportUncaught {
-  JSContext* mContext;
-  bool mWasSet;
-
-public:
-  AutoDontReportUncaught(JSContext* aContext) : mContext(aContext) {
-    MOZ_ASSERT(aContext);
-    mWasSet = JS::ContextOptionsRef(mContext).dontReportUncaught();
-    if (!mWasSet) {
-      JS::ContextOptionsRef(mContext).setDontReportUncaught(true);
-    }
-  }
-  ~AutoDontReportUncaught() {
-    if (!mWasSet) {
-      JS::ContextOptionsRef(mContext).setDontReportUncaught(false);
-    }
-  }
-};
-
 nsresult
 nsJSUtils::EvaluateString(JSContext* aCx,
                           const nsAString& aScript,
                           JS::Handle<JSObject*> aScopeObject,
                           JS::CompileOptions& aCompileOptions,
                           EvaluateOptions& aEvaluateOptions,
                           JS::Value* aRetValue,
                           void **aOffThreadToken)
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -85,16 +85,35 @@ public:
                                  JS::Handle<JSObject*> aScopeObject,
                                  JS::CompileOptions &aCompileOptions,
                                  EvaluateOptions& aEvaluateOptions,
                                  JS::Value* aRetValue,
                                  void **aOffThreadToken = nullptr);
 
 };
 
+class MOZ_STACK_CLASS AutoDontReportUncaught {
+  JSContext* mContext;
+  bool mWasSet;
+
+public:
+  AutoDontReportUncaught(JSContext* aContext) : mContext(aContext) {
+    MOZ_ASSERT(aContext);
+    mWasSet = JS::ContextOptionsRef(mContext).dontReportUncaught();
+    if (!mWasSet) {
+      JS::ContextOptionsRef(mContext).setDontReportUncaught(true);
+    }
+  }
+  ~AutoDontReportUncaught() {
+    if (!mWasSet) {
+      JS::ContextOptionsRef(mContext).setDontReportUncaught(false);
+    }
+  }
+};
+
 
 class nsDependentJSString : public nsDependentString
 {
 public:
   /**
    * In the case of string ids, getting the string's chars is infallible, so
    * the dependent string can be constructed directly.
    */
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -146,17 +146,17 @@ CallbackObject::CallSetup::CallSetup(Cal
   // compartment that we ended up in with mAutoEntryScript above, because the
   // entry point is based off of the unwrapped callback (realCallback).
   mAc.construct(cx, mRootedCallable.ref());
 
   // And now we're ready to go.
   mCx = cx;
 
   // Make sure the JS engine doesn't report exceptions we want to re-throw
-  if (mExceptionHandling == eRethrowContentExceptions ||
+  if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
       mExceptionHandling == eRethrowExceptions) {
     mSavedJSContextOptions = JS::ContextOptionsRef(cx);
     JS::ContextOptionsRef(cx).setDontReportUncaught(true);
   }
 }
 
 bool
 CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aException)
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -605,24 +605,248 @@ Promise::Then(const Optional<nsRefPtr<An
 
 already_AddRefed<Promise>
 Promise::Catch(const Optional<nsRefPtr<AnyCallback>>& aRejectCallback)
 {
   Optional<nsRefPtr<AnyCallback>> resolveCb;
   return Then(resolveCb, aRejectCallback);
 }
 
+/**
+ * The CountdownHolder class encapsulates Promise.all countdown functions and
+ * the countdown holder parts of the Promises spec. It maintains the result
+ * array and AllResolveHandlers use SetValue() to set the array indices.
+ */
+class CountdownHolder MOZ_FINAL : public nsISupports
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CountdownHolder)
+
+  CountdownHolder(const GlobalObject& aGlobal, Promise* aPromise, uint32_t aCountdown)
+    : mPromise(aPromise), mCountdown(aCountdown)
+  {
+    MOZ_ASSERT(aCountdown != 0);
+    JSContext* cx = aGlobal.GetContext();
+    JSAutoCompartment ac(cx, aGlobal.Get());
+    mValues = JS_NewArrayObject(cx, aCountdown, nullptr);
+    mozilla::HoldJSObjects(this);
+  }
+
+  ~CountdownHolder()
+  {
+    mozilla::DropJSObjects(this);
+  }
+
+  void SetValue(uint32_t index, const JS::Handle<JS::Value> aValue)
+  {
+    MOZ_ASSERT(mCountdown > 0);
+
+    JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
+    JSAutoCompartment ac(cx, mValues);
+
+    {
+      AutoDontReportUncaught silenceReporting(cx);
+      if (!JS_DefineElement(cx, mValues, index, aValue, nullptr, nullptr, JSPROP_ENUMERATE)) {
+        MOZ_ASSERT(JS_IsExceptionPending(cx));
+        JS::Rooted<JS::Value> exn(cx);
+        JS_GetPendingException(cx, &exn);
+
+        mPromise->MaybeReject(cx, exn);
+      }
+    }
+
+    --mCountdown;
+    if (mCountdown == 0) {
+      JS::Rooted<JS::Value> result(cx, JS::ObjectValue(*mValues));
+      mPromise->MaybeResolve(cx, result);
+    }
+  }
+
+private:
+  nsRefPtr<Promise> mPromise;
+  uint32_t mCountdown;
+  JS::Heap<JSObject*> mValues;
+};
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(CountdownHolder)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(CountdownHolder)
+NS_IMPL_CYCLE_COLLECTION_CLASS(CountdownHolder)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CountdownHolder)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CountdownHolder)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mValues)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CountdownHolder)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CountdownHolder)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
+  tmp->mValues = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+/**
+ * An AllResolveHandler is the per-promise part of the Promise.all() algorithm.
+ * Every Promise in the handler is handed an instance of this as a resolution
+ * handler and it sets the relevant index in the CountdownHolder.
+ */
+class AllResolveHandler MOZ_FINAL : public PromiseNativeHandler
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(AllResolveHandler)
+
+  AllResolveHandler(CountdownHolder* aHolder, uint32_t aIndex)
+    : mCountdownHolder(aHolder), mIndex(aIndex)
+  {
+    MOZ_ASSERT(aHolder);
+  }
+
+  ~AllResolveHandler()
+  {
+  }
+
+  void
+  ResolvedCallback(JS::Handle<JS::Value> aValue)
+  {
+    mCountdownHolder->SetValue(mIndex, aValue);
+  }
+
+  void
+  RejectedCallback(JS::Handle<JS::Value> aValue)
+  {
+    // Should never be attached to Promise as a reject handler.
+    MOZ_ASSERT(false, "AllResolveHandler should never be attached to a Promise's reject handler!");
+  }
+
+private:
+  nsRefPtr<CountdownHolder> mCountdownHolder;
+  uint32_t mIndex;
+};
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(AllResolveHandler)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(AllResolveHandler)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AllResolveHandler)
+NS_INTERFACE_MAP_END_INHERITING(PromiseNativeHandler)
+
+NS_IMPL_CYCLE_COLLECTION_1(AllResolveHandler, mCountdownHolder)
+
+/* static */ already_AddRefed<Promise>
+Promise::All(const GlobalObject& aGlobal, JSContext* aCx,
+             const Sequence<JS::Value>& aIterable, ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window;
+  if (MOZ_LIKELY(NS_IsMainThread())) {
+    window = do_QueryInterface(aGlobal.GetAsSupports());
+    if (!window) {
+      aRv.Throw(NS_ERROR_UNEXPECTED);
+      return nullptr;
+    }
+  }
+
+  if (aIterable.Length() == 0) {
+    JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0, nullptr));
+    if (!empty) {
+      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return nullptr;
+    }
+    Optional<JS::Handle<JS::Value>> optValue(aCx, JS::ObjectValue(*empty));
+    return Promise::Resolve(aGlobal, aCx, optValue, aRv);
+  }
+
+  nsRefPtr<Promise> promise = new Promise(window);
+  nsRefPtr<CountdownHolder> holder =
+    new CountdownHolder(aGlobal, promise, aIterable.Length());
+
+  nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
+
+  for (uint32_t i = 0; i < aIterable.Length(); ++i) {
+    Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
+    nsRefPtr<Promise> nextPromise = Promise::Cast(aGlobal, aCx, optValue, aRv);
+
+    MOZ_ASSERT(!aRv.Failed());
+
+    nsRefPtr<PromiseNativeHandler> resolveHandler =
+      new AllResolveHandler(holder, i);
+
+    nsRefPtr<PromiseCallback> resolveCb =
+      new NativePromiseCallback(resolveHandler, Resolved);
+    // Every promise gets its own resolve callback, which will set the right
+    // index in the array to the resolution value.
+    nextPromise->AppendCallbacks(resolveCb, rejectCb);
+  }
+
+  return promise.forget();
+}
+
+/* static */ already_AddRefed<Promise>
+Promise::Cast(const GlobalObject& aGlobal, JSContext* aCx,
+              const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
+{
+  // If a Promise was passed, just return it.
+  JS::Rooted<JS::Value> value(aCx, aValue.WasPassed() ? aValue.Value() :
+                                                        JS::UndefinedValue());
+  if (value.isObject()) {
+    JS::Rooted<JSObject*> valueObj(aCx, &value.toObject());
+    Promise* nextPromise;
+    nsresult rv = UNWRAP_OBJECT(Promise, valueObj, nextPromise);
+
+    if (NS_SUCCEEDED(rv)) {
+      nsRefPtr<Promise> addRefed = nextPromise;
+      return addRefed.forget();
+    }
+  }
+
+  return Promise::Resolve(aGlobal, aCx, aValue, aRv);
+}
+
+/* static */ already_AddRefed<Promise>
+Promise::Race(const GlobalObject& aGlobal, JSContext* aCx,
+              const Sequence<JS::Value>& aIterable, ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window;
+  if (MOZ_LIKELY(NS_IsMainThread())) {
+    window = do_QueryInterface(aGlobal.GetAsSupports());
+    if (!window) {
+      aRv.Throw(NS_ERROR_UNEXPECTED);
+      return nullptr;
+    }
+  }
+
+  nsRefPtr<Promise> promise = new Promise(window);
+  nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(promise);
+  nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
+
+  for (uint32_t i = 0; i < aIterable.Length(); ++i) {
+    Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
+    nsRefPtr<Promise> nextPromise = Promise::Cast(aGlobal, aCx, optValue, aRv);
+    // According to spec, Cast can throw, but our implementation never does.
+    // Remove this when subclassing is supported.
+    MOZ_ASSERT(!aRv.Failed());
+    nextPromise->AppendCallbacks(resolveCb, rejectCb);
+  }
+
+  return promise.forget();
+}
+
 void
 Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
 {
   nsRefPtr<PromiseCallback> resolveCb =
-  new NativePromiseCallback(aRunnable, Resolved);
+    new NativePromiseCallback(aRunnable, Resolved);
 
   nsRefPtr<PromiseCallback> rejectCb =
-  new NativePromiseCallback(aRunnable, Rejected);
+    new NativePromiseCallback(aRunnable, Rejected);
 
   AppendCallbacks(resolveCb, rejectCb);
 }
 
 void
 Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
                          PromiseCallback* aRejectCallback)
 {
@@ -652,17 +876,17 @@ Promise::AppendCallbacks(PromiseCallback
   }
 }
 
 void
 Promise::RunTask()
 {
   MOZ_ASSERT(mState != Pending);
 
-  nsTArray<nsRefPtr<PromiseCallback> > callbacks;
+  nsTArray<nsRefPtr<PromiseCallback>> callbacks;
   callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
                                             : mRejectCallbacks);
   mResolveCallbacks.Clear();
   mRejectCallbacks.Clear();
 
   JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
   JSAutoRequest ar(cx);
   JS::Rooted<JS::Value> value(cx, mResult);
@@ -751,16 +975,17 @@ Promise::HandleException(JSContext* aCx)
 void
 Promise::ResolveInternal(JSContext* aCx,
                          JS::Handle<JS::Value> aValue,
                          PromiseTaskSync aAsynchronous)
 {
   mResolvePending = true;
 
   if (aValue.isObject()) {
+    AutoDontReportUncaught silenceReporting(aCx);
     JS::Rooted<JSObject*> valueObj(aCx, &aValue.toObject());
 
     // Thenables.
     JS::Rooted<JS::Value> then(aCx);
     if (!JS_GetProperty(aCx, valueObj, "then", &then)) {
       HandleException(aCx);
       return;
     }
@@ -851,15 +1076,22 @@ Promise::RunResolveTask(JS::Handle<JS::V
       MOZ_ASSERT(worker);
       nsRefPtr<WorkerPromiseResolverTask> task =
         new WorkerPromiseResolverTask(worker, this, aValue, aState);
       worker->Dispatch(task);
     }
     return;
   }
 
+  // Promise.all() or Promise.race() implementations will repeatedly call
+  // Resolve/RejectInternal rather than using the Maybe... forms. Stop SetState
+  // from asserting.
+  if (mState != Pending) {
+    return;
+  }
+
   SetResult(aValue);
   SetState(aState);
   RunTask();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -85,16 +85,30 @@ public:
   already_AddRefed<Promise>
   Then(const Optional<nsRefPtr<AnyCallback>>& aResolveCallback,
        const Optional<nsRefPtr<AnyCallback>>& aRejectCallback);
 
 
   already_AddRefed<Promise>
   Catch(const Optional<nsRefPtr<AnyCallback>>& aRejectCallback);
 
+  // FIXME(nsm): Bug 956197
+  static already_AddRefed<Promise>
+  All(const GlobalObject& aGlobal, JSContext* aCx,
+      const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
+
+  static already_AddRefed<Promise>
+  Cast(const GlobalObject& aGlobal, JSContext* aCx,
+       const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
+
+  // FIXME(nsm): Bug 956197
+  static already_AddRefed<Promise>
+  Race(const GlobalObject& aGlobal, JSContext* aCx,
+       const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
+
   void AppendNativeHandler(PromiseNativeHandler* aRunnable);
 
 private:
   enum PromiseState {
     Pending,
     Resolved,
     Rejected
   };
--- a/dom/promise/tests/mochitest.ini
+++ b/dom/promise/tests/mochitest.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
 
 [test_bug883683.html]
 [test_promise.html]
+[test_promise_utils.html]
 [test_resolve.html]
new file mode 100644
--- /dev/null
+++ b/dom/promise/tests/test_promise_utils.html
@@ -0,0 +1,325 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Test for Promise.all, Promise.cast, Promise.race</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript"><!--
+
+function promiseUtilitiesDefined() {
+  ok(Promise.all, "Promise.all must be defined when Promise is enabled.");
+  ok(Promise.cast, "Promise.cast must be defined when Promise is enabled.");
+  ok(Promise.race, "Promise.race must be defined when Promise is enabled.");
+  runTest();
+}
+
+function promiseAllEmptyArray() {
+  var p = Promise.all([]);
+  ok(p instanceof Promise, "Return value of Promise.all should be a Promise.");
+  p.then(function(values) {
+    ok(Array.isArray(values), "Resolved value should be an array.");
+    is(values.length, 0, "Resolved array length should match iterable's length.");
+    runTest();
+  }, function() {
+    ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
+    runTest();
+  });
+}
+
+function promiseAllArray() {
+  var p = Promise.all([1, new Date(), Promise.resolve("firefox")]);
+  ok(p instanceof Promise, "Return value of Promise.all should be a Promise.");
+  p.then(function(values) {
+    ok(Array.isArray(values), "Resolved value should be an array.");
+    is(values.length, 3, "Resolved array length should match iterable's length.");
+    is(values[0], 1, "Array values should match.");
+    ok(values[1] instanceof Date, "Array values should match.");
+    is(values[2], "firefox", "Array values should match.");
+    runTest();
+  }, function() {
+    ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
+    runTest();
+  });
+}
+
+function promiseAllWaitsForAllPromises() {
+  var arr = [
+    new Promise(function(resolve) {
+      setTimeout(resolve.bind(undefined, 1), 50);
+    }),
+    new Promise(function(resolve) {
+      setTimeout(resolve.bind(undefined, 2), 10);
+    }),
+    new Promise(function(resolve) {
+      setTimeout(resolve.bind(undefined, new Promise(function(resolve2) {
+        resolve2(3);
+      })), 10);
+    }),
+    new Promise(function(resolve) {
+      setTimeout(resolve.bind(undefined, 4), 20);
+    })
+  ];
+
+  var p = Promise.all(arr);
+  p.then(function(values) {
+    ok(Array.isArray(values), "Resolved value should be an array.");
+    is(values.length, 4, "Resolved array length should match iterable's length.");
+    is(values[0], 1, "Array values should match.");
+    is(values[1], 2, "Array values should match.");
+    is(values[2], 3, "Array values should match.");
+    is(values[3], 4, "Array values should match.");
+    runTest();
+  }, function() {
+    ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
+    runTest();
+  });
+}
+
+function promiseAllRejectFails() {
+  var arr = [
+    new Promise(function(resolve) {
+      setTimeout(resolve.bind(undefined, 1), 50);
+    }),
+    new Promise(function(resolve, reject) {
+      setTimeout(reject.bind(undefined, 2), 10);
+    }),
+    new Promise(function(resolve) {
+      setTimeout(resolve.bind(undefined, 3), 10);
+    }),
+    new Promise(function(resolve) {
+      setTimeout(resolve.bind(undefined, 4), 20);
+    })
+  ];
+
+  var p = Promise.all(arr);
+  p.then(function(values) {
+    ok(false, "Promise.all shouldn't resolve when iterable has rejected Promises.");
+    runTest();
+  }, function(e) {
+    ok(true, "Promise.all should reject when iterable has rejected Promises.");
+    is(e, 2, "Rejection value should match.");
+    runTest();
+  });
+}
+
+function promiseAllCastError() {
+  var p = Promise.all([Promise.resolve(2), { then: function() { foo(); } }]);
+  ok(p instanceof Promise, "Should cast to a Promise.");
+  p.then(function(v) {
+    ok(false, "promiseAllCastError: should've rejected.");
+    runTest();
+  }, function(e) {
+    ok(e instanceof ReferenceError, "promiseCastThenableError");
+    runTest();
+  });
+}
+
+// Check that the resolved array is enumerable.
+function promiseAllEnumerable() {
+  var p = Promise.all([1, new Date(), Promise.resolve("firefox")]);
+  p.then(function(v) {
+    var count = 0;
+    for (key in v) {
+      ++count;
+      ok(v[key] === 1 || v[key] instanceof Date || v[key] === "firefox",
+         "Enumerated properties don't match.");
+    }
+    is(count, 3, "Resolved array from Promise.all should be enumerable");
+    runTest();
+  }, function(e) {
+    ok(false, "promiseAllEnumerable: should've resolved.");
+    runTest();
+  });
+}
+
+function promiseCastNoArg() {
+  var p = Promise.cast();
+  ok(p instanceof Promise, "Should cast to a Promise.");
+  p.then(function(v) {
+    is(v, undefined, "Resolved value should be undefined.");
+    runTest();
+  });
+}
+
+function promiseCastInteger() {
+  var p = Promise.cast(5);
+  ok(p instanceof Promise, "Should cast to a Promise.");
+  p.then(function(v) {
+    is(v, 5, "Resolved value should match original.");
+    runTest();
+  });
+}
+
+function promiseCastArray() {
+  var p = Promise.cast([1,2,3]);
+  ok(p instanceof Promise, "Should cast to a Promise.");
+  p.then(function(v) {
+    ok(Array.isArray(v), "Resolved value should be an Array");
+    is(v.length, 3, "Length should match");
+    is(v[0], 1, "Resolved value should match original");
+    is(v[1], 2, "Resolved value should match original");
+    is(v[2], 3, "Resolved value should match original");
+    runTest();
+  });
+}
+
+function promiseCastThenable() {
+  var p = Promise.cast({ then: function(resolve) { resolve(2); } });
+  ok(p instanceof Promise, "Should cast to a Promise.");
+  p.then(function(v) {
+    is(v, 2, "Should resolve to 2.");
+    runTest();
+  }, function(e) {
+    ok(false, "promiseCastThenable should've resolved");
+    runTest();
+  });
+}
+
+function promiseCastPromise() {
+  var original = Promise.resolve(true);
+  var cast = Promise.cast(original);
+
+  ok(cast instanceof Promise, "Should cast to a Promise.");
+  is(cast, original, "Should return original Promise.");
+  runTest();
+}
+
+function promiseRaceEmpty() {
+  var p = Promise.race([]);
+  ok(p instanceof Promise, "Should return a Promise.");
+  p.then(function() {
+    ok(false, "Should not resolve");
+  }, function() {
+    ok(false, "Should not reject");
+  });
+  // Per spec, An empty race never resolves or rejects.
+  setTimeout(function() {
+    ok(true);
+    runTest();
+  }, 50);
+}
+
+function promiseRaceValuesArray() {
+  var p = Promise.race([true, new Date(), 3]);
+  ok(p instanceof Promise, "Should return a Promise.");
+  p.then(function(winner) {
+    is(winner, true, "First value should win.");
+    runTest();
+  }, function(err) {
+    ok(false, "Should not fail " + err + ".");
+    runTest();
+  });
+}
+
+function promiseRacePromiseArray() {
+  function timeoutPromise(n) {
+    return new Promise(function(resolve) {
+      setTimeout(function() {
+        resolve(n);
+      }, n);
+    });
+  }
+
+  var arr = [
+    timeoutPromise(50),
+    timeoutPromise(20),
+    timeoutPromise(30),
+    timeoutPromise(100)
+  ];
+
+  var p = Promise.race(arr);
+  p.then(function(winner) {
+    is(winner, 20, "Fastest timeout should win.");
+    runTest();
+  });
+}
+
+function promiseRaceReject() {
+  var p = Promise.race([
+    Promise.reject(new Error("Fail bad!")),
+    new Promise(function(resolve) {
+      setTimeout(resolve, 0);
+    })
+  ]);
+
+  p.then(function() {
+    ok(false, "Should not resolve when winning Promise rejected.");
+    runTest();
+  }, function(e) {
+    ok(true, "Should be rejected");
+    ok(e instanceof Error, "Should reject with Error.");
+    ok(e.message == "Fail bad!", "Message should match.");
+    runTest();
+  });
+}
+
+function promiseRaceThrow() {
+  var p = Promise.race([
+    new Promise(function(resolve) {
+      nonExistent();
+    }),
+    new Promise(function(resolve) {
+      setTimeout(resolve, 0);
+    })
+  ]);
+
+  p.then(function() {
+    ok(false, "Should not resolve when winning Promise had an error.");
+    runTest();
+  }, function(e) {
+    ok(true, "Should be rejected");
+    ok(e instanceof ReferenceError, "Should reject with ReferenceError for function nonExistent().");
+    runTest();
+  });
+}
+
+var tests = [
+              promiseUtilitiesDefined,
+              promiseAllEmptyArray,
+              promiseAllArray,
+              promiseAllWaitsForAllPromises,
+              promiseAllRejectFails,
+              promiseAllCastError,
+              promiseAllEnumerable,
+
+              promiseCastNoArg,
+              promiseCastInteger,
+              promiseCastArray,
+              promiseCastThenable,
+              promiseCastPromise,
+
+              promiseRaceEmpty,
+              promiseRaceValuesArray,
+              promiseRacePromiseArray,
+              promiseRaceReject,
+              promiseRaceThrow,
+            ];
+
+function runTest() {
+  if (!tests.length) {
+    SimpleTest.finish();
+    return;
+  }
+
+  var test = tests.shift();
+  test();
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
+// -->
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/webidl/Promise.webidl
+++ b/dom/webidl/Promise.webidl
@@ -28,9 +28,18 @@ interface Promise {
   static Promise reject(optional any value);
 
   [NewObject]
   Promise then(optional AnyCallback? fulfillCallback,
                optional AnyCallback? rejectCallback);
 
   [NewObject]
   Promise catch(optional AnyCallback? rejectCallback);
+
+  [NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
+  static Promise all(sequence<any> iterable);
+
+  [NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
+  static Promise cast(optional any value);
+
+  [NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
+  static Promise race(sequence<any> iterable);
 };
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -871,18 +871,17 @@ void ReportLoadError(JSContext* aCx, con
       break;
 
     case NS_ERROR_DOM_SECURITY_ERR:
     case NS_ERROR_DOM_SYNTAX_ERR:
       Throw(aCx, aLoadResult);
       break;
 
     default:
-      JS_ReportError(aCx, "Failed to load script: %s (nsresult = 0x%x)",
-                     url.get(), aLoadResult);
+      JS_ReportError(aCx, "Failed to load script (nsresult = 0x%x)", aLoadResult);
   }
 }
 
 bool
 LoadWorkerScript(JSContext* aCx)
 {
   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
   NS_ASSERTION(worker, "This should never be null!");
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -386,17 +386,16 @@ protected:
    *
    * ReturnDrawTarget will restore the transform on the draw target. But it is
    * the callers responsibility to restore the clip. The caller should flush the
    * draw target, if necessary.
    */
   gfx::DrawTarget*
   BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds,
                                     ContextSource aSource);
-  void ReturnDrawTarget(gfx::DrawTarget* aReturned);
 
   static bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
 
 protected:
   /**
    * Return the buffer's content type.  Requires a valid buffer or
    * buffer provider.
    */
--- a/gfx/layers/basic/BasicThebesLayer.cpp
+++ b/gfx/layers/basic/BasicThebesLayer.cpp
@@ -202,17 +202,17 @@ BasicThebesLayer::Validate(LayerManager:
     PaintBuffer(ctx,
                 state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate,
                 state.mDidSelfCopy,
                 state.mClip,
                 aCallback, aCallbackData);
     MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
     Mutated();
     ctx = nullptr;
-    mContentClient->ReturnDrawTarget(target);
+    mContentClient->ReturnDrawTargetToBuffer(target);
 
     RenderTraceInvalidateEnd(this, "FFFF00");
   } else {
     // It's possible that state.mRegionToInvalidate is nonempty here,
     // if we are shrinking the valid region to nothing. So use mRegionToDraw
     // instead.
     NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
                      "No context when we have something to draw, resource exhaustion?");
--- a/gfx/layers/client/ClientThebesLayer.cpp
+++ b/gfx/layers/client/ClientThebesLayer.cpp
@@ -65,17 +65,17 @@ ClientThebesLayer::PaintThebes()
 
       nsRefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(target);
       PaintBuffer(ctx,
                   state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate,
                   state.mDidSelfCopy, state.mClip);
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
       Mutated();
       ctx = nullptr;
-      mContentClient->ReturnDrawTarget(target);
+      mContentClient->ReturnDrawTargetToBuffer(target);
     } else {
       // It's possible that state.mRegionToInvalidate is nonempty here,
       // if we are shrinking the valid region to nothing. So use mRegionToDraw
       // instead.
       NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
                        "No context when we have something to draw, resource exhaustion?");
     }
   }
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -651,17 +651,17 @@ ContentClientDoubleBuffered::UpdateDesti
   if (isClippingCheap) {
     gfxUtils::ClipToRegion(destDT, aUpdateRegion);
   }
 
   aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, CompositionOp::OP_SOURCE);
   if (isClippingCheap) {
     destDT->PopClip();
   }
-  ReturnDrawTarget(destDT);
+  ReturnDrawTargetToBuffer(destDT);
 
   if (aSource.HaveBufferOnWhite()) {
     MOZ_ASSERT(HaveBufferOnWhite());
     DrawTarget* destDT =
       BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
     if (!destDT) {
       return;
     }
@@ -670,17 +670,17 @@ ContentClientDoubleBuffered::UpdateDesti
     if (isClippingCheap) {
       gfxUtils::ClipToRegion(destDT, aUpdateRegion);
     }
 
     aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, CompositionOp::OP_SOURCE);
     if (isClippingCheap) {
       destDT->PopClip();
     }
-    ReturnDrawTarget(destDT);
+    ReturnDrawTargetToBuffer(destDT);
   }
 }
 
 DeprecatedContentClientDoubleBuffered::~DeprecatedContentClientDoubleBuffered()
 {
   if (mDeprecatedTextureClient) {
     MOZ_ASSERT(mFrontClient);
     mDeprecatedTextureClient->SetDescriptor(SurfaceDescriptor());
@@ -890,17 +890,17 @@ DeprecatedContentClientDoubleBuffered::U
   if (isClippingCheap) {
     gfxUtils::ClipToRegion(destDT, aUpdateRegion);
   }
 
   aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, CompositionOp::OP_SOURCE);
   if (isClippingCheap) {
     destDT->PopClip();
   }
-  ReturnDrawTarget(destDT);
+  ReturnDrawTargetToBuffer(destDT);
 
   if (aSource.HaveBufferOnWhite()) {
     MOZ_ASSERT(HaveBufferOnWhite());
     DrawTarget* destDT =
       BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
     if (!destDT) {
       return;
     }
@@ -909,17 +909,17 @@ DeprecatedContentClientDoubleBuffered::U
     if (isClippingCheap) {
       gfxUtils::ClipToRegion(destDT, aUpdateRegion);
     }
 
     aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, CompositionOp::OP_SOURCE);
     if (isClippingCheap) {
       destDT->PopClip();
     }
-    ReturnDrawTarget(destDT);
+    ReturnDrawTargetToBuffer(destDT);
   }
 }
 
 void
 ContentClientSingleBuffered::PrepareFrame()
 {
   if (!mFrontAndBackBufferDiffer) {
     if (mTextureClient) {
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -93,17 +93,17 @@ public:
   {}
 
 
   virtual void Clear() = 0;
   virtual RotatedContentBuffer::PaintState BeginPaintBuffer(ThebesLayer* aLayer,
                                                             uint32_t aFlags) = 0;
   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(ThebesLayer* aLayer,
                                                        const RotatedContentBuffer::PaintState& aPaintState) = 0;
-  virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) = 0;
+  virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
 
   virtual void PrepareFrame() {}
 
   // Called as part of the layers transation reply. Conveys data about our
   // buffer(s) from the compositor. If appropriate we should swap references
   // to our buffers.
   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {}
 
@@ -143,17 +143,17 @@ public:
   {
     return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
   }
   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(ThebesLayer* aLayer,
                                                        const PaintState& aPaintState) MOZ_OVERRIDE
   {
     return RotatedContentBuffer::BorrowDrawTargetForPainting(aLayer, aPaintState);
   }
-  virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
+  virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
   {
     BorrowDrawTarget::ReturnDrawTarget(aReturned);
   }
 
   void DrawTo(ThebesLayer* aLayer,
               gfx::DrawTarget* aTarget,
               float aOpacity,
               gfx::CompositionOp aOp,
@@ -213,17 +213,17 @@ public:
   {
     return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
   }
   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(ThebesLayer* aLayer,
                                                        const PaintState& aPaintState) MOZ_OVERRIDE
   {
     return RotatedContentBuffer::BorrowDrawTargetForPainting(aLayer, aPaintState);
   }
-  virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
+  virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
   {
     BorrowDrawTarget::ReturnDrawTarget(aReturned);
   }
 
   /**
    * Begin/End Paint map a gfxASurface from the texture client
    * into the buffer of RotatedBuffer. The surface is only
    * valid when the texture client is locked, so is mapped out
@@ -323,17 +323,17 @@ public:
   {
     return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
   }
   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(ThebesLayer* aLayer,
                                                        const PaintState& aPaintState) MOZ_OVERRIDE
   {
     return RotatedContentBuffer::BorrowDrawTargetForPainting(aLayer, aPaintState);
   }
-  virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
+  virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
   {
     BorrowDrawTarget::ReturnDrawTarget(aReturned);
   }
 
   /**
    * Begin/End Paint map a gfxASurface from the texture client
    * into the buffer of RotatedContentBuffer. The surface is only
    * valid when the texture client is locked, so is mapped out
@@ -558,17 +558,17 @@ public:
     mHasBuffer = false;
     mHasBufferOnWhite = false;
   }
 
   virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer,
                                       uint32_t aFlags) MOZ_OVERRIDE;
   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(ThebesLayer* aLayer,
                                                        const PaintState& aPaintState) MOZ_OVERRIDE;
-  virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
+  virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
   {
     BorrowDrawTarget::ReturnDrawTarget(aReturned);
   }
 
   virtual void Updated(const nsIntRegion& aRegionToDraw,
                        const nsIntRegion& aVisibleRegion,
                        bool aDidSelfCopy);
 
--- a/gfx/layers/composite/APZCTreeManager.cpp
+++ b/gfx/layers/composite/APZCTreeManager.cpp
@@ -23,17 +23,17 @@
 #include <algorithm>                    // for std::stable_sort
 
 #define APZC_LOG(...)
 // #define APZC_LOG(...) printf_stderr("APZC: " __VA_ARGS__)
 
 namespace mozilla {
 namespace layers {
 
-float APZCTreeManager::sDPI = 72.0;
+float APZCTreeManager::sDPI = 160.0;
 
 APZCTreeManager::APZCTreeManager()
     : mTreeLock("APZCTreeLock"),
       mTouchCount(0)
 {
   MOZ_ASSERT(NS_IsMainThread());
   AsyncPanZoomController::InitializeGlobalState();
 }
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -135,17 +135,17 @@ typedef mozilla::layers::AllowedTouchBeh
 static bool gTouchActionPropertyEnabled = false;
 
 /**
  * Constant describing the tolerance in distance we use, multiplied by the
  * device DPI, before we start panning the screen. This is to prevent us from
  * accidentally processing taps as touch moves, and from very short/accidental
  * touches moving the screen.
  */
-static float gTouchStartTolerance = 1.0f/2.0f;
+static float gTouchStartTolerance = 1.0f/4.5f;
 
 /**
  * Default touch behavior (is used when not touch behavior is set).
  */
 static const uint32_t DefaultTouchBehavior = AllowedTouchBehavior::VERTICAL_PAN |
                                              AllowedTouchBehavior::HORIZONTAL_PAN |
                                              AllowedTouchBehavior::ZOOM;
 
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -569,17 +569,17 @@ struct JSClass {
 // member initial value.  The "original ... value" verbiage is there because
 // in ECMA-262, global properties naming class objects are read/write and
 // deleteable, for the most part.
 //
 // Implementing this efficiently requires that global objects have classes
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
-#define JSCLASS_GLOBAL_SLOT_COUNT      (3 + JSProto_LIMIT * 3 + 29)
+#define JSCLASS_GLOBAL_SLOT_COUNT      (3 + JSProto_LIMIT * 3 + 30)
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                                    \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
 
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -551,20 +551,18 @@ static bool
 obj_watch(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
-#if 0 /* pending addressing Firebug's use of this method */
     if (!GlobalObject::warnOnceAboutWatch(cx, obj))
         return false;
-#endif
 
     if (args.length() <= 1) {
         js_ReportMissingArg(cx, args.calleev(), 1);
         return false;
     }
 
     RootedObject callable(cx, ValueToCallable(cx, args[1], args.length() - 2));
     if (!callable)
@@ -590,20 +588,18 @@ static bool
 obj_unwatch(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
-#if 0 /* pending addressing Firebug's use of this method */
     if (!GlobalObject::warnOnceAboutWatch(cx, obj))
         return false;
-#endif
 
     RootedId id(cx);
     if (args.length() != 0) {
         if (!ValueToId<CanGC>(cx, args[0], &id))
             return false;
     } else {
         id = JSID_VOID;
     }
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -965,16 +965,21 @@ x86_64 | ia64)
 
 arm*)
     CPU_ARCH=arm
     ;;
 
 mips|mipsel)
     CPU_ARCH="mips"
     ;;
+
+aarch64*)
+    CPU_ARCH=aarch64
+    ;;
+
 esac
 
 if test -z "$OS_TARGET"; then
     OS_TARGET=$OS_ARCH
 fi
 OS_CONFIG="${OS_TARGET}${OS_RELEASE}"
 
 dnl Set INTEL_ARCHITECTURE if we're compiling for x86-32 or x86-64.
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5913,16 +5913,26 @@ EmitObject(ExclusiveContext *cx, Bytecod
     if (bce->script->compileAndGo()) {
         gc::AllocKind kind = GuessObjectGCKind(pn->pn_count);
         obj = NewBuiltinClassInstance(cx, &JSObject::class_, kind);
         if (!obj)
             return false;
     }
 
     for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+        /* Handle __proto__ specially because it's not binary. */
+        if (pn2->isKind(PNK_MUTATEPROTO)) {
+            if (!EmitTree(cx, bce, pn2->pn_kid))
+                return false;
+            obj = nullptr;
+            if (!Emit1(cx, bce, JSOP_MUTATEPROTO))
+                return false;
+            continue;
+        }
+
         /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
         ParseNode *pn3 = pn2->pn_left;
         bool isIndex = false;
         if (pn3->isKind(PNK_NUMBER)) {
             if (!EmitNumberOp(cx, pn3->pn_dval, bce))
                 return false;
             isIndex = true;
         } else {
@@ -5961,22 +5971,19 @@ EmitObject(ExclusiveContext *cx, Bytecod
             if (Emit1(cx, bce, op) < 0)
                 return false;
         } else {
             JS_ASSERT(pn3->isKind(PNK_NAME) || pn3->isKind(PNK_STRING));
             jsatomid index;
             if (!bce->makeAtomIndex(pn3->pn_atom, &index))
                 return false;
 
-            /*
-             * Disable NEWOBJECT on initializers that set __proto__, which has
-             * a non-standard setter on objects.
-             */
-            if (pn3->pn_atom == cx->names().proto)
-                obj = nullptr;
+            MOZ_ASSERT((op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER) ||
+                        pn3->pn_atom != cx->names().proto,
+                       "__proto__ shouldn't have been generated as an initprop");
 
             if (obj) {
                 JS_ASSERT(!obj->inDictionaryMode());
                 Rooted<jsid> id(cx, AtomToId(pn3->pn_atom));
                 RootedValue undefinedValue(cx, UndefinedValue());
                 if (!DefineNativeProperty(cx, obj, id, undefinedValue, nullptr,
                                           nullptr, JSPROP_ENUMERATE, 0, 0))
                 {
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -230,16 +230,24 @@ class FullParseHandler
     ParseNode *newObjectLiteral(uint32_t begin) {
         ParseNode *literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
         // Later in this stack: remove dependency on this opcode.
         if (literal)
             literal->setOp(JSOP_NEWINIT);
         return literal;
     }
 
+    bool addPrototypeMutation(ParseNode *literal, uint32_t begin, ParseNode *expr) {
+        ParseNode *mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr);
+        if (!mutation)
+            return false;
+        literal->append(mutation);
+        return true;
+    }
+
     bool addPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *expr) {
         ParseNode *propdef = newBinary(PNK_COLON, name, expr, JSOP_INITPROP);
         if (!propdef)
             return false;
         literal->append(propdef);
         return true;
     }
 
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -134,16 +134,17 @@ class UpvarCookie
     F(EXPORT_SPEC) \
     F(EXPORT_BATCH_SPEC) \
     F(SEQ) \
     F(FORIN) \
     F(FOROF) \
     F(FORHEAD) \
     F(ARGSBODY) \
     F(SPREAD) \
+    F(MUTATEPROTO) \
     \
     /* Unary operators. */ \
     F(TYPEOF) \
     F(VOID) \
     F(NOT) \
     F(BITNOT) \
     \
     /* \
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6802,16 +6802,17 @@ Parser<ParseHandler>::objectLiteral()
     RootedAtom atom(context);
     for (;;) {
         TokenKind ltok = tokenStream.getToken(TokenStream::KeywordIsName);
         if (ltok == TOK_RC)
             break;
 
         JSOp op = JSOP_INITPROP;
         Node propname;
+        uint32_t begin;
         switch (ltok) {
           case TOK_NUMBER:
             atom = DoubleToAtom(context, tokenStream.currentToken().number());
             if (!atom)
                 return null();
             propname = newNumber(tokenStream.currentToken());
             break;
 
@@ -6820,16 +6821,20 @@ Parser<ParseHandler>::objectLiteral()
             if (atom == context->names().get) {
                 op = JSOP_INITPROP_GETTER;
             } else if (atom == context->names().set) {
                 op = JSOP_INITPROP_SETTER;
             } else {
                 propname = handler.newIdentifier(atom, pos());
                 if (!propname)
                     return null();
+                if (atom == context->names().proto) {
+                    begin = pos().begin;
+                    op = JSOP_MUTATEPROTO;
+                }
                 break;
             }
 
             // We have parsed |get| or |set|. Look for an accessor property
             // name next.
             TokenKind tt = tokenStream.getToken(TokenStream::KeywordIsName);
             if (tt == TOK_NAME) {
                 atom = tokenStream.currentName();
@@ -6888,37 +6893,41 @@ Parser<ParseHandler>::objectLiteral()
             break;
           }
 
           default:
             report(ParseError, false, null(), JSMSG_BAD_PROP_ID);
             return null();
         }
 
-        if (op == JSOP_INITPROP) {
+        if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO) {
             TokenKind tt = tokenStream.getToken();
             Node propexpr;
             if (tt == TOK_COLON) {
                 propexpr = assignExpr();
                 if (!propexpr)
                     return null();
 
                 if (foldConstants && !FoldConstants(context, &propexpr, this))
                     return null();
 
                 /*
                  * Treat initializers which mutate __proto__ as non-constant,
                  * so that we can later assume singleton objects delegate to
                  * the default Object.prototype.
                  */
-                if (!handler.isConstant(propexpr) || atom == context->names().proto)
+                if (!handler.isConstant(propexpr) || op == JSOP_MUTATEPROTO)
                     handler.setListFlag(literal, PNX_NONCONST);
 
-                if (!handler.addPropertyDefinition(literal, propname, propexpr))
+                if (op == JSOP_MUTATEPROTO
+                    ? !handler.addPrototypeMutation(literal, begin, propexpr)
+                    : !handler.addPropertyDefinition(literal, propname, propexpr))
+                {
                     return null();
+                }
             }
 #if JS_HAS_DESTRUCTURING_SHORTHAND
             else if (ltok == TOK_NAME && (tt == TOK_COMMA || tt == TOK_RC)) {
                 /*
                  * Support, e.g., |var {x, y} = o| as destructuring shorthand
                  * for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
                  */
                 if (!abortIfSyntaxParser())
@@ -6954,17 +6963,17 @@ Parser<ParseHandler>::objectLiteral()
 
         /*
          * Check for duplicate property names.  Duplicate data properties
          * only conflict in strict mode.  Duplicate getter or duplicate
          * setter halves always conflict.  A data property conflicts with
          * any part of an accessor property.
          */
         AssignmentType assignType;
-        if (op == JSOP_INITPROP)
+        if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO)
             assignType = VALUE;
         else if (op == JSOP_INITPROP_GETTER)
             assignType = GET;
         else if (op == JSOP_INITPROP_SETTER)
             assignType = SET;
         else
             MOZ_ASSUME_UNREACHABLE("bad opcode in object initializer");
 
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -108,16 +108,17 @@ class SyntaxParseHandler
     // Expressions
 
     Node newArrayLiteral(uint32_t begin, unsigned blockid) { return NodeGeneric; }
     bool addElision(Node literal, const TokenPos &pos) { return true; }
     bool addSpreadElement(Node literal, uint32_t begin, Node inner) { return true; }
     bool addArrayElement(Node literal, Node element) { return true; }
 
     Node newObjectLiteral(uint32_t begin) { return NodeGeneric; }
+    bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
     bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
     bool addShorthandPropertyDefinition(Node literal, Node name) { return true; }
     bool addAccessorPropertyDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
 
     // Statements
 
     Node newStatementList(unsigned blockid, const TokenPos &pos) { return NodeGeneric; }
     void addStatementToList(Node list, Node stmt, ParseContext<SyntaxParseHandler> *pc) {}
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1671,16 +1671,40 @@ BaselineCompiler::emit_JSOP_INITELEM()
     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
         return false;
 
     // Pop the rhs, so that the object is on the top of the stack.
     frame.pop();
     return true;
 }
 
+typedef bool (*MutateProtoFn)(JSContext *cx, HandleObject obj, HandleValue newProto);
+static const VMFunction MutateProtoInfo = FunctionInfo<MutateProtoFn>(MutatePrototype);
+
+bool
+BaselineCompiler::emit_JSOP_MUTATEPROTO()
+{
+    // Keep values on the stack for the decompiler.
+    frame.syncStack(0);
+
+    masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
+    masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
+
+    prepareVMCall();
+
+    pushArg(R1);
+    pushArg(R0.scratchReg());
+
+    if (!callVM(MutateProtoInfo))
+        return false;
+
+    frame.pop();
+    return true;
+}
+
 bool
 BaselineCompiler::emit_JSOP_INITPROP()
 {
     // Keep lhs in R0, rhs in R1.
     frame.popRegsAndSync(2);
 
     // Push the object to store the result of the IC.
     frame.push(R0);
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -85,16 +85,17 @@ namespace jit {
     _(JSOP_NEG)                \
     _(JSOP_NEWARRAY)           \
     _(JSOP_INITELEM_ARRAY)     \
     _(JSOP_NEWOBJECT)          \
     _(JSOP_NEWINIT)            \
     _(JSOP_INITELEM)           \
     _(JSOP_INITELEM_GETTER)    \
     _(JSOP_INITELEM_SETTER)    \
+    _(JSOP_MUTATEPROTO)        \
     _(JSOP_INITPROP)           \
     _(JSOP_INITPROP_GETTER)    \
     _(JSOP_INITPROP_SETTER)    \
     _(JSOP_ENDINIT)            \
     _(JSOP_GETELEM)            \
     _(JSOP_SETELEM)            \
     _(JSOP_CALLELEM)           \
     _(JSOP_DELELEM)            \
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3702,16 +3702,31 @@ CodeGenerator::visitInitElemGetterSetter
     pushArg(value);
     pushArg(ToValue(lir, LInitElemGetterSetter::IdIndex));
     pushArg(obj);
     pushArg(ImmPtr(lir->mir()->resumePoint()->pc()));
 
     return callVM(InitElemGetterSetterInfo, lir);
 }
 
+typedef bool(*MutatePrototypeFn)(JSContext *cx, HandleObject obj, HandleValue value);
+static const VMFunction MutatePrototypeInfo =
+    FunctionInfo<MutatePrototypeFn>(MutatePrototype);
+
+bool
+CodeGenerator::visitMutateProto(LMutateProto *lir)
+{
+    Register objReg = ToRegister(lir->getObject());
+
+    pushArg(ToValue(lir, LMutateProto::ValueIndex));
+    pushArg(objReg);
+
+    return callVM(MutatePrototypeInfo, lir);
+}
+
 typedef bool(*InitPropFn)(JSContext *cx, HandleObject obj,
                           HandlePropertyName name, HandleValue value);
 static const VMFunction InitPropInfo =
     FunctionInfo<InitPropFn>(InitProp);
 
 bool
 CodeGenerator::visitInitProp(LInitProp *lir)
 {
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -141,16 +141,17 @@ class CodeGenerator : public CodeGenerat
     bool visitNewCallObjectPar(LNewCallObjectPar *lir);
     bool visitNewStringObject(LNewStringObject *lir);
     bool visitNewPar(LNewPar *lir);
     bool visitNewDenseArrayPar(LNewDenseArrayPar *lir);
     bool visitNewDerivedTypedObject(LNewDerivedTypedObject *lir);
     bool visitAbortPar(LAbortPar *lir);
     bool visitInitElem(LInitElem *lir);
     bool visitInitElemGetterSetter(LInitElemGetterSetter *lir);
+    bool visitMutateProto(LMutateProto *lir);
     bool visitInitProp(LInitProp *lir);
     bool visitInitPropGetterSetter(LInitPropGetterSetter *lir);
     bool visitCreateThis(LCreateThis *lir);
     bool visitCreateThisWithProto(LCreateThisWithProto *lir);
     bool visitCreateThisWithTemplate(LCreateThisWithTemplate *lir);
     bool visitCreateArgumentsObject(LCreateArgumentsObject *lir);
     bool visitGetArgumentsObjectArg(LGetArgumentsObjectArg *lir);
     bool visitSetArgumentsObjectArg(LSetArgumentsObjectArg *lir);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1582,16 +1582,21 @@ IonBuilder::inspectOpcode(JSOp op)
         return jsop_initelem_array();
 
       case JSOP_INITPROP:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         return jsop_initprop(name);
       }
 
+      case JSOP_MUTATEPROTO:
+      {
+        return jsop_mutateproto();
+      }
+
       case JSOP_INITPROP_GETTER:
       case JSOP_INITPROP_SETTER: {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         return jsop_initprop_getter_setter(name);
       }
 
       case JSOP_INITELEM_GETTER:
       case JSOP_INITELEM_SETTER:
@@ -5519,16 +5524,27 @@ IonBuilder::jsop_initelem_array()
 
     if (!resumeAfter(initLength))
         return false;
 
    return true;
 }
 
 bool
+IonBuilder::jsop_mutateproto()
+{
+    MDefinition *value = current->pop();
+    MDefinition *obj = current->peek(-1);
+
+    MMutateProto *mutate = MMutateProto::New(alloc(), obj, value);
+    current->add(mutate);
+    return resumeAfter(mutate);
+}
+
+bool
 IonBuilder::jsop_initprop(PropertyName *name)
 {
     MDefinition *value = current->pop();
     MDefinition *obj = current->peek(-1);
 
     JSObject *templateObject = obj->toNewObject()->templateObject();
     AutoThreadSafeAccess ts(templateObject);
 
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -552,16 +552,17 @@ class IonBuilder : public MIRGenerator
     bool jsop_setprop(PropertyName *name);
     bool jsop_delprop(PropertyName *name);
     bool jsop_delelem();
     bool jsop_newarray(uint32_t count);
     bool jsop_newobject();
     bool jsop_initelem();
     bool jsop_initelem_array();
     bool jsop_initelem_getter_setter();
+    bool jsop_mutateproto();
     bool jsop_initprop(PropertyName *name);
     bool jsop_initprop_getter_setter(PropertyName *name);
     bool jsop_regexp(RegExpObject *reobj);
     bool jsop_object(JSObject *obj);
     bool jsop_lambda(JSFunction *fun);
     bool jsop_this();
     bool jsop_typeof();
     bool jsop_toid();
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -616,16 +616,36 @@ class LInitElemGetterSetter : public LCa
         return getOperand(1);
     }
     MInitElemGetterSetter *mir() const {
         return mir_->toInitElemGetterSetter();
     }
 };
 
 // Takes in an Object and a Value.
+class LMutateProto : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
+{
+  public:
+    LIR_HEADER(MutateProto)
+
+    LMutateProto(const LAllocation &object) {
+        setOperand(0, object);
+    }
+
+    static const size_t ValueIndex = 1;
+
+    const LAllocation *getObject() {
+        return getOperand(0);
+    }
+    const LAllocation *getValue() {
+        return getOperand(1);
+    }
+};
+
+// Takes in an Object and a Value.
 class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InitProp)
 
     LInitProp(const LAllocation &object) {
         setOperand(0, object);
     }
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -31,16 +31,17 @@
     _(NewStringObject)              \
     _(NewPar)                       \
     _(NewDenseArrayPar)             \
     _(NewCallObjectPar)             \
     _(NewDerivedTypedObject)        \
     _(AbortPar)                     \
     _(InitElem)                     \
     _(InitElemGetterSetter)         \
+    _(MutateProto)                    \
     _(InitProp)                     \
     _(InitPropGetterSetter)         \
     _(CheckOverRecursed)            \
     _(CheckOverRecursedPar)         \
     _(DefVar)                       \
     _(DefFun)                       \
     _(CallKnown)                    \
     _(CallGeneric)                  \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -275,16 +275,26 @@ LIRGenerator::visitInitElemGetterSetter(
                                            useRegisterAtStart(ins->value()));
     if (!useBoxAtStart(lir, LInitElemGetterSetter::IdIndex, ins->idValue()))
         return false;
 
     return add(lir, ins) && assignSafepoint(lir, ins);
 }
 
 bool
+LIRGenerator::visitMutateProto(MMutateProto *ins)
+{
+    LMutateProto *lir = new(alloc()) LMutateProto(useRegisterAtStart(ins->getObject()));
+    if (!useBoxAtStart(lir, LMutateProto::ValueIndex, ins->getValue()))
+        return false;
+
+    return add(lir, ins) && assignSafepoint(lir, ins);
+}
+
+bool
 LIRGenerator::visitInitProp(MInitProp *ins)
 {
     LInitProp *lir = new(alloc()) LInitProp(useRegisterAtStart(ins->getObject()));
     if (!useBoxAtStart(lir, LInitProp::ValueIndex, ins->getValue()))
         return false;
 
     return add(lir, ins) && assignSafepoint(lir, ins);
 }
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -74,16 +74,17 @@ class LIRGenerator : public LIRGenerator
     bool visitNewStringObject(MNewStringObject *ins);
     bool visitNewDerivedTypedObject(MNewDerivedTypedObject *ins);
     bool visitNewPar(MNewPar *ins);
     bool visitNewCallObjectPar(MNewCallObjectPar *ins);
     bool visitNewDenseArrayPar(MNewDenseArrayPar *ins);
     bool visitAbortPar(MAbortPar *ins);
     bool visitInitElem(MInitElem *ins);
     bool visitInitElemGetterSetter(MInitElemGetterSetter *ins);
+    bool visitMutateProto(MMutateProto *ins);
     bool visitInitProp(MInitProp *ins);
     bool visitInitPropGetterSetter(MInitPropGetterSetter *ins);
     bool visitCheckOverRecursed(MCheckOverRecursed *ins);
     bool visitCheckOverRecursedPar(MCheckOverRecursedPar *ins);
     bool visitDefVar(MDefVar *ins);
     bool visitDefFun(MDefFun *ins);
     bool visitCreateThisWithTemplate(MCreateThisWithTemplate *ins);
     bool visitCreateThisWithProto(MCreateThisWithProto *ins);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1619,16 +1619,52 @@ class MAbortPar : public MAryControlInst
   public:
     INSTRUCTION_HEADER(AbortPar);
 
     static MAbortPar *New(TempAllocator &alloc) {
         return new(alloc) MAbortPar();
     }
 };
 
+// Setting __proto__ in an object literal.
+class MMutateProto
+  : public MAryInstruction<2>,
+    public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >
+{
+  protected:
+    MMutateProto(MDefinition *obj, MDefinition *value)
+    {
+        setOperand(0, obj);
+        setOperand(1, value);
+        setResultType(MIRType_None);
+    }
+
+  public:
+    INSTRUCTION_HEADER(MutateProto)
+
+    static MMutateProto *New(TempAllocator &alloc, MDefinition *obj, MDefinition *value)
+    {
+        return new(alloc) MMutateProto(obj, value);
+    }
+
+    MDefinition *getObject() const {
+        return getOperand(0);
+    }
+    MDefinition *getValue() const {
+        return getOperand(1);
+    }
+
+    TypePolicy *typePolicy() {
+        return this;
+    }
+    bool possiblyCalls() const {
+        return true;
+    }
+};
+
 // Slow path for adding a property to an object without a known base.
 class MInitProp
   : public MAryInstruction<2>,
     public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >
 {
   public:
     CompilerRootPropertyName name_;
 
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -88,16 +88,17 @@ namespace jit {
     _(NewSlots)                                                             \
     _(NewArray)                                                             \
     _(NewObject)                                                            \
     _(NewDeclEnvObject)                                                     \
     _(NewCallObject)                                                        \
     _(NewStringObject)                                                      \
     _(InitElem)                                                             \
     _(InitElemGetterSetter)                                                 \
+    _(MutateProto)                                                          \
     _(InitProp)                                                             \
     _(InitPropGetterSetter)                                                 \
     _(Start)                                                                \
     _(OsrEntry)                                                             \
     _(Nop)                                                                  \
     _(RegExp)                                                               \
     _(RegExpExec)                                                           \
     _(RegExpTest)                                                           \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -181,16 +181,17 @@ class ParallelSafetyVisitor : public MIn
     CUSTOM_OP(ToString)
     SAFE_OP(NewSlots)
     CUSTOM_OP(NewArray)
     CUSTOM_OP(NewObject)
     CUSTOM_OP(NewCallObject)
     UNSAFE_OP(NewDerivedTypedObject)
     UNSAFE_OP(InitElem)
     UNSAFE_OP(InitElemGetterSetter)
+    UNSAFE_OP(MutateProto)
     UNSAFE_OP(InitProp)
     UNSAFE_OP(InitPropGetterSetter)
     SAFE_OP(Start)
     UNSAFE_OP(OsrEntry)
     SAFE_OP(Nop)
     UNSAFE_OP(RegExp)
     CUSTOM_OP(Lambda)
     UNSAFE_OP(ImplicitThis)
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -183,24 +183,34 @@ SetConst(JSContext *cx, HandlePropertyNa
     RootedObject obj(cx, scopeChain);
     while (!obj->isVarObj())
         obj = obj->enclosingScope();
 
     return SetConstOperation(cx, obj, name, rval);
 }
 
 bool
+MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value)
+{
+    // Copy the incoming value. This may be overwritten; the return value is discarded.
+    RootedValue rval(cx, value);
+
+    RootedId id(cx, NameToId(cx->names().proto));
+    return baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval, false);
+}
+
+bool
 InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value)
 {
     // Copy the incoming value. This may be overwritten; the return value is discarded.
     RootedValue rval(cx, value);
     RootedId id(cx, NameToId(name));
 
-    if (name == cx->names().proto)
-        return baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval, false);
+    MOZ_ASSERT(name != cx->names().proto,
+               "__proto__ should have been handled by JSOP_MUTATEPROTO");
     return DefineNativeProperty(cx, obj, id, rval, nullptr, nullptr, JSPROP_ENUMERATE, 0, 0, 0);
 }
 
 template<bool Equal>
 bool
 LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res)
 {
     if (!js::LooselyEqual(cx, lhs, rhs, res))
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -570,16 +570,17 @@ JSObject *NewGCThing(JSContext *cx, gc::
                      gc::InitialHeap initialHeap);
 
 bool CheckOverRecursed(JSContext *cx);
 bool CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame,
                                 uint32_t extra, uint32_t earlyCheck);
 
 bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
 bool SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval);
+bool MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value);
 bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value);
 
 template<bool Equal>
 bool LooselyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
 
 template<bool Equal>
 bool StrictlyEqual(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res);
 
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -255,17 +255,17 @@ MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX,     20
 MSG_DEF(JSMSG_BUFFER_TOO_SMALL,       202, 0, JSEXN_INTERNALERR, "buffer too small")
 MSG_DEF(JSMSG_BAD_SURROGATE_CHAR,     203, 1, JSEXN_TYPEERR, "bad surrogate character {0}")
 MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE,    204, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
 MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR,    205, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
 MSG_DEF(JSMSG_USER_DEFINED_ERROR,     206, 0, JSEXN_ERR, "JS_ReportError was called")
 MSG_DEF(JSMSG_WRONG_CONSTRUCTOR,      207, 1, JSEXN_TYPEERR, "wrong constructor called for {0}")
 MSG_DEF(JSMSG_BAD_GENERATOR_RETURN,   208, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
 MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
-MSG_DEF(JSMSG_UNUSED210,              210, 0, JSEXN_NONE, "")
+MSG_DEF(JSMSG_PROTO_SETTING_SLOW,     210, 0, JSEXN_TYPEERR, "mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create")
 MSG_DEF(JSMSG_IN_AFTER_FOR_NAME,      211, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for")
 MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE,  212, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
 MSG_DEF(JSMSG_UNUSED213,              213, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_BAD_GENERATOR_YIELD,    214, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
 MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX,   215, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized")
 MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE,    216, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
 MSG_DEF(JSMSG_UNUSED217,              217, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE,     218, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4477,32 +4477,34 @@ JS::Compile(JSContext *cx, HandleObject 
     options.setFileAndLine(filename, 1);
     JSScript *script = Compile(cx, obj, options, file.fp());
     return script;
 }
 
 JS_PUBLIC_API(bool)
 JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
 {
-    static const unsigned TINY_LENGTH = 1000;
-    static const unsigned HUGE_LENGTH = 100*1000;
+    static const size_t TINY_LENGTH = 1000;
+    static const size_t HUGE_LENGTH = 100 * 1000;
 
     // These are heuristics which the caller may choose to ignore (e.g., for
     // testing purposes).
     if (!options.forceAsync) {
         // Compiling off the main thread inolves creating a new Zone and other
         // significant overheads.  Don't bother if the script is tiny.
         if (length < TINY_LENGTH)
             return false;
 
+#ifdef JS_THREADSAFE
         // If the parsing task would have to wait for GC to complete, it'll probably
         // be faster to just start it synchronously on the main thread unless the
         // script is huge.
         if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
             return false;
+#endif // JS_THREADSAFE
     }
 
     return cx->runtime()->canUseParallelParsing();
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileOffThread(JSContext *cx, Handle<JSObject*> obj, const ReadOnlyCompileOptions &options,
                      const jschar *chars, size_t length,
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -405,17 +405,18 @@ OPDEF(JSOP_UINT24,        188,"uint24", 
 
 OPDEF(JSOP_UNUSED189,     189,"unused189",   NULL,    1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED190,     190,"unused190",   NULL,    1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED191,     191,"unused191",   NULL,    1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED192,     192,"unused192",   NULL,    1,  0,  0,  JOF_BYTE)
 
 OPDEF(JSOP_CALLELEM,      193, "callelem",   NULL,    1,  2,  1, JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC)
 
-OPDEF(JSOP_UNUSED194,     194,"unused194",   NULL,    1,  0,  0,  JOF_BYTE)
+/* __proto__: v inside an object initializer. */
+OPDEF(JSOP_MUTATEPROTO,   194, "mutateproto",NULL,    1,  2,  1, JOF_BYTE)
 
 /*
  * Get an extant property value, throwing ReferenceError if the identified
  * property does not exist.
  */
 OPDEF(JSOP_GETXPROP,      195,"getxprop",    NULL,    5,  1,  1, JOF_ATOM|JOF_PROP|JOF_TYPESET)
 
 OPDEF(JSOP_UNUSED196,     196,"unused196",   NULL,    1,  0,  0, JOF_BYTE)
--- a/js/src/jsworkers.h
+++ b/js/src/jsworkers.h
@@ -374,20 +374,22 @@ struct ParseTask
     bool init(JSContext *cx, const ReadOnlyCompileOptions &options);
 
     void activate(JSRuntime *rt);
     void finish();
 
     ~ParseTask();
 };
 
+#ifdef JS_THREADSAFE
 // Return whether, if a new parse task was started, it would need to wait for
 // an in-progress GC to complete before starting.
 extern bool
 OffThreadParsingMustWaitForGC(JSRuntime *rt);
+#endif
 
 // Compression tasks are allocated on the stack by their triggering thread,
 // which will block on the compression completing as the task goes out of scope
 // to ensure it completes at the required time.
 struct SourceCompressionTask
 {
     friend class ScriptSource;
 
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -143,16 +143,24 @@ ProtoSetterImpl(JSContext *cx, CallArgs 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 ProtoSetter(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
+
+    // Do this here, rather than in |ProtoSetterImpl|, so even likely-buggy
+    // use of the __proto__ setter on unacceptable values, where no subsequent
+    // use occurs on an acceptable value, will trigger a warning.
+    RootedObject callee(cx, &args.callee());
+    if (!GlobalObject::warnOnceAboutPrototypeMutation(cx, callee))
+        return false;
+
     return CallNonGenericMethod(cx, TestProtoThis, ProtoSetterImpl, args);
 }
 
 JSObject *
 GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
 {
     Rooted<GlobalObject*> self(cx, this);
 
@@ -496,28 +504,27 @@ GlobalObject::isRuntimeCodeGenEnabled(JS
         JSCSPEvalChecker allows = cx->runtime()->securityCallbacks->contentSecurityPolicyAllows;
         Value boolValue = BooleanValue(!allows || allows(cx));
         v.set(global, HeapSlot::Slot, RUNTIME_CODEGEN_ENABLED, boolValue);
     }
     return !v.isFalse();
 }
 
 /* static */ bool
-GlobalObject::warnOnceAboutWatch(JSContext *cx, HandleObject obj)
+GlobalObject::warnOnceAbout(JSContext *cx, HandleObject obj, uint32_t slot, unsigned errorNumber)
 {
     Rooted<GlobalObject*> global(cx, &obj->global());
-    HeapSlot &v = global->getSlotRef(WARNED_WATCH_DEPRECATED);
+    HeapSlot &v = global->getSlotRef(slot);
     if (v.isUndefined()) {
-        // Warn only once per global object.
         if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, js_GetErrorMessage, nullptr,
-                                          JSMSG_OBJECT_WATCH_DEPRECATED))
+                                          errorNumber))
         {
             return false;
         }
-        v.init(global, HeapSlot::Slot, WARNED_WATCH_DEPRECATED, BooleanValue(true));
+        v.init(global, HeapSlot::Slot, slot, BooleanValue(true));
     }
     return true;
 }
 
 JSFunction *
 GlobalObject::createConstructor(JSContext *cx, Native ctor, JSAtom *nameArg, unsigned length,
                                 gc::AllocKind kind)
 {
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -100,17 +100,18 @@ class GlobalObject : public JSObject
     static const unsigned STAR_GENERATOR_OBJECT_PROTO = LEGACY_GENERATOR_OBJECT_PROTO + 1;
     static const unsigned MAP_ITERATOR_PROTO      = STAR_GENERATOR_OBJECT_PROTO + 1;
     static const unsigned SET_ITERATOR_PROTO      = MAP_ITERATOR_PROTO + 1;
     static const unsigned COLLATOR_PROTO          = SET_ITERATOR_PROTO + 1;
     static const unsigned NUMBER_FORMAT_PROTO     = COLLATOR_PROTO + 1;
     static const unsigned DATE_TIME_FORMAT_PROTO  = NUMBER_FORMAT_PROTO + 1;
     static const unsigned REGEXP_STATICS          = DATE_TIME_FORMAT_PROTO + 1;
     static const unsigned WARNED_WATCH_DEPRECATED = REGEXP_STATICS + 1;
-    static const unsigned RUNTIME_CODEGEN_ENABLED = WARNED_WATCH_DEPRECATED + 1;
+    static const unsigned WARNED_PROTO_SETTING_SLOW = WARNED_WATCH_DEPRECATED + 1;
+    static const unsigned RUNTIME_CODEGEN_ENABLED = WARNED_PROTO_SETTING_SLOW + 1;
     static const unsigned DEBUGGERS               = RUNTIME_CODEGEN_ENABLED + 1;
     static const unsigned INTRINSICS              = DEBUGGERS + 1;
     static const unsigned FLOAT32X4_TYPE_OBJECT   = INTRINSICS + 1;
     static const unsigned INT32X4_TYPE_OBJECT     = FLOAT32X4_TYPE_OBJECT + 1;
 
     /* Total reserved-slot count for global objects. */
     static const unsigned RESERVED_SLOTS = INT32X4_TYPE_OBJECT + 1;
 
@@ -146,16 +147,23 @@ class GlobalObject : public JSObject
         setSlot(PROTO_GETTER, ObjectValue(*protoGetter));
     }
 
     void setIntrinsicsHolder(JSObject *obj) {
         JS_ASSERT(getSlotRef(INTRINSICS).isUndefined());
         setSlot(INTRINSICS, ObjectValue(*obj));
     }
 
+    // Emit the specified warning if the given slot in |obj|'s global isn't
+    // true, then set the slot to true.  Thus calling this method warns once
+    // for each global object it's called on, and every other call does
+    // nothing.
+    static bool
+    warnOnceAbout(JSContext *cx, HandleObject obj, uint32_t slot, unsigned errorNumber);
+
   public:
     Value getConstructor(JSProtoKey key) const {
         JS_ASSERT(key <= JSProto_LIMIT);
         return getSlotForCompilation(APPLICATION_SLOTS + key);
     }
 
     void setConstructor(JSProtoKey key, const Value &v) {
         JS_ASSERT(key <= JSProto_LIMIT);
@@ -600,17 +608,30 @@ class GlobalObject : public JSObject
         JS_ASSERT(functionObjectClassesInitialized());
         return getSlot(PROTO_GETTER);
     }
 
     static bool isRuntimeCodeGenEnabled(JSContext *cx, Handle<GlobalObject*> global);
 
     // Warn about use of the deprecated watch/unwatch functions in the global
     // in which |obj| was created, if no prior warning was given.
-    static bool warnOnceAboutWatch(JSContext *cx, HandleObject obj);
+    static bool warnOnceAboutWatch(JSContext *cx, HandleObject obj) {
+        // Temporarily disabled until we've provided a watch/unwatch workaround for
+        // debuggers like Firebug (bug 934669).
+        //return warnOnceAbout(cx, obj, WARNED_WATCH_DEPRECATED, JSMSG_OBJECT_WATCH_DEPRECATED);
+        return true;
+    }
+
+    // Warn about use of the given __proto__ setter to attempt to mutate an
+    // object's [[Prototype]], if no prior warning was given.
+    static bool warnOnceAboutPrototypeMutation(JSContext *cx, HandleObject protoSetter) {
+        // Temporarily disabled until the second half of bug 948583 lands.
+        //return warnOnceAbout(cx, protoSetter, WARNED_PROTO_SETTING_SLOW, JSMSG_PROTO_SETTING_SLOW);
+        return true;
+    }
 
     static bool getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global,
                                 MutableHandleObject eval);
 
     // Infallibly test whether the given value is the eval function for this global.
     bool valueIsEval(Value val);
 
     // Implemented in jsiter.cpp.
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1653,17 +1653,16 @@ CASE(JSOP_UNUSED182)
 CASE(JSOP_UNUSED183)
 CASE(JSOP_UNUSED185)
 CASE(JSOP_UNUSED186)
 CASE(JSOP_UNUSED187)
 CASE(JSOP_UNUSED189)
 CASE(JSOP_UNUSED190)
 CASE(JSOP_UNUSED191)
 CASE(JSOP_UNUSED192)
-CASE(JSOP_UNUSED194)
 CASE(JSOP_UNUSED196)
 CASE(JSOP_UNUSED201)
 CASE(JSOP_UNUSED205)
 CASE(JSOP_UNUSED206)
 CASE(JSOP_UNUSED207)
 CASE(JSOP_UNUSED208)
 CASE(JSOP_UNUSED209)
 CASE(JSOP_UNUSED210)
@@ -3107,16 +3106,38 @@ END_CASE(JSOP_NEWOBJECT)
 CASE(JSOP_ENDINIT)
 {
     /* FIXME remove JSOP_ENDINIT bug 588522 */
     JS_ASSERT(REGS.stackDepth() >= 1);
     JS_ASSERT(REGS.sp[-1].isObject() || REGS.sp[-1].isUndefined());
 }
 END_CASE(JSOP_ENDINIT)
 
+CASE(JSOP_MUTATEPROTO)
+{
+    /* Load the new [[Prototype]] value into rval. */
+    MOZ_ASSERT(REGS.stackDepth() >= 2);
+    RootedValue &rval = rootValue0;
+    rval = REGS.sp[-1];
+
+    /* Load the object being initialized into lval/obj. */
+    RootedObject &obj = rootObject0;
+    obj = &REGS.sp[-2].toObject();
+    MOZ_ASSERT(obj->is<JSObject>());
+
+    RootedId &id = rootId0;
+    id = NameToId(cx->names().proto);
+
+    if (!baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval, false))
+        goto error;
+
+    REGS.sp--;
+}
+END_CASE(JSOP_MUTATEPROTO);
+
 CASE(JSOP_INITPROP)
 {
     /* Load the property's initial value into rval. */
     JS_ASSERT(REGS.stackDepth() >= 2);
     RootedValue &rval = rootValue0;
     rval = REGS.sp[-1];
 
     /* Load the object being initialized into lval/obj. */
@@ -3124,23 +3145,18 @@ CASE(JSOP_INITPROP)
     obj = &REGS.sp[-2].toObject();
     JS_ASSERT(obj->is<JSObject>());
 
     PropertyName *name = script->getName(REGS.pc);
 
     RootedId &id = rootId0;
     id = NameToId(name);
 
-    if (JS_UNLIKELY(name == cx->names().proto)
-        ? !baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval,
-                                                           script->strict())
-        : !DefineNativeProperty(cx, obj, id, rval, nullptr, nullptr,
-                                JSPROP_ENUMERATE, 0, 0, 0)) {
+    if (!DefineNativeProperty(cx, obj, id, rval, nullptr, nullptr, JSPROP_ENUMERATE, 0, 0, 0))
         goto error;
-    }
 
     REGS.sp--;
 }
 END_CASE(JSOP_INITPROP);
 
 CASE(JSOP_INITELEM)
 {
     JS_ASSERT(REGS.stackDepth() >= 3);
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -2070,16 +2070,18 @@ nsListControlFrame::KeyDown(nsIDOMEvent*
 {
   MOZ_ASSERT(aKeyEvent, "aKeyEvent is null.");
 
   nsEventStates eventStates = mContent->AsElement()->State();
   if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
     return NS_OK;
   }
 
+  AutoIncrementalSearchResetter incrementalSearchResetter;
+
   // Don't check defaultPrevented value because other browsers don't prevent
   // the key navigation of list control even if preventDefault() is called.
 
   const WidgetKeyboardEvent* keyEvent =
     aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   MOZ_ASSERT(keyEvent,
     "DOM event must have WidgetKeyboardEvent for its internal event");
 
@@ -2119,51 +2121,55 @@ nsListControlFrame::KeyDown(nsIDOMEvent*
       break;
     case NS_VK_DOWN:
     case NS_VK_RIGHT:
       AdjustIndexForDisabledOpt(mEndSelectionIndex, newIndex,
                                 static_cast<int32_t>(numOptions),
                                 1, 1);
       break;
     case NS_VK_RETURN:
-      if (mComboboxFrame) {
-        nsWeakFrame weakFrame(this);
+      if (IsInDropDownMode()) {
+        // If the select element is a dropdown style, Enter key should be
+        // consumed everytime since Enter key may be pressed accidentally after
+        // the dropdown is closed by Enter key press.
+        aKeyEvent->PreventDefault();
+
         if (mComboboxFrame->IsDroppedDown()) {
-          // At closing dropdown, users may not expect there is additional
-          // behavior for this key event.  Therefore, let's consume the event.
-          aKeyEvent->PreventDefault();
+          nsWeakFrame weakFrame(this);
           ComboboxFinish(mEndSelectionIndex);
           if (!weakFrame.IsAlive()) {
             return NS_OK;
           }
         }
+        // XXX This is strange. On other browsers, "change" event is fired
+        //     immediately after the selected item is changed rather than
+        //     Enter key is pressed.
         FireOnChange();
-        if (!weakFrame.IsAlive()) {
-          // If the keydown event causes destroying this, fired keypress on
-          // another element may cause another action which may not be
-          // expected by the user.
-          aKeyEvent->PreventDefault();
-        }
         return NS_OK;
       }
+
+      // If this is single select listbox, Enter key doesn't cause anything.
+      if (!GetMultiple()) {
+        return NS_OK;
+      }
+
       newIndex = mEndSelectionIndex;
       break;
     case NS_VK_ESCAPE: {
-      nsWeakFrame weakFrame(this);
-      // XXX When the Escape keydown causes closing dropdown, it shouldn't
-      //     cause any additonal actions. We should call preventDefault() here.
-      AboutToRollup();
-      if (!weakFrame.IsAlive()) {
-        // If the keydown event causes destroying this, fired keypress on
-        // another element may cause another action which may not be
-        // expected by the user.
-        aKeyEvent->PreventDefault();
+      // If the select element is a listbox style, Escape key causes nothing.
+      if (!IsInDropDownMode()) {
         return NS_OK;
       }
-      break;
+
+      AboutToRollup();
+      // If the select element is a dropdown style, Enter key should be
+      // consumed everytime since Escape key may be pressed accidentally after
+      // the dropdown is closed by Escepe key.
+      aKeyEvent->PreventDefault();
+      return NS_OK;
     }
     case NS_VK_PAGE_UP: {
       int32_t itemsPerPage =
         std::max(1, static_cast<int32_t>(mNumDisplayRows - 1));
       AdjustIndexForDisabledOpt(mEndSelectionIndex, newIndex,
                                 static_cast<int32_t>(numOptions),
                                 -itemsPerPage, -1);
       break;
@@ -2189,40 +2195,40 @@ nsListControlFrame::KeyDown(nsIDOMEvent*
 
 #if defined(XP_WIN) || defined(XP_OS2)
     case NS_VK_F4:
       DropDownToggleKey(aKeyEvent);
       return NS_OK;
 #endif
 
     default: // printable key will be handled by keypress event.
+      incrementalSearchResetter.Cancel();
       return NS_OK;
   }
 
   aKeyEvent->PreventDefault();
 
-  // Cancel incremental search if it's being performed.
-  GetIncrementalString().Truncate();
-
   // Actually process the new index and let the selection code
   // do the scrolling for us
   PostHandleKeyEvent(newIndex, 0, keyEvent->IsShift(), isControlOrMeta);
   return NS_OK;
 }
 
 nsresult
 nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
 {
   MOZ_ASSERT(aKeyEvent, "aKeyEvent is null.");
 
   nsEventStates eventStates = mContent->AsElement()->State();
   if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
     return NS_OK;
   }
 
+  AutoIncrementalSearchResetter incrementalSearchResetter;
+
   const WidgetKeyboardEvent* keyEvent =
     aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   MOZ_ASSERT(keyEvent,
     "DOM event must have WidgetKeyboardEvent for its internal event");
 
   // Select option with this as the first character
   // XXX Not I18N compliant
 
@@ -2245,27 +2251,35 @@ nsListControlFrame::KeyPress(nsIDOMEvent
   bool isControlOrMeta = (keyEvent->IsControl() || keyEvent->IsMeta());
   if (isControlOrMeta && keyEvent->charCode != ' ') {
     return NS_OK;
   }
 
   // NOTE: If keyCode of keypress event is not 0, charCode is always 0.
   //       Therefore, all non-printable keys are not handled after this block.
   if (!keyEvent->charCode) {
-    // Backspace key will delete the last char in the string
-    // XXX Backspace key causes "go back the history" on Windows.  Shouldn't we
-    //     prevent its default action if incremental search is used since
-    //     getting focus?  When I tested this, it worked accidentally.
-    if (keyEvent->keyCode == NS_VK_BACK && !GetIncrementalString().IsEmpty()) {
-      GetIncrementalString().Truncate(GetIncrementalString().Length() - 1);
+    // Backspace key will delete the last char in the string.  Otherwise,
+    // non-printable keypress should reset incremental search.
+    if (keyEvent->keyCode == NS_VK_BACK) {
+      incrementalSearchResetter.Cancel();
+      if (!GetIncrementalString().IsEmpty()) {
+        GetIncrementalString().Truncate(GetIncrementalString().Length() - 1);
+      }
       aKeyEvent->PreventDefault();
+    } else {
+      // XXX When a select element has focus, even if the key causes nothing,
+      //     it might be better to call preventDefault() here because nobody
+      //     should expect one of other elements including chrome handles the
+      //     key event.
     }
     return NS_OK;
   }
 
+  incrementalSearchResetter.Cancel();
+
   // We ate the key if we got this far.
   aKeyEvent->PreventDefault();
 
   // XXX Why don't we check/modify timestamp first?
 
   // Incremental Search: if time elapsed is below
   // INCREMENTAL_SEARCH_KEYPRESS_TIME, append this keystroke to the search
   // string we will use to find options and start searching at the current
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -440,12 +440,33 @@ protected:
 #ifdef DO_REFLOW_COUNTER
   int32_t mReflowId;
 #endif
 
 private:
   // for incremental typing navigation
   static nsAString& GetIncrementalString ();
   static DOMTimeStamp gLastKeyTime;
+
+  class MOZ_STACK_CLASS AutoIncrementalSearchResetter
+  {
+  public:
+    AutoIncrementalSearchResetter() :
+      mCancelled(false)
+    {
+    }
+    ~AutoIncrementalSearchResetter()
+    {
+      if (!mCancelled) {
+        nsListControlFrame::GetIncrementalString().Truncate();
+      }
+    }
+    void Cancel()
+    {
+      mCancelled = true;
+    }
+  private:
+    bool mCancelled;
+  };
 };
 
 #endif /* nsListControlFrame_h___ */
 
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -794,17 +794,17 @@ void nsDisplayNotation::Paint(nsDisplayL
       gfxCtx->NewPath();
       gfxPoint p[] = {
         rect.TopRight(),
         rect.TopRight() + gfxPoint(-w -.4*h, std::max(-e / 2.0, h - .4*w)),
         rect.TopRight() + gfxPoint(-.7*w, .7*h),
         rect.TopRight() + gfxPoint(std::min(e / 2.0, -w + .4*h), h + .4*w),
         rect.TopRight()
       };
-      gfxCtx->Polygon(p, sizeof(p));
+      gfxCtx->Polygon(p, MOZ_ARRAY_LENGTH(p));
       gfxCtx->Fill();
     }
       break;
 
     default:
       NS_NOTREACHED("This notation can not be drawn using nsDisplayNotation");
       break;
     }
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -555,16 +555,17 @@ function getStreamContent(inputStream)
 
     return streamBuf;
 }
 
 // Build the sandbox for fails-if(), etc., condition evaluation.
 function BuildConditionSandbox(aURL) {
     var sandbox = new Components.utils.Sandbox(aURL.spec);
     var xr = CC[NS_XREAPPINFO_CONTRACTID].getService(CI.nsIXULRuntime);
+    var appInfo = CC[NS_XREAPPINFO_CONTRACTID].getService(CI.nsIXULAppInfo);
     sandbox.isDebugBuild = gDebug.isDebugBuild;
     sandbox.xulRuntime = {widgetToolkit: xr.widgetToolkit, OS: xr.OS, __exposedProps__: { widgetToolkit: "r", OS: "r", XPCOMABI: "r", shell: "r" } };
 
     // xr.XPCOMABI throws exception for configurations without full ABI
     // support (mobile builds on ARM)
     try {
         sandbox.xulRuntime.XPCOMABI = xr.XPCOMABI;
     } catch(e) {
@@ -595,16 +596,17 @@ function BuildConditionSandbox(aURL) {
       gWindowUtils.layerManagerType != "Basic";
     sandbox.layersOpenGL =
       gWindowUtils.layerManagerType == "OpenGL";
     sandbox.layersOMTC =
       gWindowUtils.layerManagerRemote == true;
 
     // Shortcuts for widget toolkits.
     sandbox.B2G = xr.widgetToolkit == "gonk";
+    sandbox.B2GDT = appInfo.name.toLowerCase() == "b2g" && !sandbox.B2G;
     sandbox.Android = xr.OS == "Android" && !sandbox.B2G;
     sandbox.cocoaWidget = xr.widgetToolkit == "cocoa";
     sandbox.gtk2Widget = xr.widgetToolkit == "gtk2";
     sandbox.qtWidget = xr.widgetToolkit == "qt";
     sandbox.winWidget = xr.widgetToolkit == "windows";
 
     if (sandbox.Android) {
         var sysInfo = CC["@mozilla.org/system-info;1"].getService(CI.nsIPropertyBag2);
--- a/media/webrtc/signaling/test/Makefile.in
+++ b/media/webrtc/signaling/test/Makefile.in
@@ -12,16 +12,20 @@ LIBS = \
   $(DEPTH)/media/webrtc/signalingtest/signaling_ecc/$(LIB_PREFIX)ecc.$(LIB_SUFFIX) \
   $(DEPTH)/media/webrtc/signalingtest/signaling_sipcc/$(LIB_PREFIX)sipcc.$(LIB_SUFFIX) \
   $(DEPTH)/layout/media/webrtc/$(LIB_PREFIX)webrtc.$(LIB_SUFFIX) \
   $(DEPTH)/layout/media/$(LIB_PREFIX)gkmedias.$(LIB_SUFFIX) \
   $(DEPTH)/media/webrtc/trunk/testing/gtest_gtest/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \
   $(DEPTH)/netwerk/srtp/src/$(LIB_PREFIX)nksrtp_s.$(LIB_SUFFIX) \
   $(NULL)
 
+ifdef JS_SHARED_LIBRARY
+LIBS += $(MOZ_JS_LIBS)
+endif
+
 ifdef MOZ_ALSA
 LIBS += \
   $(MOZ_ALSA_LIBS) \
   $(NULL)
 endif
 
 ifeq ($(OS_TARGET),Android)
 LIBS += \
--- a/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal.h.in
+++ b/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal.h.in
@@ -283,16 +283,19 @@ static const bool config_ivsalloc =
 #    define LG_QUANTUM		4
 #  endif
 #  ifdef __SH4__
 #    define LG_QUANTUM		4
 #  endif
 #  ifdef __tile__
 #    define LG_QUANTUM		4
 #  endif
+#  ifdef __aarch64__
+#    define LG_QUANTUM		4
+#  endif
 #  ifndef LG_QUANTUM
 #    error "No LG_QUANTUM definition for architecture; specify via CPPFLAGS"
 #  endif
 #endif
 
 #define	QUANTUM			((size_t)(1U << LG_QUANTUM))
 #define	QUANTUM_MASK		(QUANTUM - 1)
 
--- a/memory/mozjemalloc/jemalloc.c
+++ b/memory/mozjemalloc/jemalloc.c
@@ -1097,17 +1097,17 @@ static unsigned		ncpus;
 /*
  * VM page size. It must divide the runtime CPU page size or the code
  * will abort.
  * Platform specific page size conditions copied from js/public/HeapAPI.h
  */
 #if (defined(SOLARIS) || defined(__FreeBSD__)) && \
     (defined(__sparc) || defined(__sparcv9) || defined(__ia64))
 #define pagesize_2pow			((size_t) 13)
-#elif defined(__powerpc64__)
+#elif defined(__powerpc64__) || defined(__aarch64__)
 #define pagesize_2pow			((size_t) 16)
 #else
 #define pagesize_2pow			((size_t) 12)
 #endif
 #define pagesize			((size_t) 1 << pagesize_2pow)
 #define pagesize_mask			(pagesize - 1)
 
 /* Various quantum-related settings. */
--- a/mfbt/Endian.h
+++ b/mfbt/Endian.h
@@ -117,24 +117,24 @@
  * here because they're not present on all platforms.  Instead we have
  * this big conditional that ideally will catch all the interesting
  * cases.
  */
 #elif defined(__sparc) || defined(__sparc__) || \
       defined(_POWER) || defined(__powerpc__) || \
       defined(__ppc__) || defined(__hppa) || \
       defined(_MIPSEB) || defined(__ARMEB__) || \
-      defined(__s390__) || \
+      defined(__s390__) || defined(__AARCH64EB__) || \
       (defined(__sh__) && defined(__LITTLE_ENDIAN__)) || \
       (defined(__ia64) && defined(__BIG_ENDIAN__))
 #  define MOZ_BIG_ENDIAN 1
 #elif defined(__i386) || defined(__i386__) || \
       defined(__x86_64) || defined(__x86_64__) || \
       defined(_MIPSEL) || defined(__ARMEL__) || \
-      defined(__alpha__) || \
+      defined(__alpha__) || defined(__AARCH64EL__) || \
       (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
       (defined(__ia64) && !defined(__BIG_ENDIAN__))
 #  define MOZ_LITTLE_ENDIAN 1
 #endif
 
 #if MOZ_BIG_ENDIAN
 #  define MOZ_LITTLE_ENDIAN 0
 #elif MOZ_LITTLE_ENDIAN
--- a/mfbt/tests/TestPoisonArea.cpp
+++ b/mfbt/tests/TestPoisonArea.cpp
@@ -156,16 +156,19 @@
 /* On mipsel, jr ra needs to be followed by a nop.
    0x03e00008 as a 64 bits integer just does that */
 #define RETURN_INSTR_TYPE uint64_t
 #endif
 
 #elif defined __s390__
 #define RETURN_INSTR 0x07fe0000 /* br %r14 */
 
+#elif defined __aarch64__
+#define RETURN_INSTR 0xd65f03c0 /* ret */
+
 #elif defined __ia64
 struct ia64_instr { uint32_t i[4]; };
 static const ia64_instr _return_instr =
   {{ 0x00000011, 0x00000001, 0x80000200, 0x00840008 }}; /* br.ret.sptk.many b0 */
 
 #define RETURN_INSTR _return_instr
 #define RETURN_INSTR_TYPE ia64_instr
 
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -813,16 +813,16 @@ pref("browser.snippets.updateInterval", 
 
 // URL used to check for user's country code
 pref("browser.snippets.geoUrl", "https://geo.mozilla.org/country.json");
 
 // URL used to ping metrics with stats about which snippets have been shown
 pref("browser.snippets.statsUrl", "https://snippets-stats.mozilla.org/mobile");
 
 // These prefs require a restart to take effect.
-pref("browser.snippets.enabled", false);
+pref("browser.snippets.enabled", true);
 pref("browser.snippets.syncPromo.enabled", false);
 
 #ifdef MOZ_ANDROID_SYNTHAPKS
 // The URL of the APK factory from which we obtain APKs for webapps.
 // This currently points to the development server.
 pref("browser.webapps.apkFactoryUrl", "http://dapk.net/application.apk");
 #endif
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -711,16 +711,18 @@ public abstract class GeckoApp
                 handlersJSON.put("apps", new JSONArray(appList));
                 mCurrentResponse = handlersJSON.toString();
             } else if (event.equals("Intent:Open")) {
                 GeckoAppShell.openUriExternal(message.optString("url"),
                     message.optString("mime"), message.optString("packageName"),
                     message.optString("className"), message.optString("action"), message.optString("title"));
             } else if (event.equals("Locale:Set")) {
                 setLocale(message.getString("locale"));
+            } else if (event.equals("SystemUI:Visibility")) {
+                setSystemUiVisible(message.getBoolean("visible"));
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
     public String getResponse(JSONObject origMessage) {
         String res = mCurrentResponse;
@@ -1575,16 +1577,17 @@ public abstract class GeckoApp
         registerEventListener("Update:Check");
         registerEventListener("Update:Download");
         registerEventListener("Update:Install");
         registerEventListener("PrivateBrowsing:Data");
         registerEventListener("Contact:Add");
         registerEventListener("Intent:Open");
         registerEventListener("Intent:GetHandlers");
         registerEventListener("Locale:Set");
+        registerEventListener("SystemUI:Visibility");
 
         if (SmsManager.getInstance() != null) {
           SmsManager.getInstance().start();
         }
 
         mContactService = new ContactService(GeckoAppShell.getEventDispatcher(), this);
 
         mPromptService = new PromptService(this);
@@ -2104,16 +2107,17 @@ public abstract class GeckoApp
         unregisterEventListener("Update:Check");
         unregisterEventListener("Update:Download");
         unregisterEventListener("Update:Install");
         unregisterEventListener("PrivateBrowsing:Data");
         unregisterEventListener("Contact:Add");
         unregisterEventListener("Intent:Open");
         unregisterEventListener("Intent:GetHandlers");
         unregisterEventListener("Locale:Set");
+        unregisterEventListener("SystemUI:Visibility");
 
         deleteTempFiles();
 
         if (mLayerView != null)
             mLayerView.destroy();
         if (mDoorHangerPopup != null)
             mDoorHangerPopup.destroy();
         if (mFormAssistPopup != null)
@@ -2810,9 +2814,22 @@ public abstract class GeckoApp
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 GeckoApp.this.doRestart();
                 GeckoApp.this.finish();
             }
         });
     }
+
+    private void setSystemUiVisible(final boolean visible) {
+        ThreadUtils.postToUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (visible) {
+                    mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+                } else {
+                    mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
+                }
+            }
+        });
+    }
 }
--- a/mobile/android/base/home/HomeConfig.java
+++ b/mobile/android/base/home/HomeConfig.java
@@ -163,18 +163,21 @@ public final class HomeConfig {
 
         public PanelConfig(PanelConfig panelConfig) {
             mType = panelConfig.mType;
             mTitle = panelConfig.mTitle;
             mId = panelConfig.mId;
             mLayoutType = panelConfig.mLayoutType;
 
             mViews = new ArrayList<ViewConfig>();
-            for (ViewConfig viewConfig : panelConfig.mViews) {
-                mViews.add(new ViewConfig(viewConfig));
+            List<ViewConfig> viewConfigs = panelConfig.mViews;
+            if (viewConfigs != null) {
+                for (ViewConfig viewConfig : viewConfigs) {
+                    mViews.add(new ViewConfig(viewConfig));
+                }
             }
             mFlags = panelConfig.mFlags.clone();
 
             validate();
         }
 
         public PanelConfig(PanelType type, String title, String id) {
             this(type, title, id, EnumSet.noneOf(Flags.class));
--- a/mobile/android/base/preferences/CustomListPreference.java
+++ b/mobile/android/base/preferences/CustomListPreference.java
@@ -75,18 +75,22 @@ public abstract class CustomListPreferen
     }
 
     /**
      * Returns the Android resource id for the layout.
      */
     protected abstract int getPreferenceLayoutResource();
 
     /**
-     * Set whether this object's UI should display this as the default item. To ensure proper ordering,
-     * this method should only be called after this Preference is added to the PreferenceCategory.
+     * Set whether this object's UI should display this as the default item.
+     * Note: This must be called from the UI thread because it touches the view hierarchy.
+     *
+     * To ensure proper ordering, this method should only be called after this Preference
+     * is added to the PreferenceCategory.
+     *
      * @param isDefault Flag indicating if this represents the default list item.
      */
     public void setIsDefault(boolean isDefault) {
         mIsDefault = isDefault;
         if (isDefault) {
             setOrder(0);
             setSummary(LABEL_IS_DEFAULT);
         } else {
--- a/mobile/android/base/preferences/SearchPreferenceCategory.java
+++ b/mobile/android/base/preferences/SearchPreferenceCategory.java
@@ -11,16 +11,17 @@ import android.util.Log;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.util.GeckoEventListener;
+import org.mozilla.gecko.util.ThreadUtils;
 
 public class SearchPreferenceCategory extends CustomListCategory implements GeckoEventListener {
     public static final String LOGTAG = "SearchPrefCategory";
 
     public SearchPreferenceCategory(Context context) {
         super(context);
     }
 
@@ -76,17 +77,17 @@ public class SearchPreferenceCategory ex
             this.removeAll();
 
             // Create an element in this PreferenceCategory for each engine.
             for (int i = 0; i < engines.length(); i++) {
                 try {
                     JSONObject engineJSON = engines.getJSONObject(i);
                     final String engineName = engineJSON.getString("name");
 
-                    SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
+                    final SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
                     enginePreference.setSearchEngineFromJSON(engineJSON);
                     enginePreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                         @Override
                         public boolean onPreferenceClick(Preference preference) {
                             SearchEnginePreference sPref = (SearchEnginePreference) preference;
                             // Display the configuration dialog associated with the tapped engine.
                             sPref.showDialog();
                             return true;
@@ -95,17 +96,22 @@ public class SearchPreferenceCategory ex
 
                     addPreference(enginePreference);
 
                     // The first element in the array is the default engine.
                     if (i == 0) {
                         // We set this here, not in setSearchEngineFromJSON, because it allows us to
                         // keep a reference  to the default engine to use when the AlertDialog
                         // callbacks are used.
-                        enginePreference.setIsDefault(true);
+                        ThreadUtils.postToUiThread(new Runnable() {
+                            @Override
+                            public void run() {
+                                enginePreference.setIsDefault(true);
+                            }
+                        });
                         mDefaultReference = enginePreference;
                     }
                 } catch (JSONException e) {
                     Log.e(LOGTAG, "JSONException parsing engine at index " + i, e);
                 }
             }
         }
     }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d8069cf7e05fb22792d5fa586999b87723c014df
GIT binary patch
literal 797
zc$@(p1LFLNP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0008yNkl<Zc-rlm
z%}Z2a6vjhBBqT({2oY)Hs+}z)T;$l?x%26Kxd@CPS_D!Qv<U(iE)o@y7NVF^ArVRt
zR)P=&X|;%=^5fr`o+sWz7vWChy?N%E@8aN{J9plBe&?L`ob!$+DwWESHVa?@4g=uA
z#aJLq=7vrsGNl`rllf<{L~g6!$!^1b;`$Try>!yWyUAR+^MLCfIsk<?IGN(@{zUG}
zB`3RA%?K1v6{hi-wkQBld<(q0>Jj)I0v8a8>u$C@0PDl`P&{3jL?k}SbBqe!>!~LI
z#WxSQgX>1rE`&eAz4j{4pG;(mHwnqlAY$JLQ8xexo;P0KhL?wH2QQzOXvEyXO@N(N
z2Y~0|^g2brt0Qv%AP^D>q}RAQfaE<=Xf0^fLRGpi`-V|a17M#2@qQ^EqU<(Pyjkap
z8UVhm?D1S<Kmdv4bFPK`G^+)`(BCr~@I7CLG35Wm?^I0YUugn7F!{e85`b%snzi02
zrcm*gX+~RN0gyT~TnnkRq6WYcD$Pq8S5SlJUrQ;~tU`_KqWogaKz9O)rz5(hnz`9h
zO0^GgwlQh+nKe961xn?YJl(iK6M&txL!tm7Penkj#<5!lJ6vDW?!;0-#wb7_YK;WX
z1?V9=X7er!yz(qma;1xkAr(Hrn^!q?`s94Ccl724W;fQFMkzWCOL2UF_#Yl28(tWs
z)>nF#2Nx$@c!<A`nde?uo*8(8Q#lVX#GLiL0>mKn1>SGMp6J3ea{}gP^g5j2XdNj<
z{H%}oWs2YTd@E02#`6oTG>ilfGJrfM&#3?~mnp)}n;eG&2+{$dczEwgwR8a7R3rhI
z7EBL6;WCLLCC-KwC+q!F0M_)sY{YjEe};=k62PyLNXeAnbRrADQ<9JPx2!T;G|~Vp
zcO268iC>dZA?g4!taV{8Eb`|<ZfI%wM+HF3q7NV<!<Yp)_9<imEPw^D0QMi<7Qh1h
buK>RQCoN`p4?r0F00000NkvXXu0mjf;rL`!
rename from mobile/android/base/resources/drawable-hdpi/copy.png
rename to mobile/android/base/resources/drawable-hdpi/ab_copy.png
index 0dd8865f4a9aefc688496d3f3da1a3a131adf40c..0c8933e5db60945b72443a15206b0e7e2fc53cbc
GIT binary patch
literal 193
zc%17D@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt4o?@ykcwMxZ|d?j81Ohel;vt=
zVhJuNmAS52wCp6)%S#t+KYsbN^tYh5(x=xT%}fb5`*){a-lM9@aFHR^u=`p~9D@u)
zR$RlgbY_PVhsm26L54g0ElXlzh|6DC<->5GUH1qJ!-ols5}y>cBmEd0N*Z<vFfh0=
lyk_{q@?bJQQ2pQU3><I8Cr!Uu^8m<W@O1TaS?83{1OODDL0kX;
rename from mobile/android/base/resources/drawable-hdpi/cut.png
rename to mobile/android/base/resources/drawable-hdpi/ab_cut.png
index c760936ee152c1e85e625404b32fcdb1e634f079..9cabe022de057bba4c2901f8d32118b65823a38a
GIT binary patch
literal 664
zc$@*40%!e+P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0007CNkl<Zc-rk*
zJxc>Y5KUnbQlv;>V<}kJDhO%Rd|bZ2V`C>+2!dcE2!fqhS=dMjf{0ky2tfoTq_C2R
zBq;iK;yiN$%dw|PaFbivVn}YY+{~MOGxP4^>-BnCn*m?|7y$njz>1ao9G5MIBfekE
z0MHizJNRoe01N<y0Ft@t99cM(UkhplfC8S1r%QG5w|J&>jCCylQ1GX?UbS-FSgLr7
zPh4A>@{#8NNN5vffAoE+zgAiP29(G@s{{b&^K{J9BL)xZ_@l`}%g+8gxZhu|&e&^j
zDgeN7fE+)tlUTZVj!X^<fGBb(`lEY3TG{dr-<#-kqXdARrCD-t=?I{O00>}ckkdof
zWfPj|gRZ2y2EbQ~X#nG5q{2KyOLU_SXPJ#p6IrK|+2<rE2f%HRobFQAI?kXFXd+wQ
z0`252llN5C0c@g!3<ZtMyHKKoc1an&5;G3Ud2SM;9a2{BB_LizK-lMLDM7T@q(Ixa
z7ifbu(8(TBd!E)p;5z8Rb%BoM0C3=00GJ6xp{A@3ME+yqdI|t0C=Im>mm+>88lCX(
zJbgi>i333UL+?iam$cD4)B^Sh;;rV`)1*Bc+-gM|#~>?2l7%N(%Ool-xYY**-H@Er
z2h=De23oRG02uS+?Aobi?4cDLP)c-vkP>ZWQUU>@&kM4l#<F1;1OG*TNC+ih8?;j{
z=2+0NW*NblN=-pdhj^lMa<qJ)!5S-4T^=dxJR2bF@QG^_vn~(y0dYR?^RRZWRZvs*
yYZbqFv1I_bn0dW!0E`!a`IpiFFaQhykJ=ZJxhh70199H~0000<MNUMnLSTXrLLnjm
index ed03f620f8ef9e969d0471ab76329038e25c9f0d..ee614d589e5dcf07bd21e43f7ade7d3383f95c24
GIT binary patch
literal 574
zc$@(~0>S->P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm00067Nkl<Zc-rll
z-AV#M7=|Mjk?5d<=%m}|NTN{D-P~5wRXU6=rL!n0$>@jfBZz*~ETgNkZ)k?z2G@a|
zrJapAc-dtgndjNr`M%YK>2#XuSOF_w1+0J-umb;2V53k<Jv;TzBE^xe8!mwG6mgy@
zfgkYpx)+3grd9y%`f{b#yeql&4|g{_G*3Vce@pNa%3IlMJkYf@F~&pzgkK`~8+PYQ
zUSmY?k6zF&;23iR)bLLPzlmc^6OiGr0sfibxA<p{iF*Ly^8|mz;fLSw;Wol+2&4~h
zngGJ*2>ue_U+A$ZBD}r;PMSP?UxF_qyp{llO$x`P;4cI`WkB#1K8K^=i6=l=73Z4p
z4#D?+!-v&4@FL1PPpy29miV46v6x5${v6<k1n(hyoXmx1wV1VY$~&tNxXEI`pGojF
zgil<6A6IyTnM70y<twp1y#5}@L%CB|41}l9ce?;TB6uI+b)($CC?Qu4ArT4hH%}$_
z0O6AtP)qdX3IY-`{0SdB;P4GG_OE}`qXgD)St2JkEx{iH{41+u2%oe-9EqO1Da8uR
zfN$X{r6vH4EK0(w`mLjR@Tm!4<i-TRV+PHI#suF+cvA!-yDMvS0N+7)(*$Nobc=5N
zlRq~52ydc5qy)hqAiU86D1i}DnGnDz;6?1e(^kL=SOF_w1*`z(3;Z`mn%T!Z5C8xG
M07*qoM6N<$f?A^jEdT%j
rename from mobile/android/base/resources/drawable-hdpi/paste.png
rename to mobile/android/base/resources/drawable-hdpi/ab_paste.png
index 886c49317e0b1477bfdc4a4b7601d6caf8649198..0be696557481d253ea906e6b6eb0a33b68ab859b
GIT binary patch
literal 324
zc$@)50lWT*P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0003CNkl<Zc-rlm
zy$ZrG6h<9=ADx`6ZPPzfTdSk9Zz9e<fwLgE`UawdgW&7bUQh}`p=l!5z&9MY4JG8{
zerciYm1Su)5U@gEIGQLCrOUoZ<{KwSF9g*zrZ^9ufS=^sv5-$M%8mrpG-i!Jwd*%8
z&i0>cs%eZ(fOb%oZ-FjzunN2*bRei^7cd0BKvP~rxfrxv7~R`650gOs<Y|K+=exfV
z2xTGMaCTOWhZCgNU|Os>1!(cHBjiIT=as~YO~8$^lkP#K?y(7I?S37lJA;5(AOHbd
z1yl|yIsk#j2<d|kAVLbD0}$vCA#?x&KYWp)0}y}!1R!7(d|rouLGYg#0uX?}|MLQS
WL1h)ZtVA9F0000<MNUMnLSTYr2Y+(_
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..10a4b7432e1001b82afd43aca0b02b51dc41f74d
GIT binary patch
literal 846
zc$@)F1F`&xP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0009ONkl<Zc-rlm
z%}Z2a6vkr+krp8#Nvl?Yh`4g)!kV$UbLaa*#eJJ1m$gX<i55XEk`fV$Xdx<yMPQ5k
zMy*Xyl-9p9JrB&u!=;$H&U?lY?&5{vdhdPD@0|0TbKdK@YPEW%R|F6NL;!&cgF}h`
zu5@8M=I6)a$!z)Ah+kYwqza$oUjAo1Rrr?hi@P_|r4=t*nMxPNuJL{c%N;-}H#!cZ
zH*a|P-wmu^fLR1c|7ioz>)kMBA!sB$53lcxq)Q)a(Kw*tfqM=Skq3<2sQ|!(SD6~x
zD8Rh)^P@!=)%g$D%c)#t63^`GXOfxnYy9neD*<TCC3tpQjDUx~z;M6LhVpC&Jb#~2
zQV_E(1z--#<^WkoG<w2rPQgRq-{n2f(QRu05$uHaJdD3`(i}$AvZ4)EE56GVfP$kq
zrJBHt$!04F%I;Hf2!C4w&|}w?V3(UTUNq4~@7JR6m4Y?{V3SfgJK?G!LB#X&UPjdn
z0D}D}bsnC&=n6pV3Ki<18303Et2`U7jF+CGO6n^!0I3+9Yg_^_@0GTe%mAeMV3YTb
z0XqKzWJ+(%09g0A2}<dnO8^MBPo>avGXSQJ^Z@3qLlNISu5Oh(W&oTX)kc%90N7Jh
z8SOO#;9*3B%#KX)IjBJW@=jE@E%RAO4{~0va<578#yEoOfzBF$9veV4I+BKlkPn{_
zfGIhxrrIq=)EYoGp5mr5MPf$Eg!Me$@kk$RIGMKcKodi~exuL1oFqAzHBvH>Hmllr
z(Ukc(9qgVmgz0GD+6&}ziGs&H7YN0)!?jziHu`KF0>bXA1nahp!(kSWq)Zzc9fW`r
z<~VP$sj*920*J7CylnXihrI?2|HNpBVCiuU5nTN0K?qX-omTLw$B~#{8@M@V8~mPO
zq?rG~XTm_30609<yri-9AlepyUpHuI2#B_ez)T$g4bjnd0Q4-!lrRv60QL|(dO83w
zgIK5oz&Y%PA%HyuMQ;dT55Z3{MgaB@Xq1l)s*oK71<Rag+Ndvr(SIo;fCwN0hyZNY
YA00i7^RVudCjbBd07*qoM6N<$f^;x~dH?_b
rename from mobile/android/base/resources/drawable-hdpi/select_all.png
rename to mobile/android/base/resources/drawable-hdpi/ab_select_all.png
index 902402e26efd69430ebd4ff0d25bf075f475ce73..e7b2b205f3c52212246014c63ba640db68d7e98e
GIT binary patch
literal 199
zc%17D@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtK2I0NkcwMxXYS={FyLwV9pLBp
z=)tqszpXy<Gb#Bw>Z#r@aL%0lDX@=w$;`;>Oh6qB9y|uRugkI|o|k!STgP1>erdJN
zfydsgpT6&AKENDmQ}DK4v*26la-9ZoA;uk-m>)3O2(T!yzi55YdV;a2LFNE+g#v>E
s-v#cA+z%VCFq~n3!f@sU$XtfH%X|!ldkeIr#14YEp00i_>zopr005#z?f?J)
index bb6aef1d069a14a7fc1cea9780c919c61679e4fa..6744de04390f846457972a4c699f2e0f9be5a33c
GIT binary patch
literal 144
zc%17D@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezt=sPZ!6Kid%1QEaYWS;Bj?qb5i7F
zJKo0=WwzpwgWn!Tzdt6KogK@W89-pitr^+rj3Cw@-W6+?GcrgRf;bJ{JP8m5_g;gk
Z_so1to1;9Gu6K)qxSp<lF6*2UngHmZB>4aU
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4af976e251efe3f002feea608d7b77d3d750217c
GIT binary patch
literal 569
zc$@(_0>=G`P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800062Nkl<Zc-rlk
zJ4*vW6oo}3h=quVAQo13Vx=Hybo1D3ve~>-SXwFASct8Hf`x@(qk@ePBp^P(2O_=|
z6j2Lbe<z+pW(q^XuI>;mwzy<AOy+#&&b>EDL#b5y)9?UnHw^d#-@>qRL*ZC@Ef7iE
zX}a~MMH0_JBYB{kndxXE-^x8T!W{q(_d$4NM7KU5`iS*9L}zs~y%>z9_Qm@ThLzP-
z15ms%6isbW1fuhJZmE))L1f|_S$V}etP~&;&rCr4Q;%n+YPgf2?ExcsiR-y1q%r^;
zdJA_)T-ycQYlJ1V3IMpu^_36IjynL5z}L94q7ncUl|=wJ^E(BAcmWwZQw3lO0PP0=
zMF5<tx`G}8p!#Q=h_hqZj%d>jWkm=#$1Fq~-fRbeS{V~HlUD}7;lddJSF3bbOPmD@
z_fG&m;XYLWbTx_r^G;{D-)#u>SESv?E`j(<c?RTq-3}ri+KDl{fV-cgdy#=<&VGV$
z;IP;bdlVLMyAbboJ&JKi7u$%3GWey#EC{!47&4QgSZWh{4hax8(@VIfVJYMafDYj9
zN{UMWIa+PP9ROPn;x|%Q23^XcauWQ^uK+kgtBCK|xK{?ie!r*?FUsDp3jpUme{2Zx
zf)uY8fNZ}G4j#NV@wwgrmElOtX}ADTlK~IF1MvPE{!4%_G^x6rv#tJG00000NkvXX
Hu0mjfFwO2P
rename from mobile/android/base/resources/drawable-mdpi/copy.png
rename to mobile/android/base/resources/drawable-mdpi/ab_copy.png
index 74cb920f487b60595b896c04ebc6bdf9dbd746ce..ac097fa93a6caf091945332f94c0ed25230e04d5
GIT binary patch
literal 166
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJTu&FrkcwMxryFt|P~dU34N+Hr
zdExBq?^c3bijuDadjD|MS7cZG2uKnV)DZcx-eKn}+rtyjKe-WffUTBMC&7i=NBw48
zf(0k*G|oMxX-pMN{K5x>K8Uq&X>4fsaGcZdiD#k10jDPM2j@GOY^7F}PDo4_cHalI
On8DN4&t;ucLK6T7&^ZnO
rename from mobile/android/base/resources/drawable-mdpi/cut.png
rename to mobile/android/base/resources/drawable-mdpi/ab_cut.png
index 8e6a93fe4fd079ccc034d09f86ffa37a2e9e2f5e..4314e82d1588aaef6809b2898a5c9924a0354561
GIT binary patch
literal 459
zc$@*t0W|)JP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80004!Nkl<Zc-rlk
zze~eF6vsO_h=YTJARQbE{sTG%2ODjYrcKhO&7j~QI0){7|9}V%g1CsdiHM_!Lvaus
zEQ$yg{deN`i+2(*L)-jlg&Q8Z>s{aby!*a;O$%Wdj?@&u_yMdK&Q}_?r0Ini`$qs`
z&MysQ3Sg`Ns&0FJ)$(pR$MfED+FHf{(il9LM9_|Ic~6$p@(6<Q<In)0UpDLhF0v~1
z17Otr1NvF3Hm(U%v75(b(|sEnz^u2{nE}_B%@0g46BisA+t~LRy_RLe>A}ZlA_)+1
z0)cmsNmn@iK!%ra>~l@%Uc&n8@4DT%!1@+GpG&I<2{MHv-bbK!xt~FC%qP0(K68%o
z8G~ke3n)RQ);waS0C?f)5P*8iJ$V2e3V?0|;5<tJDZw7ATJGl<fls9b)ILsvw2QEZ
zBD_M81(6~wQjVA+EG7bgla0tVyc5@Ow%=>WIecs<X+#=>;<+$jBf0_Tv}{Cqx8euU
zif!47bNw;mX;CgI8|I7ZePGl8>aAG)Gg1J5>>Crd|KuZYy@~(;002ovPDHLkV1jr^
B%+3G+
index b28b3b54f4c81d482f797f31936cbd4013c093b5..bc87b16277f14ff00d2c24dd279b6113a795c1ea
GIT binary patch
literal 442
zc$@*c0Y(0aP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80004jNkl<Zc-rlj
z%}T>S5XVKNc<|s=iin6$pdj>6Xw|l{rZ)Y!>Dkw?C@NLdhw#u^{CWfLg6$in^KW-x
zVMy1wZ0sS2VL~AD`|a%Pl7%n~|20y9RABxEc5_AR@M`TviY4t`asq%O@SL~+ue##5
zcFM=iQ|AH_j@;Vb_v)X8a_xsi^4t|S0usJO@DIRC)y4(D4m%*>2VVW1;cjO@!Z$T|
zM+~F2fEoU#;Fl6^7MOg%5fi>a@Yg9kxcc)kL_vxbmiZ-oUBQR6@@oM%2`~(q&g?lA
zd%=n{hzUNJ!h;(Dk1KFk4Z4MrKSEIyXIKP03t7PFyW6Pki+u{vMifO`^-j!ycTMnE
zLpVbsqu^`wzOUeS0&Xk75}0O8HI5c87j5Oe3H&IykAhomfnE^jS#@GS_xT>>XUqt}
zAFv$)ZY>}sxD(&S%E=cp!Jl{*1l&Tv)QJwZgW!(>?n;0mDlgL=aYlJnz+DO;7%0HW
k2*?Y_GSc7jRA7Dt#!u1eMKY>%JOBUy07*qoM6N<$f}JkNng9R*
rename from mobile/android/base/resources/drawable-mdpi/paste.png
rename to mobile/android/base/resources/drawable-mdpi/ab_paste.png
index 61fd91c8808a6cc1c8bcae5d7c5db8305c92bd44..f87d274e4c9b124858558ce30764fcef71701935
GIT binary patch
literal 249
zc$@+G00#ewP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80002MNkl<Zc-rlk
zO$x#=5Jp|N@;t6wX|QQcY5F6*N%!Ifyn&~2;X<T4uM=msrEP+I(o$yeAY=ySWrhT@
za?VZ4`~|i<)k~6{jY{$d!)x9f0WY9p`=r7-!)v&}US}U4R9rJ5xflUIc!6#!by{7A
zicsv*&4&q`Y`vxe%^|k0ApwfDEJ(Q<xIkpeTWGtFrntie=ydN;0qz7;;1`xB(AVlQ
zNg2VPN8m?BFv$qy7RW;+0?QLXFna;{8;ZaeTWULgcV@%J00000NkvXXu0mjfRxoB-
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..022e173c4a239b83e17f4a5551fe00aec37b67d8
GIT binary patch
literal 587
zc$@)C0<`^!P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80006KNkl<Zc-rlk
z&npCB7{@mU2T78WlcXFZIdGA}F1s`A%&y&aQEm=O<e)^!K{+}ge}bDLxk}{cTKUoX
zch>W%cWP*V&AhX5*u&GzzRmkSpXdAhc-v5+Q20};1N?6Q)1GUJ##3t%GkG=<v$Nw-
z>r0-m5hHOKok?w*cBXS^Bpj;JyaB}G>3MPXh*RbGSsY*eSc_V300s^q(QSx>yg2xr
znw~w7NC(^p$?qQdW)}cJ_$DX-BG2F)$qg$rTIN7N`ol)z1_%LK*9IWxNKE90l^$cQ
z(xC#`Cwp?T=R@9mH2{b{wX7uFS8G+}mgt>*S^$$~@|1(fxd#B0YZe9G!!i3#3xG-|
z_q=-nz@$SifG3T<0VqCN%?AMLohbFXbri^oj1RsPFq7v>fi~X&j*RrV#~Ns4LIST-
z161>->ggR10L+d>)dk18bD*6_m~ixTH2~ZPL{9z4`=AzpdltxqyQZKjIPc(MQqdm<
zb{BA%x`1+W*{q5(Ex&UvvM)&F_pZz8MN}IO0ssdMQU_a%R}SY%q_i4^N}818JbA~t
z10f2o$lg6sr^`2hV;sVGbw`Skb6G!fa!%w91g27WOA2)WFt_Zj6eiDN@;bFs6ha@M
zvLQQ8OF`5efOO%k97Ih4Fr1Wv;EvG%(1xHxo-_dTA*4u`GywcTAUiFLb6KnZGpYj=
ZwQpyC2@&y{><$0`002ovPDHLkV1hXx0~7!N
rename from mobile/android/base/resources/drawable-mdpi/select_all.png
rename to mobile/android/base/resources/drawable-mdpi/ab_select_all.png
index e0dd67c69445979727fc9fdec76c60386524ba92..147044bc6b666349830aaea6b126dc7872dcc3da
GIT binary patch
literal 157
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ6i*k&kcwMxr(1I|DDtq{PMJD2
zB4_*c?^c0t%vg?`pOn_67~vwv%&F4Rq0REc=F{h}*krBn*P9yeRZQO5xSuH@;rfA$
zO&8>&Wuz?l8yI;uu;1Y|V3jz)P|d*1_OG0Axg?_r??hS79ZR%#L;&q$@O1TaS?83{
F1OTglGY$X%
index 01d681697f799729aa60bcc03878b8718ef5f705..b8e61f95830c68ba094af6ea5d48e220156fd532
GIT binary patch
literal 128
zc%17D@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzcTX3`kcwMxuP@|fP~dTOY;#iN
zWINu+6D8)5$no&VWM99(OEi_%u`v{sT=_L)Hv_{z#wS7B@3P%sWMHsPU}s=hwx8jF
a=K-dCC7Dgm!jC}aGkCiCxvX<aXaWGDtR|BH
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c371418315ad90566d2441fcecdb3021bd7a6a97
GIT binary patch
literal 1028
zc$@(Q1pE7mP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000BaNkl<Zc-rlo
z--}IA6vs75k|c@bK@v|=LL}kdnfv?qoih)V2U3)#D9zK9G=)5%NG4G-`BfxEGGxM_
z#?LY1-?_fuhdoxiPP^-#qjk^hht-U8_Bm&NKYQ)H*IL^wXti4N+B^Uczyt6AJb)-{
z`|h;U3e{j;w$wb;SE!Gr^R;)WY~{!PY~?q9;@|Ia{XXuWM!St{--hW1kgo(gA?_Z;
z&Qh?;*beO<<tzRBx*9;CI<O>DY+Mc#&XG^$s$cPQCJY3gzk&BG>ox#%_qDzG+AB-&
zufAgaR<7KCfcNe8xE?_8DBAs$&tZDJ#r+N10Z1`xILD<32)oHOAWVS$JlbEAo|Dd1
zKjHd%?EvWZi!k!f#i&nXWDoLQyN2iLW}&3vy{|c~R0F^&epb3X7P6v4sA~b;%PAo|
z>5^IibWx7D>1?jt9PB{6^n^olVZ?Vfs|3K&5$^g7?%KoaQCM%G{#1Cus5$_g``FT^
zOef*`*$9Nosjx?GpWGTX0bmDHV#WTzPDO3-s&VrTE|97KFoYE@dOZ#RnNs7T`3Al>
zq6z>+UzzJ%xp^`U02uWn<{J#CQ~_XzgnJ&22|#lWK%xFnn+IGK0FK54U_byE)3yeT
zi1~RY4ggH0%{K^K6#$02wtGfwoMyM>I-@KO2v(cqg`q3<>E%(1$NLsDb^aS?1Y6Zb
zf{gyeG#HA>{h1z5s0@YWBE`{SS{u>muV9oZ-CrdD#{MjVh_&D`t}X0Pd=K7pS45eU
zOo_DtkTLr<rol2`A%uSwFSb|OEOLwz?`a0G1Md1wR)d(yg;#^Zt3upO_`DtdY6U>?
zyEym53ZN7~VUAH>iFU&_L>5=I)dbnur7VKbRhh1`)3#{Xv|Z_?M`TNl^C*}cXR(8e
z8bqJNh(F=<vEDIbb`(_rFc)hSY|>x+{#|yQ_Xq`mwwUd)UBh!P=vC^@1-RYWBV~#I
z!ov`&ppn6Xc*ibz+s6086CMz-sVJ!ez>wD=e#(y0?86emfcu|d&cGZWc7fA?RU~_h
zQw4x&uH$%%06urR_iF?|@yA@^MV!7VQ2^+!F7YB#`^dy44w3RZ{|x}=rWEgXe_6BF
z4<It}9C_pVi2)$?c9-}`^Pd_L1%M~AF7Z4CHgSI905EoUh@arOKHDY|0D}^Qqc20k
z)Hh6Q*e;0xB!pEgY*^yQd7bx@4nQV9C7%BB{GSC+UYkDv+!l$rsLccL0Ad8-*8mT|
y1MmPm01v<e@Blmj|2IP(fCu0KcmN(i*V-S5DfJ6ivwpt-0000<MNUMnLSTZ9c<u54
rename from mobile/android/base/resources/drawable-xhdpi/copy.png
rename to mobile/android/base/resources/drawable-xhdpi/ab_copy.png
index 364b1692f3eadd2b28e8dbf3d3e83aed90b7ba14..efdc62d52f0c1cc0406df4d1c98efd30efc67cad
GIT binary patch
literal 251
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=hdf;zLn>~)y}g&~kbwx>g>!v&
z-IFI<Y4DZ3E-rul+J(iDrJeiMy(@DbMjN#<$JZ&m^wRWYXMg~K^ABrg8*RQle-}R^
z&|IMd#eWPtBa8NYQEp&kIK&uW>F`U5lYyaO7sIo-KM*YqqKq!zK7}&I{7$@Vb>Q1|
zQHBru8SdW~Wmv(`uuY4>ftBG3{{sykAgxm<vQFTEC<Av0P!~%>21vKU<3<)Bb??z(
d7N`>xW?4UH6TeX#^ZP%D>*?y}vd$@?2>@tMQXK#Q
rename from mobile/android/base/resources/drawable-xhdpi/cut.png
rename to mobile/android/base/resources/drawable-xhdpi/ab_cut.png
index d4e4d81f367d31034dc364793a430f63c7bd19db..b92aed3759a40191c2a9e2bb44fd7882a32376c9
GIT binary patch
literal 890
zc$@)x1BLvFP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0009)Nkl<Zc-rlo
zJ8KkC6o6Bt5DSYGg4kPx6afW61kEOyePrKR3k3^7&`J<Qu#zB%AS57yg#;`_LO_%d
z1Vuy?F&HGGjDKf6AIyczWgZS1XXbi}!z431JNJC&eJ7b1kH`PDC;$bZ02F`%Pyh-b
zS<VKXpJkF0r)m>1q5u?t0{BM&5<bTw_C*wc0#E=7KmnuxXm&@l3$6Z>xqA02*K3X5
z$6#rAv)Mg&z<U6V&T=ppbiT)x%Y|nD1rWRiAj%yUtM76yvit`;L4f=)=fo3kR1`qA
zEVc#@&6?!r$7UUbgh2QfL3!^X09=1`Qq~fhHAyJ+?6rvdKj%E*Q3L?obF$uEz95!a
z#SL-SzX@Qz(c5M%maE^fJm83g#ut+i3jrXpxNhHrC2&)*)R{k3Ucg?8OM1k=fVhp)
zHkiUZAZQP-i6!>j`^9>1xh9`ElvjD%x>>?=ct)W)0M|Fk$`uk7*NEre1VC(WWGPNR
zu(&k1hw`QA15lE<O|jN1aqY{p=z~e$A?|!D<^FBCzCvGs_m#F2B!0z0JE_)d4c5ff
zXPo=4n5=IL*<RotuT(3HYl^k*(y*k)aI^nX6u($+53jn)Q{S<6m1hCMVmd3Pld?Ub
z;>|Eb6GI#8K8JIX%<gk^`uj=mra^`lCOFf=5+0^`;uwWXh}U>I4&&0~1#7YkZ2<g^
zP))o8K%%SFyPw_X$hl8c1devO!&|%nz|<xRZRJja&HgjDi>z81oD$1Ea7$ZUjTi4Y
zANBsBn;=P^l><Ocr`btqgm%gN66?oe2B0vmS0FEx9RM}|w7C15lvZ|&T#yvs2vs6&
z@F9tcSF{L^vH&2?k1_@)SbHyOduMYDLr)VRxI@+&)uS)~rmiQ9!><Vi)6L}(lu8?i
z-FCUKaTu$|SmhD%x=$M-A)7Ejw>wA1;vxW;g${|!X!Bz#m!jFBu<2}xtt4%U`MN1O
zO?#YUQ`F0C@l|U=T(>-6hLDT$%{$*;jO^I0Ga%?QtkAgb`Kz(fys@?`<O#1|jTyn^
zsXAt$qT#~w>>KFoaRs0N6o3NIKa^Ae3P1tqKTIe91)u;FfC5ke3Lr*)0aadE2HvCB
Q)&Kwi07*qoM6N<$g6V;ec>n+a
index bb19810bc2062509e4e4968099a359ad73818728..6160d99f34cf142e33eb07607e14814ace2a0400
GIT binary patch
literal 804
zc$@(w1Ka$GP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0008(Nkl<Zc-rln
zZ%Y(W6viWZAtJJf6cW*w2m;@=rMv33+O82n5lCSeg&`C{A0Y@#Qn4Z`tmq?D{wZDS
zQ*GygJ8*coHN=cFc=o(F%)*@=?(g@UnYnk_W8H4Ir^^Mn02kl_T!0I30WQD=xBwU6
z0$f0rIyYJ^wUT*EG_M}-RRJWShXe#*98c6Q&z>g<z0(2XQ>~}fT63?~XkRzm0h~Na
zJ_G)Vz;~+k>0Ojam_tWk+^hfv|5)G;1bq8qefs-_TJzV~<dtU_w<RDQehZ%k{<)0z
zS-b@p{!s*eS;qV6L1;ukI{XVHZ}Ba_@DK68Blr~=AF#I$VE9IBDFXkJ+un)*hF^@q
zbMmGH;9dR?_*KB`)u0stocx0b{F;mp61)KcoO~R9T_=xYQ3C#E`%sdvHCp!sct2U;
z1^5jaujuoN5Ww(Uxh7BWI|}}lZhIVy5}>x6v!^36@=pG43_g~8p&cN5?J=3qSJ`PT
zB>Qg?kU4o=o8d1_&b(px0tD#f0pFeiJoejR&pofkb4tE_2iK0k4-tH^0+0?~JF?CE
zEff2O2_hxk2{|M`AAx_%@TCX{$6=Y!YfKCi3=;Nmzb5BpfWMsqzR<V8P(;E$p4c?e
zZ158^?_~TWU9&U++zFKo5*U6?zW*}<KdjFySwLI@UP~mQgH>B(;%V@^3jRGOU#@_3
z2^&hncIbrr1Q3J2MadI92`o)Ox`e?XfjeQ5BrrTD|3Ma5BlMj@1!V1n^&nvjoxl<l
z{0$lZLGYUbe@aU#M?m&YSc^zl!sG({O@i+T{6{RUDftow<S*d>izTUR-1Y%}gpxlx
z0$4%-86XKeA$3mv6DNO^1+WBk!m5@)Py5e+*U6g@pwh&#A3s(m5>QA!z@Me$%?Lp8
z?XUuH1%HN;Hz$B4^x>Hx@LxE2%K}(Jg%>&I1#l6(eE|%9$nYrto16=90WQD=xBwU6
i0$hL#Z~-phzv>TQSm5Dw1$~GB0000<MNUMnLSTa0re4(m
rename from mobile/android/base/resources/drawable-xhdpi/paste.png
rename to mobile/android/base/resources/drawable-xhdpi/ab_paste.png
index 6edd4b222ef06eeb46acd9c90ff81bcee1df867f..e82c6651613562a982e14fc344e5a906bc25e7d3
GIT binary patch
literal 427
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU@Y=<aSW-r_4f8gufq;9#|!5l
zI(qP+uMCq_r?c>FwXG^!Z|n<}KcKF$bVtVnW($p`?g)(^RxkgXa}*kF6W`&z|1f_a
zH}B8-b^lNEzIBY8RxJxOdO^vg?$b-k*p5EgVZCGS@yw44GuBwf-ZnbOu;PcY_OH#C
z&+lJ-aZYS^6o10%y#WWW-+W<tT0Ok$*sRUjr>`;J@Ty-K5&d@Ye9K-_@$a9ferKo(
z5MTLi&#`syq`4aQz3Y#vbbWk);SPI40OPBirfsM9|Jg23yX@Sv=e7-dpPehep|N-Y
z<C+HHy|;nP`J4XaNeDT7UGe+Ds`Zm|zAR%7W?;~&t6ITcws+@ChE$H__n5!5J&p{v
zu6dtU^WL^$?Z50`2G6KH)%*$1f0hO_?ArdE;Ve7QQw#^P8*=$A87?p}Y}v?qhn*pc
zq2b$h28JyR48N~3frJbAerSVeH~<EYDkB3!L)MSWA~3N4bLlsq-Ux`UtN=v?gQu&X
J%Q~loCIGw_w@&~7
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df2021160da6d23a7173015ce5c285e945516ff5
GIT binary patch
literal 1104
zc$@)H1h4yvP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000CRNkl<Zc-rlo
z%WD&H5XXyn2qHy1C{jeEc=4p5C`H6R^0Z0QG(89gsUV1=SQJH3P!PR{iUmE0q9URc
z@t_t|f*uqf@m=D-6Te?*U>uUBn{0Nr@pl+nHtFU!pLtKVU6o4ZzZM6;0dN2u00+PU
zXi<`x@s;u6v59DE^yXk<WTro!`O+Ut&+dw)%lQ2pt`&z;+555GxyfWEzhO(?K$p*A
z10a#kZ>M5&%KllPlmX-=fb9XeC5sXOtk^@vsSK5BRsiA+AnsUH0ARTs+`3dxseyRr
z!%#9i4M2A&`2E>HV&v^Su*wLH^Yn($1Beahj@42G3ckZ@$Ke_4>m3jZt^m9OfIO`Q
z0@oklJ&~{ipz=rcq2URiq0~OF)}!0Q{a@99@EG@68ae<_GOI05OX9Grs_*f7U@8jN
zzohSrN^;d2fKGU8Vd<~(kcjQOR6xA1+1Lf#+(8AQ4B+|D0D!Xhl;x*|@+||Pz!T1?
zMEVh*vD_K}W3`VK5i$P>9<iFQ`3ZnI1Yn;?2!L|N8~`)3JQNciulo&v0<gVksD8-=
z%c@`ofMtsvo-B2=RJ#CBkN|He;CV9uw6=1|6TIF=0Q7=Qsv_Jr1Hi#X9)?X$y8%$>
zX(AcEHv_<_PPVta761T(zx6Np@op0U?Du8q3km>2?UV$7O0?Mo0282Wd;$W%+_PT+
z7&HOE`Y)4FfB+^GfT&dnd>0|`C@27W=;GjHl?01oaZwB~30_gvr^f^UH$HMeVPg~o
z0IthKH&`+&gIs>7uB;G1BeaIFW$2j!K<sVQ^MAVm=n}|L*>o6^?nujUI&2pJj=vm(
ztDlE5{G01`Qvh)Ly=sd)BX$8&e6arLWi<y(nUBMq{-E@0c`zLGqTc`#>9LrMeU8PP
zJ*)ueT(Gmo%Ibhm0C@kc$o4<<G9*+>Q5@((ja~j}u^(vK^3{e*mOk8fS*QRo?!|6U
zt+DgHUI9=+#=P<@y&jKP1JDp6a&ITIH4@f!E;ANV=ixagWwzI%A(#Wuo&aU9Y0JsA
z8RvO!k2uso3T&v@-m;|1zte8t2m;};R9XSh<uNa;*t9VDq1ib?C8=zkFHoOzGc@OI
zvjl1mfWkOtw&t?{9+Z}0GX<-zt12KNG>|gChcpGCa|1nsI|HuH=CO8(3gW$obcfdh
z1bYCw3{pAPc1RRuE`^`l7{4AWL<DaC!UKfR0PszeCpCo7Q2_Xjb5%hv5IPA!H?w^J
z5JDRQ;z<<m5IO<?h0Rp65R3uXL*ORK5P&@d_8f))>>(hD{<H&N4}n9}Lkj?=5cKla
z2!K5VynfcI3Yb99kK9`J0f7oi-C;hz$b`q3r`x-Km~a3b00+PUZ~z<t2fzXFAb$aO
Wh*}oKi<B<_0000<MNUMnLSTaWs_oeT
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..614afe56e2508397d1cf650b678e5ebb0e5d6e71
GIT binary patch
literal 233
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=8$4YcLn>~)y=}<VVj$w+$e)_3
zDpnSE|Fug{hJ%5GieO<E|Li11zCAjPTe%hgR55@-L$~Df)ZXIsyZo0o_RW`Gzxg+F
zfOVtngQF+k@gBI$vX67ZH+}~u1{DSermGB-%1+LaTkzwz@A-y&rX{wF6Brmc86ZT%
y=?Sk57&t9h{_-$k3PX4w$}1V-W-@~9{Xd&`eyge9di}>?Ag-sYpUXO@geCy`1xhdg
index 930ca8d95e8bee5a1240fba645d9dab919abd734..9c5156cfd39c9ae0936beb6821ff0aa9c5bfd77e
GIT binary patch
literal 179
zc%17D@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Rh}-6Ar-gY-cl4}5D;(;?4IP}
ze(}vkr{iKQT;_Xt?|f4C>FQX|%zyv~{zl0ct0Va98J`4gX9BUbkrZk2fT%EpNQ1j4
dk|7K-8I1dO>xulk?s^i$^>p=fS?83{1ONx(CE@@8
--- a/mobile/android/base/resources/values-v11/styles.xml
+++ b/mobile/android/base/resources/values-v11/styles.xml
@@ -76,24 +76,28 @@
         <item name="android:textColor">#FF000000</item>
     </style>
 
     <style name="GeckoActionBar" parent="@android:style/Widget.Holo.Light.ActionMode">
         <item name="android:background">@drawable/ab_stacked_transparent_light_holo</item>
     </style>
 
     <style name="GeckoActionBar.Title" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
-        <item name="android:drawableLeft">?android:attr/actionModeCloseDrawable</item>
+        <item name="android:drawableLeft">@drawable/ab_done</item>
         <item name="android:background">@android:color/transparent</item>
         <item name="android:paddingLeft">15dp</item>
         <item name="android:paddingRight">15dp</item>
     </style>
 
     <style name="GeckoActionBar.Button" parent="android:style/Widget.Holo.Light.ActionButton">
-        <item name="android:padding">12dp</item>
+        <item name="android:padding">8dip</item>
+        <!-- The default implementation doesn't do any image scaling. Our custom menus mean we can't just use the same image
+             in both menus and the actionbar without doing some scaling though. -->
+        <item name="android:scaleType">centerInside</item>
     </style>
 
     <style name="GeckoActionBar.Button.MenuButton" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
         <item name="android:scaleType">center</item>
         <item name="android:background">@android:color/transparent</item>
+        <item name="android:src">@drawable/menu_light</item>
     </style>
 
 </resources>
--- a/mobile/android/base/resources/values-v11/themes.xml
+++ b/mobile/android/base/resources/values-v11/themes.xml
@@ -48,15 +48,15 @@
         <item name="topSitesGridItemViewStyle">@style/Widget.TopSitesGridItemView</item>
         <item name="topSitesGridViewStyle">@style/Widget.TopSitesGridView</item>
         <item name="topSitesThumbnailViewStyle">@style/Widget.TopSitesThumbnailView</item>
         <item name="homeListViewStyle">@style/Widget.HomeListView</item>
         <item name="geckoMenuListViewStyle">@style/Widget.GeckoMenuListView</item>
         <item name="menuItemActionModeStyle">@style/GeckoActionBar.Button</item>
         <item name="android:actionModeStyle">@style/GeckoActionBar</item>
         <item name="android:actionButtonStyle">@style/GeckoActionBar.Button</item>
-        <item name="android:actionModeCutDrawable">@drawable/cut</item>
-        <item name="android:actionModeCopyDrawable">@drawable/copy</item>
-        <item name="android:actionModePasteDrawable">@drawable/paste</item>
-        <item name="android:actionModeSelectAllDrawable">@drawable/select_all</item>
+        <item name="android:actionModeCutDrawable">@drawable/ab_cut</item>
+        <item name="android:actionModeCopyDrawable">@drawable/ab_copy</item>
+        <item name="android:actionModePasteDrawable">@drawable/ab_paste</item>
+        <item name="android:actionModeSelectAllDrawable">@drawable/ab_select_all</item>
     </style>
 
 </resources>
--- a/mobile/android/base/widget/ActivityChooserModel.java
+++ b/mobile/android/base/widget/ActivityChooserModel.java
@@ -26,16 +26,21 @@ import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.database.DataSetObservable;
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Xml;
 
 /**
+ * Mozilla: Extra imports.
+ */
+import android.content.pm.ApplicationInfo;
+
+/**
  * Mozilla: Unused import.
  */
 //import com.android.internal.content.PackageMonitor;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
@@ -253,16 +258,21 @@ public class ActivityChooserModel extend
      * Monitor for added and removed packages.
      */
     /**
      * Mozilla: Not needed for the application.
      */
     //private final PackageMonitor mPackageMonitor = new DataModelPackageMonitor();
 
     /**
+     * Mozilla: Count to monitor added and removed packages.
+     */
+    private int mApplicationsCount;
+
+    /**
      * Context for accessing resources.
      */
     private final Context mContext;
 
     /**
      * The name of the history file that backs this model.
      */
     private final String mHistoryFileName;
@@ -727,16 +737,25 @@ public class ActivityChooserModel extend
 
     /**
      * Loads the activities for the current intent if needed which is
      * if they are not already loaded for the current intent.
      *
      * @return Whether loading was performed.
      */
     private boolean loadActivitiesIfNeeded() {
+        /**
+         * Mozilla: Hack to find change in the installed/uninstalled applications.
+         */
+        List<ApplicationInfo> applications = mContext.getPackageManager().getInstalledApplications(0);
+        if (applications != null && applications.size() != mApplicationsCount) {
+            mApplicationsCount = applications.size();
+            mReloadActivities = true;
+        }
+
         if (mReloadActivities && mIntent != null) {
             mReloadActivities = false;
             mActivities.clear();
             List<ResolveInfo> resolveInfos = mContext.getPackageManager()
                     .queryIntentActivities(mIntent, 0);
             final int resolveInfoCount = resolveInfos.size();
             for (int i = 0; i < resolveInfoCount; i++) {
                 ResolveInfo resolveInfo = resolveInfos.get(i);
--- a/mobile/android/chrome/content/SelectionHandler.js
+++ b/mobile/android/chrome/content/SelectionHandler.js
@@ -400,63 +400,63 @@ var SelectionHandler = {
   removeAction: function(id) {
     delete this.actions[id];
   },
 
   actions: {
     SELECT_ALL: {
       label: Strings.browser.GetStringFromName("contextmenu.selectAll"),
       id: "selectall_action",
-      icon: "drawable://select_all",
+      icon: "drawable://ab_select_all",
       action: function(aElement) {
         SelectionHandler.selectAll(aElement);
       },
       selector: ClipboardHelper.selectAllContext,
-      order: 1,
+      order: 5,
     },
 
     CUT: {
       label: Strings.browser.GetStringFromName("contextmenu.cut"),
       id: "cut_action",
-      icon: "drawable://cut",
+      icon: "drawable://ab_cut",
       action: function(aElement) {
         let start = aElement.selectionStart;
         let end   = aElement.selectionEnd;
 
         SelectionHandler.copySelection();
         aElement.value = aElement.value.substring(0, start) + aElement.value.substring(end)
 
         // copySelection closes the selection. Show a caret where we just cut the text.
         SelectionHandler.attachCaret(aElement);
       },
-      order: 1,
+      order: 4,
       selector: ClipboardHelper.cutContext,
     },
 
     COPY: {
       label: Strings.browser.GetStringFromName("contextmenu.copy"),
       id: "copy_action",
-      icon: "drawable://copy",
+      icon: "drawable://ab_copy",
       action: function() {
         SelectionHandler.copySelection();
       },
-      order: 1,
+      order: 3,
       selector: ClipboardHelper.getCopyContext(false)
     },
 
     PASTE: {
       label: Strings.browser.GetStringFromName("contextmenu.paste"),
       id: "paste_action",
-      icon: "drawable://paste",
+      icon: "drawable://ab_paste",
       action: function(aElement) {
         ClipboardHelper.paste(aElement);
         SelectionHandler._positionHandles();
         SelectionHandler._updateMenu();
       },
-      order: 1,
+      order: 2,
       selector: ClipboardHelper.pasteContext,
     },
 
     SHARE: {
       label: Strings.browser.GetStringFromName("contextmenu.share"),
       id: "share_action",
       icon: "drawable://ic_menu_share",
       action: function() {
@@ -465,21 +465,22 @@ var SelectionHandler = {
       selector: ClipboardHelper.shareContext,
     },
 
     SEARCH: {
       label: function() {
         return Strings.browser.formatStringFromName("contextmenu.search", [Services.search.defaultEngine.name], 1);
       },
       id: "search_action",
-      icon: "drawable://ic_url_bar_search",
+      icon: "drawable://ab_search",
       action: function() {
         SelectionHandler.searchSelection();
         SelectionHandler._closeSelection();
       },
+      order: 1,
       selector: ClipboardHelper.searchWithContext,
     },
 
   },
 
   /*
    * Called by BrowserEventHandler when the user taps in a form input.
    * Initializes SelectionHandler and positions the caret handle.
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -261,18 +261,19 @@ AboutReader.prototype = {
         this._scrolled = false;
         break;
       case "click":
         if (!this._scrolled)
           this._toggleToolbarVisibility();
         break;
       case "scroll":
         if (!this._scrolled) {
-          this._scrolled = true;
-          this._setToolbarVisibility(false);
+          let isScrollingUp = this._scrollOffset > aEvent.pageY;
+          this._setToolbarVisibility(isScrollingUp);
+          this._scrollOffset = aEvent.pageY;
         }
         break;
       case "popstate":
         if (!aEvent.state)
           this._closeAllDropdowns();
         break;
       case "resize":
         this._updateImageMargins();
@@ -496,32 +497,40 @@ AboutReader.prototype = {
     // Don't allow visible toolbar until banner state is known
     if (this._readingListCount == -1 || this._isReadingListItem == -1)
       return;
 
     if (this._getToolbarVisibility() === visible)
       return;
 
     this._toolbarElement.classList.toggle("toolbar-hidden");
+    this._setSystemUIVisibility(visible);
 
     if (!visible && !this._hasUsedToolbar) {
       this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
       if (!this._hasUsedToolbar) {
         gChromeWin.NativeWindow.toast.show(gStrings.GetStringFromName("aboutReader.toolbarTip"), "short");
 
         Services.prefs.setBoolPref("reader.has_used_toolbar", true);
         this._hasUsedToolbar = true;
       }
     }
   },
 
   _toggleToolbarVisibility: function Reader_toggleToolbarVisibility(visible) {
     this._setToolbarVisibility(!this._getToolbarVisibility());
   },
 
+  _setSystemUIVisibility: function Reader_setSystemUIVisibility(visible) {
+    gChromeWin.sendMessageToJava({
+      type: "SystemUI:Visibility",
+      visible: visible
+    });
+  },
+
   _loadFromURL: function Reader_loadFromURL(url) {
     this._showProgressDelayed();
 
     gChromeWin.Reader.parseDocumentFromURL(url, function(article) {
       if (article)
         this._showContent(article);
       else
         this._showError(gStrings.GetStringFromName("aboutReader.loadError"));
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -6788,17 +6788,17 @@ var SearchEngines = {
         // POST      everything else                     YES
         return (method == "GET" || method == "") ||
                (form.enctype != "text/plain") && (form.enctype != "multipart/form-data");
       }
     };
     SelectionHandler.addAction({
       id: "search_add_action",
       label: Strings.browser.GetStringFromName("contextmenu.addSearchEngine"),
-      icon: "drawable://ic_url_bar_search",
+      icon: "drawable://ab_add_search_engine",
       selector: filter,
       action: function(aElement) {
         SearchEngines.addEngine(aElement);
       }
     });
   },
 
   uninit: function uninit() {
--- a/mobile/android/themes/core/netError.css
+++ b/mobile/android/themes/core/netError.css
@@ -34,16 +34,20 @@ ul {
   margin: 0;
   list-style: round outside none;
 }
 
 li:not(:last-of-type),
 #errorLongDesc,
 #errorLongContent {
   padding-bottom: 10px;
+}
+
+/* Push the #ignoreWarningButton to the bottom on the blocked site page */
+.blockedsite > #errorPageContainer > #errorLongContent {
   flex: 1;
 }
 
 h1 {
   padding: 1rem 0;
   font-weight: 300;
   border-bottom: 1px solid #e0e2e5;
 }
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -334,23 +334,34 @@ InternalMethods.prototype = {
   },
 
   whenVerified: function(data) {
     if (data.verified) {
       log.debug("already verified");
       return Promise.resolve(data);
     }
     if (!this.whenVerifiedPromise) {
-      this.whenVerifiedPromise = Promise.defer();
       log.debug("whenVerified promise starts polling for verified email");
       this.pollEmailStatus(data.sessionToken, "start");
     }
     return this.whenVerifiedPromise.promise;
   },
 
+  /**
+   * Resend the verification email to the logged-in user.
+   *
+   * @return Promise
+   *         fulfilled: json data returned from xhr call
+   *         rejected: error
+   */
+  resendVerificationEmail: function(data) {
+    this.pollEmailStatus(data.sessionToken, "start");
+    return this.fxAccountsClient.resendVerificationEmail(data.sessionToken);
+  },
+
   notifyObservers: function(topic) {
     log.debug("Notifying observers of " + topic);
     Services.obs.notifyObservers(null, topic, null);
   },
 
   /**
    * Give xpcshell tests an override point for duration testing. This is
    * necessary because the tests need to manipulate the date in order to
@@ -359,22 +370,23 @@ InternalMethods.prototype = {
   now: function() {
     return Date.now();
   },
 
   pollEmailStatus: function pollEmailStatus(sessionToken, why) {
     let myGenerationCount = this.generationCount;
     log.debug("entering pollEmailStatus: " + why + " " + myGenerationCount);
     if (why == "start") {
-      if (this.currentTimer) {
-        // safety check - this case should have been caught on
-        // entry with setSignedInUser
-        throw new Error("Already polling for email status");
+      // If we were already polling, stop and start again.  This could happen
+      // if the user requested the verification email to be resent while we
+      // were already polling for receipt of an earlier email.
+      this.pollTimeRemaining = this.POLL_SESSION;
+      if (!this.whenVerifiedPromise) {
+        this.whenVerifiedPromise = Promise.defer();
       }
-      this.pollTimeRemaining = this.POLL_SESSION;
     }
 
     this.checkEmailStatus(sessionToken)
       .then((response) => {
         log.debug("checkEmailStatus -> " + JSON.stringify(response));
         // Check to see if we're still current.
         // If for some ghastly reason we are not, stop processing.
         if (this.generationCount !== myGenerationCount) {
@@ -482,17 +494,17 @@ this.FxAccounts.prototype = Object.freez
    * @return Promise
    *         The promise resolves to null when the data is saved
    *         successfully and is rejected on error.
    */
   setSignedInUser: function setSignedInUser(credentials) {
     log.debug("setSignedInUser - aborting any existing flows");
     internal.abortExistingFlow();
 
-    let record = {version: this.version, accountData: credentials };
+    let record = {version: this.version, accountData: credentials};
     // Cache a clone of the credentials object.
     internal.signedInUser = JSON.parse(JSON.stringify(record));
 
     // This promise waits for storage, but not for verification.
     // We're telling the caller that this is durable now.
     return internal.signedInUserStorage.set(record)
       .then(() => {
         internal.notifyObservers(ONLOGIN_NOTIFICATION);
@@ -529,16 +541,32 @@ this.FxAccounts.prototype = Object.freez
           // that might not be fulfilled for a long time.
           internal.startVerifiedCheck(data);
         }
         return data;
       });
   },
 
   /**
+   * Resend the verification email fot the currently signed-in user.
+   *
+   */
+  resendVerificationEmail: function resendVerificationEmail() {
+    return this.getSignedInUser().then((data) => {
+      // If the caller is asking for verification to be re-sent, and there is
+      // no signed-in user to begin with, this is probably best regarded as an
+      // error.
+      if (data) {
+        return internal.resendVerificationEmail(data);
+      }
+      throw new Error("Cannot resend verification email; no signed-in user");
+    });
+  },
+
+  /**
    * returns a promise that fires with the assertion.  If there is no verified
    * signed-in user, fires with null.
    */
   getAssertion: function getAssertion(audience) {
     log.debug("enter getAssertion()");
     let mustBeValidUntil = internal.now() + ASSERTION_LIFETIME;
     return internal.getUserAccountData()
       .then((data) => {
--- a/services/fxaccounts/FxAccountsClient.jsm
+++ b/services/fxaccounts/FxAccountsClient.jsm
@@ -96,37 +96,49 @@ this.FxAccountsClient.prototype = {
     return this._request("/raw_password/session/create", "POST", null,
                          {email: hexEmail, password: password});
   },
 
   /**
    * Destroy the current session with the Firefox Account API server
    *
    * @param sessionTokenHex
-   *        The session token endcoded in hex
+   *        The session token encoded in hex
    * @return Promise
    */
   signOut: function (sessionTokenHex) {
     return this._request("/session/destroy", "POST",
       this._deriveHawkCredentials(sessionTokenHex, "sessionToken"));
   },
 
   /**
    * Check the verification status of the user's FxA email address
    *
    * @param sessionTokenHex
-   *        The current session token endcoded in hex
+   *        The current session token encoded in hex
    * @return Promise
    */
   recoveryEmailStatus: function (sessionTokenHex) {
     return this._request("/recovery_email/status", "GET",
       this._deriveHawkCredentials(sessionTokenHex, "sessionToken"));
   },
 
   /**
+   * Resend the verification email for the user
+   *
+   * @param sessionTokenHex
+   *        The current token encoded in hex
+   * @return Promise
+   */
+  resendVerificationEmail: function(sessionTokenHex) {
+    return this._request("/recovery_email/resend_code", "POST",
+      this._deriveHawkCredentials(sessionTokenHex, "sessionToken"));
+  },
+
+  /**
    * Retrieve encryption keys
    *
    * @param keyFetchTokenHex
    *        A one-time use key fetch token encoded in hex
    * @return Promise
    *        Returns a promise that resolves to an object:
    *        {
    *          kA: an encryption key for recevorable data
@@ -165,17 +177,17 @@ this.FxAccountsClient.prototype = {
       };
     });
   },
 
   /**
    * Sends a public key to the FxA API server and returns a signed certificate
    *
    * @param sessionTokenHex
-   *        The current session token endcoded in hex
+   *        The current session token encoded in hex
    * @param serializedPublicKey
    *        A public key (usually generated by jwcrypto)
    * @param lifetime
    *        The lifetime of the certificate
    * @return Promise
    *        Returns a promise that resolves to the signed certificate. The certificate
    *        can be used to generate a Persona assertion.
    */
@@ -218,17 +230,17 @@ this.FxAccountsClient.prototype = {
   },
 
   /**
    * The FxA auth server expects requests to certain endpoints to be authorized using Hawk.
    * Hawk credentials are derived using shared secrets, which depend on the context
    * (e.g. sessionToken vs. keyFetchToken).
    *
    * @param tokenHex
-   *        The current session token endcoded in hex
+   *        The current session token encoded in hex
    * @param context
    *        A context for the credentials
    * @param size
    *        The size in bytes of the expected derived buffer
    * @return credentials
    *        Returns an object:
    *        {
    *          algorithm: sha256
--- a/services/fxaccounts/tests/xpcshell/test_accounts.js
+++ b/services/fxaccounts/tests/xpcshell/test_accounts.js
@@ -59,16 +59,21 @@ function MockFxAccountsClient() {
         kA: expandBytes("11"),
         wrapKB: expandBytes("22")
       };
       deferred.resolve(response);
     });
     return deferred.promise;
   };
 
+  this.resendVerificationEmail = function(sessionToken) {
+    // Return the session token to show that we received it in the first place
+    return Promise.resolve(sessionToken);
+  };
+
   this.signCertificate = function() { throw "no" };
 
   FxAccountsClient.apply(this);
 }
 MockFxAccountsClient.prototype = {
   __proto__: FxAccountsClient.prototype
 }
 
@@ -163,19 +168,17 @@ add_task(function test_get_signed_in_use
   // sign out
   yield account.signOut();
 
   // user should be undefined after sign out
   let result = yield account.getSignedInUser();
   do_check_eq(result, null);
 });
 
-/*
- * Sanity-check that our mocked client is working correctly
- */
+// Sanity-check that our mocked client is working correctly
 add_test(function test_client_mock() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let client = fxa.internal.fxAccountsClient;
   do_check_eq(client._verified, false);
   do_check_eq(typeof client.signIn, "function");
 
@@ -183,22 +186,20 @@ add_test(function test_client_mock() {
   client.recoveryEmailStatus()
     .then(response => {
       do_check_eq(response.verified, false);
       do_test_finished();
       run_next_test();
     });
 });
 
-/*
- * Sign in a user, and after a little while, verify the user's email.
- * Right after signing in the user, we should get the 'onlogin' notification.
- * Polling should detect that the email is verified, and eventually
- * 'onverified' should be observed
- */
+// Sign in a user, and after a little while, verify the user's email.
+// Right after signing in the user, we should get the 'onlogin' notification.
+// Polling should detect that the email is verified, and eventually
+// 'onverified' should be observed
 add_test(function test_verification_poll() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let test_user = getTestUser("francine");
   let login_notification_received = false;
 
   makeObserver(ONVERIFIED_NOTIFICATION, function() {
@@ -219,29 +220,27 @@ add_test(function test_verification_poll
     login_notification_received = true;
   });
 
   fxa.setSignedInUser(test_user).then(() => {
     fxa.internal.getUserAccountData().then(user => {
       // The user is signing in, but email has not been verified yet
       do_check_eq(user.verified, false);
       do_timeout(200, function() {
-        // Mock email verification ...
+        log.debug("Mocking verification of francine's email");
         fxa.internal.fxAccountsClient._email = test_user.email;
         fxa.internal.fxAccountsClient._verified = true;
       });
     });
   });
 });
 
-/*
- * Sign in the user, but never verify the email.  The check-email
- * poll should time out.  No verifiedlogin event should be observed, and the
- * internal whenVerified promise should be rejected
- */
+// Sign in the user, but never verify the email.  The check-email
+// poll should time out.  No verifiedlogin event should be observed, and the
+// internal whenVerified promise should be rejected
 add_test(function test_polling_timeout() {
   do_test_pending();
 
   // This test could be better - the onverified observer might fire on
   // somebody else's stack, and we're not making sure that we're not receiving
   // such a message. In other words, this tests either failure, or success, but
   // not both.
 
@@ -298,19 +297,17 @@ add_test(function test_getKeys() {
           do_test_finished();
           run_next_test();
         });
       });
     });
   });
 });
 
-/*
- * getKeys with no keyFetchToken should trigger signOut
- */
+// getKeys with no keyFetchToken should trigger signOut
 add_test(function test_getKeys_no_token() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let user = getTestUser("lettuce.protheroe");
   delete user.keyFetchToken
 
   makeObserver(ONLOGOUT_NOTIFICATION, function() {
@@ -321,21 +318,19 @@ add_test(function test_getKeys_no_token(
     });
   });
 
   fxa.setSignedInUser(user).then((user) => {
     fxa.internal.getKeys();
   });
 });
 
-/*
- * Alice (User A) signs up but never verifies her email.  Then Bob (User B)
- * signs in with a verified email.  Ensure that no sign-in events are triggered
- * on Alice's behalf.  In the end, Bob should be the signed-in user.
- */
+// Alice (User A) signs up but never verifies her email.  Then Bob (User B)
+// signs in with a verified email.  Ensure that no sign-in events are triggered
+// on Alice's behalf.  In the end, Bob should be the signed-in user.
 add_test(function test_overlapping_signins() {
   do_test_pending();
 
   let fxa = new MockFxAccounts();
   let alice = getTestUser("alice");
   let bob = getTestUser("bob");
 
   makeObserver(ONVERIFIED_NOTIFICATION, function() {
@@ -452,16 +447,74 @@ add_task(function test_getAssertion() {
   do_check_eq(fxa.internal.cert.validUntil, now + 24*3600*1000 + (6*3600*1000));
   exp = Number(payload.exp);
   do_check_true(start + 2*60*1000 <= exp);
   do_check_true(exp <= finish + 2*60*1000);
 
   _("----- DONE ----\n");
 });
 
+add_task(function test_resend_email_not_signed_in() {
+  let fxa = new MockFxAccounts();
+
+  try {
+    yield fxa.resendVerificationEmail();
+  } catch(err) {
+    do_check_eq(err.message,
+      "Cannot resend verification email; no signed-in user");
+    do_test_finished();
+    run_next_test();
+    return;
+  }
+  do_throw("Should not be able to resend email when nobody is signed in");
+});
+
+add_task(function test_resend_email() {
+  do_test_pending();
+
+  let fxa = new MockFxAccounts();
+  let alice = getTestUser("alice");
+
+  do_check_eq(fxa.internal.generationCount, 0);
+
+  // Alice is the user signing in; her email is unverified.
+  fxa.setSignedInUser(alice).then(() => {
+    log.debug("Alice signing in");
+
+    // We're polling for the first email
+    do_check_eq(fxa.internal.generationCount, 1);
+
+    // The polling timer is ticking
+    do_check_true(fxa.internal.currentTimer > 0);
+
+    fxa.internal.getUserAccountData().then(user => {
+      do_check_eq(user.email, alice.email);
+      do_check_eq(user.verified, false);
+      log.debug("Alice wants verification email resent");
+
+      fxa.resendVerificationEmail().then((result) => {
+        // Mock server response; ensures that the session token actually was
+        // passed to the client to make the hawk call
+        do_check_eq(result, "alice's session token");
+
+        // Timer was not restarted
+        do_check_eq(fxa.internal.generationCount, 1);
+
+        // Timer is still ticking
+        do_check_true(fxa.internal.currentTimer > 0);
+
+        // Ok abort polling before we go on to the next test
+        fxa.internal.abortExistingFlow();
+        do_test_finished();
+        run_next_test();
+      });
+    });
+  });
+});
+
 /*
  * End of tests.
  * Utility functions follow.
  */
 
 function expandHex(two_hex) {
   // Return a 64-character hex string, encoding 32 identical bytes.
   let eight_hex = two_hex + two_hex + two_hex + two_hex;
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/cpp/Makefile.in
@@ -0,0 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ifdef JS_SHARED_LIBRARY
+LIBS += $(MOZ_JS_LIBS)
+endif
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -191,17 +191,18 @@ const PING_BGUC_IS_DOWNLOADING          
 // An update is staged (no notification)
 const PING_BGUC_IS_STAGED                    = 1;
 // Invalid url for app.update.url default preference (no notification)
 const PING_BGUC_INVALID_DEFAULT_URL          = 2;
 // Invalid url for app.update.url user preference (no notification)
 const PING_BGUC_INVALID_CUSTOM_URL           = 3;
 // Invalid url for app.update.url.override user preference (no notification)
 const PING_BGUC_INVALID_OVERRIDE_URL         = 4;
-// Unable to check for updates per gCanCheckForUpdates (no notification)
+// Unable to check for updates per gCanCheckForUpdates and hasUpdateMutex()
+// (no notification)
 const PING_BGUC_UNABLE_TO_CHECK              = 5;
 // Already has an active update in progress (no notification)
 const PING_BGUC_HAS_ACTIVEUPDATE             = 6;
 // Background checks disabled by preference (no notification)
 const PING_BGUC_PREF_DISABLED                = 7;
 // Background checks disabled for the current session (no notification)
 const PING_BGUC_DISABLED_FOR_SESSION         = 8;
 // Background checks disabled in Metro (no notification)
@@ -253,23 +254,24 @@ const PING_BGUC_ADDON_SAME_APP_VER      
 // No incompatible add-ons found during incompatible check (background download)
 const PING_BGUC_CHECK_NO_INCOMPAT            = 28;
 // Incompatible add-ons found and all of them have updates (background download)
 const PING_BGUC_ADDON_UPDATES_FOR_INCOMPAT   = 29;
 // Incompatible add-ons found (update notification)
 const PING_BGUC_ADDON_HAVE_INCOMPAT          = 30;
 
 var gLocale = null;
+var gUpdateMutexHandle = null;
 
 #ifdef MOZ_WIDGET_GONK
+var gSDCardMountLock = null;
+
 XPCOMUtils.defineLazyGetter(this, "gExtStorage", function aus_gExtStorage() {
     return Services.env.get("EXTERNAL_STORAGE");
 });
-
-var gSDCardMountLock = null;
 #endif
 
 XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
                                   "resource://gre/modules/UpdateChannel.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "gLogEnabled", function aus_gLogEnabled() {
   return getPref("getBoolPref", PREF_APP_UPDATE_LOG, false);
 });
@@ -478,35 +480,38 @@ function closeHandle(handle) {
                                 ctypes.void_t.ptr); /* handle */
   CloseHandle(handle);
   lib.close();
 }
 
 /**
  * Creates a mutex.
  *
- * @param aAllowExisting false if the function should fail if the mutex exists
- * @return The Win32 handle to the mutex
+ * @param  aName
+ *         The name for the mutex.
+ * @param  aAllowExisting
+ *         If false the function will close the handle and return null.
+ * @return The Win32 handle to the mutex.
  */
-function createMutex(name, aAllowExisting) {
+function createMutex(aName, aAllowExisting) {
   if (aAllowExisting === undefined) {
     aAllowExisting = true;
   }
 
   const INITIAL_OWN = 1;
   const ERROR_ALREADY_EXISTS = 0xB7;
   var lib = ctypes.open("kernel32.dll");
   var CreateMutexW = lib.declare("CreateMutexW",
                                  ctypes.winapi_abi,
                                  ctypes.void_t.ptr, /* return handle */
                                  ctypes.void_t.ptr, /* security attributes */
                                  ctypes.int32_t, /* initial owner */
                                  ctypes.jschar.ptr); /* name */
 
-  var handle = CreateMutexW(null, INITIAL_OWN, name);
+  var handle = CreateMutexW(null, INITIAL_OWN, aName);
   var alreadyExists = ctypes.winLastError == ERROR_ALREADY_EXISTS;
   if (handle && !handle.isNull() && !aAllowExisting && alreadyExists) {
     closeHandle(handle);
     handle = null;
   }
   lib.close();
 
   if (handle && handle.isNull())
@@ -549,21 +554,21 @@ function getPerInstallationMutexName(aGl
  * 2) Running a Metro and Desktop application at the same time from the same
  *    path
  * 3) 2 applications running in 2 different user sessions from the same path
  *
  * @return true if this instance holds the update mutex
  */
 function hasUpdateMutex() {
 #ifdef XP_WIN
-  if (!this._updateMutexHandle) {
-    this._updateMutexHandle = createMutex(getPerInstallationMutexName(true), false);
+  if (!gUpdateMutexHandle) {
+    gUpdateMutexHandle = createMutex(getPerInstallationMutexName(true), false);
   }
 
-  return !!this._updateMutexHandle;
+  return !!gUpdateMutexHandle;
 #else
   return true;
 #endif // XP_WIN
 }
 
 XPCOMUtils.defineLazyGetter(this, "gCanApplyUpdates", function aus_gCanApplyUpdates() {
   function submitHasPermissionsTelemetryPing(val) {
     try {
@@ -664,23 +669,16 @@ XPCOMUtils.defineLazyGetter(this, "gCanA
     catch (e) {
        LOG("gCanApplyUpdates - unable to apply updates. Exception: " + e);
       // No write privileges to install directory
       submitHasPermissionsTelemetryPing(false);
       return false;
     }
   } // if (!useService)
 
-  if (!hasUpdateMutex()) {
-    LOG("gCanApplyUpdates - unable to apply updates because another instance" +
-        "of the application is already handling updates for this " +
-        "installation.");
-    return false;
-  }
-
   LOG("gCanApplyUpdates - able to apply updates");
   submitHasPermissionsTelemetryPing(true);
   return true;
 });
 
 /**
  * Whether or not the application can stage an update.
  *
@@ -790,23 +788,16 @@ XPCOMUtils.defineLazyGetter(this, "gCanC
 
   // If we don't know the OS version we're updating, we can't update.
   if (!gOSVersion) {
     LOG("gCanCheckForUpdates - unable to check for updates, unknown OS " +
         "version");
     return false;
   }
 
-  if (!hasUpdateMutex()) {
-    LOG("gCanCheckForUpdates - unable to apply updates because another " +
-        "instance of the application is already handling updates for this " +
-        "installation.");
-    return false;
-  }
-
   LOG("gCanCheckForUpdates - able to check for updates");
   return true;
 });
 
 /**
  * Logs a string to the error console.
  * @param   string
  *          The string to write to the error console.
@@ -2606,17 +2597,17 @@ UpdateService.prototype = {
         }
       }
       else if (!gMetroUpdatesEnabled) {
         this._backgroundUpdateCheckCodePing(PING_BGUC_METRO_DISABLED);
       }
       else if (!getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true)) {
         this._backgroundUpdateCheckCodePing(PING_BGUC_PREF_DISABLED);
       }
-      else if (!gCanCheckForUpdates) {
+      else if (!(gCanCheckForUpdates && hasUpdateMutex())) {
         this._backgroundUpdateCheckCodePing(PING_BGUC_UNABLE_TO_CHECK);
       }
       else if (!this.backgroundChecker._enabled) {
         this._backgroundUpdateCheckCodePing(PING_BGUC_DISABLED_FOR_SESSION);
       }
     }
     catch (e) {
       Cu.reportError(e);
@@ -2754,17 +2745,17 @@ UpdateService.prototype = {
         LOG("UpdateService:_selectAndInstallUpdate - notifying that the " +
             "update is not supported for this system");
         this._showPrompt(update);
       }
       this._backgroundUpdateCheckCodePing(PING_BGUC_UNSUPPORTED);
       return;
     }
 
-    if (!gCanApplyUpdates) {
+    if (!(gCanApplyUpdates && hasUpdateMutex())) {
       LOG("UpdateService:_selectAndInstallUpdate - the user is unable to " +
           "apply updates... prompting");
       this._showPrompt(update);
       this._backgroundUpdateCheckCodePing(PING_BGUC_UNABLE_TO_APPLY);
       return;
     }
 
     /**
@@ -2965,17 +2956,18 @@ UpdateService.prototype = {
     // Compatibility or new version updates mean the same thing here.
     this.onCompatibilityUpdateAvailable(addon);
   },
 
   onUpdateFinished: function(addon) {
     if (--this._updateCheckCount > 0)
       return;
 
-    if (this._incompatibleAddons.length > 0 || !gCanApplyUpdates) {
+    if (this._incompatibleAddons.length > 0 ||
+        !(gCanApplyUpdates && hasUpdateMutex())) {
       LOG("UpdateService:onUpdateEnded - prompting because there are " +
           "incompatible add-ons");
       this._showPrompt(this._update);
       this._backgroundUpdateCheckCodePing(PING_BGUC_ADDON_HAVE_INCOMPAT);
     }
     else {
       LOG("UpdateService:_selectAndInstallUpdate - updates for all " +
           "incompatible add-ons found, just download the update");
@@ -3000,24 +2992,24 @@ UpdateService.prototype = {
       this._backgroundChecker = new Checker();
     return this._backgroundChecker;
   },
 
   /**
    * See nsIUpdateService.idl
    */
   get canCheckForUpdates() {
-    return gCanCheckForUpdates;
+    return gCanCheckForUpdates && hasUpdateMutex();
   },
 
   /**
    * See nsIUpdateService.idl
    */
   get canApplyUpdates() {
-    return gCanApplyUpdates;
+    return gCanApplyUpdates && hasUpdateMutex();
   },
 
   /**
    * See nsIUpdateService.idl
    */
   get canStageUpdates() {
     return getCanStageUpdates();
   },
@@ -3793,17 +3785,17 @@ Checker.prototype = {
    */
   _enabled: true,
   get enabled() {
     if (!gMetroUpdatesEnabled) {
       return false;
     }
 
     return getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true) &&
-           gCanCheckForUpdates && this._enabled;
+           gCanCheckForUpdates && hasUpdateMutex() && this._enabled;
   },
 
   /**
    * See nsIUpdateService.idl
    */
   stopChecking: function UC_stopChecking(duration) {
     // Always stop the current check
     if (this._request)
--- a/toolkit/mozapps/update/tests/unit_aus_update/canCheckForAndCanApplyUpdates.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/canCheckForAndCanApplyUpdates.js
@@ -3,26 +3,132 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 function run_test() {
   setupTestCommon();
 
   // Verify write access to the custom app dir
   logTestInfo("testing write access to the application directory");
-  var testFile = getCurrentProcessDir();
+  let testFile = getCurrentProcessDir();
   testFile.append("update_write_access_test");
-  testFile.create(AUS_Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
+  testFile.create(AUS_Ci.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE);
   do_check_true(testFile.exists());
   testFile.remove(false);
   do_check_false(testFile.exists());
 
   standardInit();
 
+  if (IS_WIN) {
+    // Create a mutex to prevent being able to check for or apply updates.
+    logTestInfo("attempting to create mutex");
+    let handle = createMutex(getPerInstallationMutexName());
+
+    logTestInfo("testing that the mutex was successfully created");
+    do_check_neq(handle, null);
+
+    // Check if available updates cannot be checked for when there is a mutex
+    // for this installation.
+    logTestInfo("testing nsIApplicationUpdateService:canCheckForUpdates is " +
+                "false when there is a mutex");
+    do_check_false(gAUS.canCheckForUpdates);
+
+    // Check if updates cannot be applied when there is a mutex for this
+    // installation.
+    logTestInfo("testing nsIApplicationUpdateService:canApplyUpdates is " +
+                "false when there is a mutex");
+    do_check_false(gAUS.canApplyUpdates);
+
+    logTestInfo("destroying mutex");
+    closeHandle(handle)
+  }
+
   // Check if available updates can be checked for
-  logTestInfo("testing nsIApplicationUpdateService:canCheckForUpdates");
+  logTestInfo("testing nsIApplicationUpdateService:canCheckForUpdates is true");
   do_check_true(gAUS.canCheckForUpdates);
   // Check if updates can be applied
-  logTestInfo("testing nsIApplicationUpdateService:canApplyUpdates");
+  logTestInfo("testing nsIApplicationUpdateService:canApplyUpdates is true");
   do_check_true(gAUS.canApplyUpdates);
 
+  if (IS_WIN) {
+    // Attempt to create a mutex when application update has already created one
+    // with the same name.
+    logTestInfo("attempting to create mutex");
+    let handle = createMutex(getPerInstallationMutexName());
+
+    logTestInfo("testing that the mutex was not successfully created");
+    do_check_eq(handle, null);
+  }
+
   doTestFinish();
 }
+
+if (IS_WIN) {
+  /**
+   * Determines a unique mutex name for the installation.
+   *
+   * @return Global mutex path.
+   */
+  function getPerInstallationMutexName() {
+    let hasher = AUS_Cc["@mozilla.org/security/hash;1"].
+                 createInstance(AUS_Ci.nsICryptoHash);
+    hasher.init(hasher.SHA1);
+
+    let exeFile = Services.dirsvc.get(XRE_EXECUTABLE_FILE, AUS_Ci.nsILocalFile);
+
+    let converter = AUS_Cc["@mozilla.org/intl/scriptableunicodeconverter"].
+                    createInstance(AUS_Ci.nsIScriptableUnicodeConverter);
+    converter.charset = "UTF-8";
+    let data = converter.convertToByteArray(exeFile.path.toLowerCase());
+
+    hasher.update(data, data.length);
+    return "Global\\MozillaUpdateMutex-" + hasher.finish(true);
+  }
+
+  /**
+   * Closes a Win32 handle.
+   *
+   * @param  aHandle
+   *         The handle to close.
+   */
+  function closeHandle(aHandle) {
+    let lib = ctypes.open("kernel32.dll");
+    let CloseHandle = lib.declare("CloseHandle",
+                                  ctypes.winapi_abi,
+                                  ctypes.int32_t, /* success */
+                                  ctypes.void_t.ptr); /* handle */
+    CloseHandle(aHandle);
+    lib.close();
+  }
+
+  /**
+   * Creates a mutex.
+   *
+   * @param  aName
+   *         The name for the mutex.
+   * @return The Win32 handle to the mutex.
+   */
+  function createMutex(aName) {
+    const INITIAL_OWN = 1;
+    const ERROR_ALREADY_EXISTS = 0xB7;
+    let lib = ctypes.open("kernel32.dll");
+    let CreateMutexW = lib.declare("CreateMutexW",
+                                   ctypes.winapi_abi,
+                                   ctypes.void_t.ptr, /* return handle */
+                                   ctypes.void_t.ptr, /* security attributes */
+                                   ctypes.int32_t, /* initial owner */
+                                   ctypes.jschar.ptr); /* name */
+
+    let handle = CreateMutexW(null, INITIAL_OWN, aName);
+    lib.close();
+    let alreadyExists = ctypes.winLastError == ERROR_ALREADY_EXISTS;
+    if (handle && !handle.isNull() && alreadyExists) {
+      closeHandle(handle);
+      handle = null;
+    }
+
+    if (handle && handle.isNull()) {
+      handle = null;
+    }
+
+    return handle;
+  }
+}
--- a/toolkit/themes/windows/global/menulist-aero.css
+++ b/toolkit/themes/windows/global/menulist-aero.css
@@ -16,16 +16,20 @@ menulist:-moz-focusring:not([open="true"
   }
 
   .menulist-label {
     margin-top: -1px !important;
     margin-bottom: -1px !important;
     -moz-margin-start: 0 !important;
   }
 
+  .menulist-description {
+    -moz-margin-start: 1ex !important;
+  }
+
   menulist:not([editable="true"]) > .menulist-dropmarker {
     margin-top: -2px;
     -moz-margin-start: 3px;
     -moz-margin-end: -3px;
   }
 
   .menulist-icon {
     margin-top: -1px;
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -38,16 +38,17 @@
 #include "nsWindow.h"
 #include "nsIWidgetListener.h"
 #include "cutils/properties.h"
 #include "ClientLayerManager.h"
 #include "BasicLayers.h"
 #include "libdisplay/GonkDisplay.h"
 #include "pixelflinger/format.h"
 #include "mozilla/BasicEvents.h"
+#include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "ParentProcessController.h"
 #include "nsThreadUtils.h"
 #include "HwcComposer2D.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
@@ -568,16 +569,17 @@ nsWindow::GetLayerManager(PLayerTransact
         return nullptr;
     }
 
     if (sUsingOMTC) {
         CreateCompositor();
         if (mCompositorParent) {
             uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
             CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController());
+            CompositorParent::GetAPZCTreeManager(rootLayerTreeId)->SetDPI(GetDPI());
         }
         if (mLayerManager)
             return mLayerManager;
     }
 
     if (mUseLayersAcceleration) {
         DebugOnly<nsIntRect> fbBounds = gScreenBounds;
         if (!sGLContext) {