Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 05 Jun 2013 16:29:54 -0400
changeset 134129 204de5b7e0a6dd2d79c2b0378d1104ecac01b1f3
parent 134089 ec4504144bcfd34a4c4458bda80e92464db4ada7 (current diff)
parent 134128 0327342bd9dceb836213678a160cfc2fd3af2099 (diff)
child 134142 72fbfb2f8e51a69e59fb11da6e1a98ea02a8073f
child 134195 a32d62b694349aac84d69d44a3efd87dbc6db266
child 134266 26afe15af309d9883898316b7dcf7a6596de8b9b
push id24783
push userryanvm@gmail.com
push dateWed, 05 Jun 2013 20:30:03 +0000
treeherdermozilla-central@204de5b7e0a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone24.0a1
first release with
nightly linux32
204de5b7e0a6 / 24.0a1 / 20130606031128 / files
nightly linux64
204de5b7e0a6 / 24.0a1 / 20130606031128 / files
nightly mac
204de5b7e0a6 / 24.0a1 / 20130606031128 / files
nightly win32
204de5b7e0a6 / 24.0a1 / 20130606031128 / files
nightly win64
204de5b7e0a6 / 24.0a1 / 20130606031128 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c.
build/pgo/Makefile.in
build/pgo/blueprint/Makefile.in
build/pgo/blueprint/moz.build
build/pgo/genpgocert.py.in
build/pgo/js-input/Makefile.in
build/pgo/js-input/moz.build
build/pgo/moz.build
js/src/jslog2.cpp
--- a/CLOBBER
+++ b/CLOBBER
@@ -12,12 +12,9 @@
 #          O               O
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
-Bug 496923 removed a directory which the non-regenerated js/src/tests/Makefile will still request.
-
-Alternative to clobber is to run ./config.status from the objdir and to
-touch the CLOBBER file in the objdir.
+Bug 875929 removed a file from js/src/moz.build and apparently the build system didn't notice.
--- a/accessible/public/nsIAccessibleStates.idl
+++ b/accessible/public/nsIAccessibleStates.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(7fe1ee90-edaa-43f1-9f3b-071099b51f08)]
+[scriptable, uuid(f1e0fbb7-fde4-4519-9383-2bcbee428513)]
 interface nsIAccessibleStates : nsISupports
 {
   /**
    * MSAA State flags - used for bitfield. More than 1 allowed.
    */
   const unsigned long  STATE_UNAVAILABLE        = 0x00000001;  // Disabled, maps to opposite of Java ENABLED, Gnome/ATK SENSITIVE?
   const unsigned long  STATE_SELECTED           = 0x00000002;
   const unsigned long  STATE_FOCUSED            = 0x00000004;
@@ -66,10 +66,11 @@ interface nsIAccessibleStates : nsISuppo
   const unsigned long  EXT_STATE_OPAQUE                  = 0x00000100;  // Indicates this object paints every pixel within its rectangular region.
   const unsigned long  EXT_STATE_SINGLE_LINE             = 0x00000200;  // This text object can only contain 1 line of text    
   const unsigned long  EXT_STATE_TRANSIENT               = 0x00000400;  // 
   const unsigned long  EXT_STATE_VERTICAL                = 0x00000800;  // Especially used for sliders and scrollbars  
   const unsigned long  EXT_STATE_STALE                   = 0x00001000;  // Object not dead, but not up-to-date either
   const unsigned long  EXT_STATE_ENABLED                 = 0x00002000;  // A widget that is not unavailable
   const unsigned long  EXT_STATE_SENSITIVE               = 0x00004000;  // Same as ENABLED for now
   const unsigned long  EXT_STATE_EXPANDABLE              = 0x00008000;  // If COLLAPSED or EXPANDED
+  const unsigned long  EXT_STATE_PINNED                  = 0x00010000;  // Indicates object is pinned.
 };
 
--- a/accessible/src/atk/nsStateMap.h
+++ b/accessible/src/atk/nsStateMap.h
@@ -20,16 +20,18 @@ The following nsIAccessible states aren'
                          The nsIAccessible state is not currently supported.
   STATE_LINKED:          The object is formatted as a hyperlink. Supported via ATK_ROLE_LINK.
   STATE_EXTSELECTABLE:   Indicates that an object extends its selection.
                          This is supported via STATE_MULTISELECTABLE.
   STATE_PROTECTED:       The object is a password-protected edit control.
                          Supported via ATK_ROLE_PASSWORD_TEXT
   STATE_HASPOPUP:        Object displays a pop-up menu or window when invoked.
                          No ATK equivalent.  The nsIAccessible state is not currently supported.
+  STATE_PINNED:          The object is pinned, usually indicating it is fixed in place and has permanence.
+                         No ATK equivalent.  The nsIAccessible state is not currently supported.
 
 The following ATK states are not supported:
   ATK_STATE_ARMED:       No clear use case, used briefly when button is activated
   ATK_STATE_HAS_TOOLTIP: No clear use case, no IA2 equivalent
   ATK_STATE_ICONIFIED:   Mozilla does not have elements which are collapsable into icons
   ATK_STATE_TRUNCATED:   No clear use case. Indicates that an object's onscreen content is truncated, 
                          e.g. a text value in a spreadsheet cell. No IA2 state.
 ******************************************************************************/
@@ -103,10 +105,11 @@ static const AtkStateMap gAtkStateMap[] 
   { ATK_STATE_OPAQUE,                         kMapDirectly },   // states::OPAQUE                  = 1 << 39
   { ATK_STATE_SINGLE_LINE,                    kMapDirectly },   // states::SINGLE_LINE             = 1 << 40
   { ATK_STATE_TRANSIENT,                      kMapDirectly },   // states::TRANSIENT               = 1 << 41
   { ATK_STATE_VERTICAL,                       kMapDirectly },   // states::VERTICAL                = 1 << 42
   { ATK_STATE_STALE,                          kMapDirectly },   // states::STALE                   = 1 << 43
   { ATK_STATE_ENABLED,                        kMapDirectly },   // states::ENABLED                 = 1 << 44
   { ATK_STATE_SENSITIVE,                      kMapDirectly },   // states::SENSITIVE               = 1 << 45
   { ATK_STATE_EXPANDABLE,                     kMapDirectly },   // states::EXPANDABLE              = 1 << 46
-  { kNone,                                    kNoSuchState },   //                                 = 1 << 47
+  { kNone,                                    kMapDirectly },   // states::PINNED                  = 1 << 47
+  { kNone,                                    kNoSuchState },   //                                 = 1 << 48
 };
--- a/accessible/src/base/States.h
+++ b/accessible/src/base/States.h
@@ -267,14 +267,19 @@ namespace states {
    */
   const uint64_t SENSITIVE = ((uint64_t) 0x1) << 45;
 
   /**
    * The object is expandable, provides a UI to expand/collapse its children
    * @see EXPANDED and COLLAPSED states.
    */
   const uint64_t EXPANDABLE = ((uint64_t) 0x1) << 46;
+
+  /**
+   * The object is pinned, usually indicating it is fixed in place and has permanence.
+   */
+  const uint64_t PINNED = ((uint64_t) 0x1) << 47;
 } // namespace states
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 	
--- a/accessible/src/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/AccessibleWrap.cpp
@@ -1251,16 +1251,18 @@ AccessibleWrap::get_states(AccessibleSta
   if (state & states::SUPPORTS_AUTOCOMPLETION)
     *aStates |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
   if (state & states::TRANSIENT)
     *aStates |= IA2_STATE_TRANSIENT;
   if (state & states::VERTICAL)
     *aStates |= IA2_STATE_VERTICAL;
   if (state & states::CHECKED)
     *aStates |= IA2_STATE_CHECKABLE;
+  if (state & states::PINNED)
+    *aStates |= IA2_STATE_PINNED;
 
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_extendedRole(BSTR *aExtendedRole)
--- a/accessible/src/xul/XULTabAccessible.cpp
+++ b/accessible/src/xul/XULTabAccessible.cpp
@@ -78,23 +78,29 @@ XULTabAccessible::NativeRole()
 uint64_t
 XULTabAccessible::NativeState()
 {
   // Possible states: focused, focusable, unavailable(disabled), offscreen.
 
   // get focus and disable status from base class
   uint64_t state = AccessibleWrap::NativeState();
 
-  // Check whether the tab is selected
+  // Check whether the tab is selected and/or pinned
   nsCOMPtr<nsIDOMXULSelectControlItemElement> tab(do_QueryInterface(mContent));
   if (tab) {
     bool selected = false;
     if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
       state |= states::SELECTED;
+
+    if (mContent && mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::pinned) &&
+        mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::pinned,
+                              nsGkAtoms::_true, eCaseMatters))
+      state |= states::PINNED;
   }
+
   return state;
 }
 
 uint64_t
 XULTabAccessible::NativeInteractiveState() const
 {
   uint64_t state = Accessible::NativeInteractiveState();
   return (state & states::UNAVAILABLE) ? state : state | states::SELECTABLE;
--- a/accessible/tests/mochitest/states.js
+++ b/accessible/tests/mochitest/states.js
@@ -38,16 +38,17 @@ const STATE_UNAVAILABLE = nsIAccessibleS
 
 const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
 const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
 const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
 const EXT_STATE_ENABLED = nsIAccessibleStates.EXT_STATE_ENABLED;
 const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
 const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
 const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
+const EXT_STATE_PINNED = nsIAccessibleStates.EXT_STATE_PINNED;
 const EXT_STATE_SENSITIVE = nsIAccessibleStates.EXT_STATE_SENSITIVE;
 const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
 const EXT_STATE_STALE = nsIAccessibleStates.EXT_STATE_STALE;
 const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
   nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
 const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
 
 const kOrdinalState = 0;
--- a/accessible/tests/mochitest/states/Makefile.in
+++ b/accessible/tests/mochitest/states/Makefile.in
@@ -25,16 +25,17 @@ MOCHITEST_A11Y_FILES =\
 		test_expandable.xul \
 		test_frames.html \
 		test_inputs.html \
 		test_link.html \
 		test_popup.xul \
 		test_selects.html \
 		test_stale.html \
 		test_textbox.xul \
+		test_tabs.xul \
 		test_tree.xul \
 		test_visibility.html \
 		test_visibility.xul \
 		z_frames.html \
 		z_frames_article.html \
 		z_frames_checkbox.html \
 		z_frames_textbox.html \
 		z_frames_update.html \
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/states/test_tabs.xul
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL tabbox hierarchy tests">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
+          src="../states.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    function doTest()
+    {
+      testStates("tab1", 0, EXT_STATE_PINNED);
+      testStates("tab2", 0, 0, 0, EXT_STATE_PINNED);
+      testStates("tab3", 0, 0, 0, EXT_STATE_PINNED);
+
+      SimpleTest.finish()
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=577727"
+         title="Make pinned tabs distinguishable from other tabs for accessibility">
+        Mozilla Bug 577727
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <tabbox>
+        <tabs id="tabs">
+          <tab id="tab1" label="tab1" pinned="true"/>
+          <tab id="tab2" label="tab2" pinned="false"/>
+          <tab id="tab3" label="tab3"/>
+        </tabs>
+        <tabpanels id="tabpanels">
+          <tabpanel/>
+          <tabpanel/>
+        </tabpanels>
+      </tabbox>
+    </vbox>
+  </hbox>
+
+</window>
+
--- a/browser/base/content/browser-webrtcUI.js
+++ b/browser/base/content/browser-webrtcUI.js
@@ -39,14 +39,17 @@ let WebrtcIndicator = {
       aPopup.removeChild(aPopup.lastChild);
   },
 
   menuCommand: function (aMenuitem) {
     let streamData = this._menuitemData.get(aMenuitem);
     if (!streamData)
       return;
 
-    let tab = streamData.tab;
-    let browserWindow = tab.ownerDocument.defaultView;
-    browserWindow.gBrowser.selectedTab = tab;
+    let browserWindow = streamData.browser.ownerDocument.defaultView;
+    if (streamData.tab) {
+      browserWindow.gBrowser.selectedTab = streamData.tab;
+    } else {
+      streamData.browser.focus();
+    }
     browserWindow.focus();
   }
 }
--- a/browser/installer/windows/Makefile.in
+++ b/browser/installer/windows/Makefile.in
@@ -19,16 +19,17 @@ PRE_RELEASE_SUFFIX := ""
 DEFINES += -DPRE_RELEASE_SUFFIX="$(PRE_RELEASE_SUFFIX)"
 
 INSTALLER_FILES = \
 	app.tag \
 	nsis/installer.nsi \
 	nsis/uninstaller.nsi \
 	nsis/stub.nsi \
 	nsis/shared.nsh \
+	stub.tag \
 	$(NULL)
 
 ifdef MOZ_MAINTENANCE_SERVICE
 INSTALLER_FILES += \
 	nsis/maintenanceservice_installer.nsi \
 	$(NULL)
 endif
 
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -8,18 +8,17 @@
 # InetBgDL
 # ShellLink
 # UAC
 
 ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
 !verbose 3
 
 SetDatablockOptimize on
-SetCompress force
-SetCompressor /FINAL /SOLID lzma
+SetCompress off
 CRCCheck on
 
 RequestExecutionLevel user
 
 !addplugindir ./
 
 Var Dialog
 Var ProgressbarDownload
@@ -234,20 +233,20 @@ Var ControlRightPX
 !insertmacro GetSingleInstallPath
 !insertmacro GetTextWidthHeight
 !insertmacro IsUserAdmin
 !insertmacro OnStubInstallUninstall
 !insertmacro SetBrandNameVars
 !insertmacro UnloadUAC
 
 VIAddVersionKey "FileDescription" "${BrandShortName} Stub Installer"
-VIAddVersionKey "OriginalFilename" "stub.exe"
+VIAddVersionKey "OriginalFilename" "setup-stub.exe"
 
 Name "$BrandFullName"
-OutFile "stub.exe"
+OutFile "setup-stub.exe"
 icon "setup.ico"
 XPStyle on
 BrandingText " "
 ChangeUI all "nsisui.exe"
 !ifdef HAVE_64BIT_OS
   InstallDir "$PROGRAMFILES64\${BrandFullName}\"
 !else
   InstallDir "$PROGRAMFILES32\${BrandFullName}\"
new file mode 100644
--- /dev/null
+++ b/browser/installer/windows/stub.tag
@@ -0,0 +1,4 @@
+;!@Install@!UTF-8!
+Title="Mozilla Firefox"
+RunProgram="setup-stub.exe"
+;!@InstallEnd@!
\ No newline at end of file
--- a/browser/metro/base/content/ContentAreaObserver.js
+++ b/browser/metro/base/content/ContentAreaObserver.js
@@ -155,32 +155,45 @@ var ContentAreaObserver = {
     if (newHeight == oldHeight && newWidth == oldWidth)
       return;
 
     this.styles["viewable-height"].height = newHeight + "px";
     this.styles["viewable-height"].maxHeight = newHeight + "px";
     this.styles["viewable-width"].width = newWidth + "px";
     this.styles["viewable-width"].maxWidth = newWidth + "px";
 
-    // Adjust the app and find bar position above the soft keyboard
-    let navBar = document.getElementById("navbar");
-    let contextAppBar = document.getElementById("contextappbar");
-    let findBar = document.getElementById("content-navigator");
-    let keyboardHeight = MetroUtils.keyboardHeight;
-    navBar.style.bottom = keyboardHeight + "px";
-    contextAppBar.style.bottom = keyboardHeight + "px";
-    findBar.style.bottom = keyboardHeight + "px";
+    this.updateAppBarPosition();
 
     // Update the back/tab button states. If the keyboard is up
     // these are hidden.
     BrowserUI._updateButtons();
 
     this._disatchBrowserEvent("ViewableSizeChanged");
   },
 
+  updateAppBarPosition: function updateAppBarPosition(aForceDown) {
+    // Adjust the app and find bar position above the soft keyboard
+    let navBar = document.getElementById("navbar");
+    let contextAppBar = document.getElementById("contextappbar");
+    let findBar = document.getElementById("content-navigator");
+    let keyboardHeight = aForceDown ? 0 : MetroUtils.keyboardHeight;
+    navBar.style.bottom = keyboardHeight + "px";
+    contextAppBar.style.bottom = keyboardHeight + "px";
+    findBar.style.bottom = keyboardHeight + "px";
+  },
+
+  /*
+   * Called by BrowserUI right before we blur the nav bar edit. We use
+   * this to get a head start on shuffling app bars around before the
+   * soft keyboard transitions down.
+   */
+  navBarWillBlur: function navBarWillBlur() {
+    this.updateAppBarPosition(true);
+  },
+
   onBrowserCreated: function onBrowserCreated(aBrowser) {
     aBrowser.classList.add("content-width");
     aBrowser.classList.add("content-height");
   },
 
   /*
    * Event handling
    */
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -535,17 +535,21 @@ var BrowserUI = {
 
   blurFocusedElement: function blurFocusedElement() {
     let focusedElement = document.commandDispatcher.focusedElement;
     if (focusedElement)
       focusedElement.blur();
   },
 
   blurNavBar: function blurNavBar() {
-    this._edit.blur();
+    if (this._edit.focused) {
+      this._edit.blur();
+      return true;
+    }
+    return false;
   },
 
   // If the user types in the address bar, cancel pending
   // navbar autohide if set.
   navEditKeyPress: function navEditKeyPress() {
     ContextUI.cancelDismiss();
   },
 
@@ -1489,17 +1493,21 @@ var StartUI = {
     } else if (aURI != "about:blank") { // about:blank is loaded briefly for new tabs; ignore it
       this.hide(aURI);
     }
   },
 
   onClick: function onClick(aEvent) {
     // If someone clicks / taps in empty grid space, take away
     // focus from the nav bar edit so the soft keyboard will hide.
-    BrowserUI.blurNavBar();
+    if (BrowserUI.blurNavBar()) {
+      // Advanced notice to CAO, so we can shuffle the nav bar in advance
+      // of the keyboard transition.
+      ContentAreaObserver.navBarWillBlur();
+    }
   },
 
   handleEvent: function handleEvent(aEvent) {
     switch (aEvent.type) {
       case "autocompletestart":
         this.filter();
         break;
       case "autocompleteend":
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -326,18 +326,17 @@ documenttab[selected] .documenttab-selec
 /* App Bar ----------------------------------------------------------------- */
 
 appbar {
   display: block;
   position: fixed;
   bottom: 0;
   width: 100%;
   transform: translateY(100%);
-  transition: transform @metro_animation_duration@ @metro_animation_easing@,
-              bottom @metro_animation_duration@ @metro_animation_easing@;
+  transition: transform @metro_animation_duration@ @metro_animation_easing@;
   font-size: 0;
 }
 
 appbar > toolbar {
   -moz-appearance: none;
   -moz-box-align: center;
   border: 0;
   width: 100%;
@@ -357,16 +356,23 @@ appbar > toolbar > toolbarbutton[disable
   visibility: collapse;
 }
 
 #navbar[startpage],
 appbar[visible] {
   transform: none;
 }
 
+#stack[keyboardVisible] > appbar {
+  /* Slow the bottom up transition since it's impossible to match the system's
+     soft keyboard movement. */
+  transition: transform @metro_animation_duration@ @metro_animation_easing@,
+              bottom @appbar_keyboard_slideup_duration@ @metro_animation_easing@;
+}
+
 appbar > toolbar > toolbarbutton {
   list-style-image: url(chrome://browser/skin/images/appbar-icons.png);
   -moz-image-region: rect(0px, 200px, 40px, 160px); /* Gear icon is default. */
 }
 appbar > toolbar > toolbarbutton:hover {
   -moz-image-region: rect(40px, 200px, 80px, 160px);
 }
 appbar > toolbar > toolbarbutton:active {
--- a/browser/metro/theme/defines.inc
+++ b/browser/metro/theme/defines.inc
@@ -78,8 +78,13 @@
 %define border_radius_normal 5px
 %define border_radius_tiny 1px
 
 %define shadow_width_small 1px
 
 % easing function and duration for animations match winJS showPanel method
 %define metro_animation_duration 550ms
 %define metro_animation_easing cubic-bezier(0.1, 0.9, 0.2, 1)
+
+% this is meant to be slower than the system keyboard such
+% that the bars slide up after the keyboard is in place.
+%define appbar_keyboard_slideup_duration 750ms
+
--- a/browser/metro/theme/forms.css
+++ b/browser/metro/theme/forms.css
@@ -9,25 +9,31 @@
 
 #content-navigator {
   display: block;
   position: fixed;
   pointer-events: none;
   padding: 0;
   bottom: 0;
   transform: translateY(100%);
-  transition: transform @metro_animation_duration@ @metro_animation_easing@,
-              bottom @metro_animation_duration@ @metro_animation_easing@;
+  transition: transform @metro_animation_duration@ @metro_animation_easing@;
   background-color: @metro_orange@;
 }
 
 #content-navigator[showing] {
   transform: none;
 }
 
+#stack[keyboardVisible] > #content-navigator {
+  /* Slow the bottom up transition since it's impossible to match the system's
+     soft keyboard movement. */
+  transition: transform @metro_animation_duration@ @metro_animation_easing@,
+              bottom @appbar_keyboard_slideup_duration@ @metro_animation_easing@;
+}
+
 #content-navigator > .previous-button,
 #content-navigator > .next-button,
 #content-navigator > .close-button {
   min-width: @touch_button_small@ !important; /* button size */
   min-height: @touch_button_small@ !important; /* button size */
   border: none !important;
   background-image: none !important;
   background-color: inherit !important;
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -34,28 +34,25 @@ this.webrtcUI = {
   showGlobalIndicator: false,
 
   get activeStreams() {
     let contentWindowSupportsArray = MediaManagerService.activeMediaCaptureWindows;
     let count = contentWindowSupportsArray.Count();
     let activeStreams = [];
     for (let i = 0; i < count; i++) {
       let contentWindow = contentWindowSupportsArray.GetElementAt(i);
-      let browserWindow = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                       .getInterface(Ci.nsIWebNavigation)
-                                       .QueryInterface(Ci.nsIDocShell)
-                                       .chromeEventHandler.ownerDocument.defaultView;
+      let browser = getBrowserForWindow(contentWindow);
+      let browserWindow = browser.ownerDocument.defaultView;
       let tab = browserWindow.gBrowser &&
                 browserWindow.gBrowser._getTabForContentWindow(contentWindow.top);
-      if (tab) {
-        activeStreams.push({
-          uri: contentWindow.location.href,
-          tab: tab
-        });
-      }
+      activeStreams.push({
+        uri: contentWindow.location.href,
+        tab: tab,
+        browser: browser
+      });
     }
     return activeStreams;
   }
 }
 
 function getBrowserForWindowId(aWindowID) {
   return getBrowserForWindow(Services.wm.getOuterWindowWithId(aWindowID));
 }
@@ -207,18 +204,18 @@ function prompt(aWindowID, aCallID, aAud
 function updateIndicators() {
   webrtcUI.showGlobalIndicator =
     MediaManagerService.activeMediaCaptureWindows.Count() > 0;
 
   let e = Services.wm.getEnumerator("navigator:browser");
   while (e.hasMoreElements())
     e.getNext().WebrtcIndicator.updateButton();
 
-  for (let {tab: tab} of webrtcUI.activeStreams)
-    showBrowserSpecificIndicator(tab.linkedBrowser);
+  for (let {browser: browser} of webrtcUI.activeStreams)
+    showBrowserSpecificIndicator(browser);
 }
 
 function showBrowserSpecificIndicator(aBrowser) {
   let hasVideo = {};
   let hasAudio = {};
   MediaManagerService.mediaCaptureWindowState(aBrowser.contentWindow,
                                               hasVideo, hasAudio);
   let captureState;
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -1348,39 +1348,55 @@ private void CancelNotification()
         sRet += "Total Private Dirty Memory         " + mi[0].getTotalPrivateDirty() + " kb\n";
         sRet += "Total Proportional Set Size Memory " + mi[0].getTotalPss()          + " kb\n";
         sRet += "Total Shared Dirty Memory          " + mi[0].getTotalSharedDirty()  + " kb";
 
 
         return(sRet);
         }
 
+    public void FixDataLocalPermissions()
+        {
+        String chmodResult;
+        File localDir = new java.io.File("/data/local");
+        if (!localDir.canWrite()) {
+            chmodResult = ChmodDir("/data/local");
+            Log.i("SUTAgentAndroid", "Changed permissions on /data/local to make it writable: " + chmodResult);
+        }
+        File tmpDir = new java.io.File("/data/local/tmp");
+        if (tmpDir.exists() && !tmpDir.isDirectory()) {
+            if (!tmpDir.delete()) {
+                Log.e("SUTAgentAndroid", "Could not delete file /data/local/tmp");
+            }
+        }
+        if (!tmpDir.exists() && !tmpDir.mkdirs()) {
+            Log.e("SUTAgentAndroid", "Could not create directory /data/local/tmp");
+        }
+        chmodResult = ChmodDir("/data/local/tmp");
+        Log.i("SUTAgentAndroid", "Changed permissions on /data/local/tmp to make it writable: " + chmodResult);
+        }
+
     public String GetTestRoot()
         {
-
-        // According to all the docs this should work, but I keep getting an
-        // exception when I attempt to create the file because I don't have
-        // permission, although /data/local/tmp is supposed to be world
-        // writeable/readable
-        File tmpFile = new java.io.File("/data/local/tmp/tests");
-        try{
-            tmpFile.createNewFile();
-        } catch (IOException e){
-            Log.i("SUTAgentAndroid", "Caught exception creating file in /data/local/tmp: " + e.getMessage());
-        }
-   
         String state = Environment.getExternalStorageState();
         // Ensure sdcard is mounted and NOT read only
         if (state.equalsIgnoreCase(Environment.MEDIA_MOUNTED) &&
             (Environment.MEDIA_MOUNTED_READ_ONLY.compareTo(state) != 0))
             {
             return(Environment.getExternalStorageDirectory().getAbsolutePath());
             }
-        if (tmpFile.exists()) 
+        File tmpFile = new java.io.File("/data/local/tmp/tests");
+        try{
+            tmpFile.createNewFile();
+        } catch (IOException e){
+            Log.i("SUTAgentAndroid", "Caught exception creating file in /data/local/tmp: " + e.getMessage());
+        }
+        if (tmpFile.exists())
             {
+            tmpFile.delete();
             return("/data/local");
             }
         Log.e("SUTAgentAndroid", "ERROR: Cannot access world writeable test root");
 
         return(null);
         }
 
     public String GetAppRoot(String AppName)
@@ -3823,17 +3839,17 @@ private void CancelNotification()
                     for (int lcv = 0; lcv < nFiles; lcv++) {
                         if (files[lcv].isDirectory()) {
                             sSubDir = files[lcv].getAbsolutePath();
                             sRet += "\n" + ChmodDir(sSubDir);
                         }
                         else {
                             // set the new file's permissions to rwxrwxrwx, if possible
                             try {
-                                Process pProc = Runtime.getRuntime().exec("chmod 777 "+files[lcv]);
+                                Process pProc = Runtime.getRuntime().exec(this.getSuArgs("chmod 777 "+files[lcv]));
                                 RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
                                 outThrd.start();
                                 outThrd.joinAndStopRedirect(5000);
                                 sRet += "\n\tchmod " + files[lcv].getName() + " ok";
                             } catch (InterruptedException e) {
                                 sRet += "\n\ttimeout waiting for chmod " + files[lcv].getName();
                             } catch (IOException e) {
                                 sRet += "\n\tunable to chmod " + files[lcv].getName();
@@ -3843,17 +3859,17 @@ private void CancelNotification()
                 }
                 else
                     sRet += "\n\t<empty>";
                 }
             }
 
         // set the new directory's (or file's) permissions to rwxrwxrwx, if possible
         try {
-            Process pProc = Runtime.getRuntime().exec("chmod 777 "+sTmpDir);
+            Process pProc = Runtime.getRuntime().exec(this.getSuArgs("chmod 777 "+sTmpDir));
             RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
             outThrd.start();
             outThrd.joinAndStopRedirect(5000);
             sRet += "\n\tchmod " + sTmpDir + " ok";
         } catch (InterruptedException e) {
             sRet += "\n\ttimeout waiting for chmod " + sTmpDir;
         } catch (IOException e) {
             sRet += "\n\tunable to chmod " + sTmpDir;
--- a/build/mobile/sutagent/android/SUTAgentAndroid.java
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -157,16 +157,18 @@ public class SUTAgentAndroid extends Act
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.main);
 
         fixScreenOrientation();
 
         DoCommand dc = new DoCommand(getApplication());
 
+        dc.FixDataLocalPermissions();
+
         // Get configuration settings from "ini" file
         File dir = getFilesDir();
         File iniFile = new File(dir, "SUTAgent.ini");
         String sIniFile = iniFile.getAbsolutePath();
 
         String lc = dc.GetIniData("General", "LogCommands", sIniFile);
         if (lc != "" && Integer.parseInt(lc) == 1) {
             SUTAgentAndroid.LogCommands = true;
--- a/build/moz.build
+++ b/build/moz.build
@@ -7,18 +7,16 @@
 if CONFIG['OS_ARCH'] not in ('WINNT', 'OS2'):
     DIRS += ['unix']
 elif CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['win32']
 
 if CONFIG['STLPORT_SOURCES']:
     DIRS += ['stlport']
 
-DIRS += ['pgo']
-
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     TEST_DIRS += [
         'mobile/sutagent/android',
         'mobile/sutagent/android/watcher',
         'mobile/sutagent/android/ffxcp',
         'mobile/sutagent/android/fencp',
         'mobile/robocop',
     ]
deleted file mode 100644
--- a/build/pgo/Makefile.in
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEPTH		= @DEPTH@
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-relativesrcdir = @relativesrcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-include $(topsrcdir)/config/rules.mk
-
-# We install to _profile/pgo
-TARGET_DEPTH = ../..
-include $(topsrcdir)/build/automation-build.mk
-
-# Need to override the browser_path from binary-location.mk (included via automation-build.mk)
-# since we want to run from e.g. dist/firefox rather than dist/bin
-ifeq ($(OS_ARCH),Darwin)
-browser_path = \"$(TARGET_DIST)/$(MOZ_APP_NAME)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/$(PROGRAM)\"
-else
-browser_path = \"$(TARGET_DIST)/$(MOZ_APP_NAME)/$(PROGRAM)\"
-endif
-   
-# Stuff to make a build with a profile
-
-_PGO_FILES = 	\
-  automation.py \
-  $(topsrcdir)/build/automationutils.py \
-  $(topsrcdir)/testing/profiles/prefs_general.js \
-  profileserver.py \
-  genpgocert.py \
-  index.html \
-  server-locations.txt \
-  favicon.ico \
-  $(NULL)
-
-genpgocert.py: genpgocert.py.in
-	$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
-	$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@
-
-GARBAGE += genpgocert.py
-
-libs:: $(_PGO_FILES)
-	$(INSTALL) $^ $(_PROFILE_DIR)
-
-genservercert::
-	$(PYTHON) $(DEPTH)/_profile/pgo/genpgocert.py --gen-server
deleted file mode 100644
--- a/build/pgo/blueprint/Makefile.in
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEPTH		= @DEPTH@
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_PROFILE_DIR = $(DEPTH)/_profile/pgo/blueprint
-
-_PGO_FILES = 	\
-  sample.html \
-  elements.html \
-  forms.html \
-  grid.html \
-  test.jpg \
-  test-small.jpg \
-  valid.png \
-  screen.css \
-  print.css \
-  grid.png \
-  fancytype-screen.css \
-  $(NULL)
-
-libs:: $(_PGO_FILES)
-	$(INSTALL) $^ $(_PROFILE_DIR)
\ No newline at end of file
deleted file mode 100644
--- a/build/pgo/blueprint/moz.build
+++ /dev/null
@@ -1,6 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/README
@@ -0,0 +1,9 @@
+The certificate authority and server certificates here are generated by $topsrcdir/build/pgo/genpgocert.py.
+
+You can generate a new CA cert by running:
+$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-ca
+
+You can generate new server certificates by running:
+$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-server
+
+These will place the new files in this directory where you can commit them.
rename from build/pgo/genpgocert.py.in
rename to build/pgo/genpgocert.py
--- a/build/pgo/genpgocert.py.in
+++ b/build/pgo/genpgocert.py
@@ -1,25 +1,29 @@
-#
+#!/usr/bin/env python
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-from automation import Automation
+# This script exists to generate the Certificate Authority and server
+# certificates used for SSL testing in Mochitest. The already generated
+# certs are located at $topsrcdir/build/pgo/certs/ .
+
+import mozinfo
 import os
+import random
 import re
 import shutil
+import subprocess
 import sys
+import tempfile
 
-#expand DIST_BIN = __XPC_BIN_PATH__
-#expand BIN_SUFFIX = __BIN_SUFFIX__
-#expand PROFILE_DIR = __PROFILE_DIR__
-#expand CERTS_SRC_DIR = __CERTS_SRC_DIR__
-
-automation = Automation()
+from mozbuild.base import MozbuildObject
+from mozfile import NamedTemporaryFile
+from mozprofile.permissions import ServerLocations
 
 dbFiles = [
   re.compile("^cert[0-9]+\.db$"),
   re.compile("^key[0-9]+\.db$"),
   re.compile("^secmod\.db$")
 ]
 
 def unlinkDbFiles(path):
@@ -34,154 +38,150 @@ def dbFilesExist(path):
     for name in files:
       for dbFile in dbFiles:
         if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
           return True
   return False
 
 
 def runUtil(util, args, inputdata = None):
-  if inputdata:
-    proc = automation.Process([util] + args, env = automation.environment(), stdin = automation.PIPE)
-    proc.communicate(inputdata)
-    return proc.returncode
-  return automation.Process([util] + args, env = automation.environment()).wait()
+  env = os.environ.copy()
+  if mozinfo.os == "linux":
+    pathvar = "LD_LIBRARY_PATH"
+    app_path = os.path.dirname(util)
+    if pathvar in env:
+      env[pathvar] = "%s%s%s" % (app_path, os.pathsep, env[pathvar])
+    else:
+      env[pathvar] = app_path
+  proc = subprocess.Popen([util] + args, env=env,
+                          stdin=subprocess.PIPE if inputdata else None)
+  proc.communicate(inputdata)
+  return proc.returncode
 
 
 def createRandomFile(randomFile):
-  import random
-  file = open(randomFile, "wb");
   for count in xrange(0, 2048):
-    file.write(chr(random.randint(0, 255)))
-  file.close()
+    randomFile.write(chr(random.randint(0, 255)))
 
 
-def createCertificateAuthority(profileDir, srcDir):
-  certutil = DIST_BIN + "/certutil" + BIN_SUFFIX
-  pk12util = DIST_BIN + "/pk12util" + BIN_SUFFIX
+def createCertificateAuthority(build, srcDir):
+  certutil = build.get_binary_path(what="certutil")
+  pk12util = build.get_binary_path(what="pk12util")
 
-  tempDbDir = os.path.join(profileDir, ".temp")
-  if not os.path.exists(tempDbDir):
-    os.mkdir(tempDbDir)
-  
-  pwfilePath = os.path.join(tempDbDir, ".crtdbpw")
-  rndfilePath = os.path.join(tempDbDir, ".rndfile")
-  pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
-  pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
-  
-  pwfile = open(pwfilePath, "w")
-  pwfile.write("\n")
-  pwfile.close()
+  #TODO: mozfile.TemporaryDirectory
+  tempDbDir = tempfile.mkdtemp()
+  with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
+    pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
+    pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
 
-  unlinkDbFiles(tempDbDir)
+    pwfile.write("\n")
 
-  # Create temporary certification database for CA generation
-  status = runUtil(certutil, ["-N", "-d", tempDbDir, "-f", pwfilePath])
-  if status != 0:
-    return status
+    # Create temporary certification database for CA generation
+    status = runUtil(certutil, ["-N", "-d", tempDbDir, "-f", pwfile.name])
+    if status:
+      return status
+
+    createRandomFile(rndfile)
+    status = runUtil(certutil, ["-S", "-d", tempDbDir, "-s", "CN=Temporary Certificate Authority, O=Mozilla Testing, OU=Profile Guided Optimization", "-t", "C,,", "-x", "-m", "1", "-v", "120", "-n", "pgo temporary ca", "-2", "-f", pwfile.name, "-z", rndfile.name], "Y\n0\nN\n")
+    if status:
+      return status
 
-  createRandomFile(rndfilePath);
-  status = runUtil(certutil, ["-S", "-d", tempDbDir, "-s", "CN=Temporary Certificate Authority, O=Mozilla Testing, OU=Profile Guided Optimization", "-t", "C,,", "-x", "-m", "1", "-v", "120", "-n", "pgo temporary ca", "-2", "-f", pwfilePath, "-z", rndfilePath], "Y\n0\nN\n")
-  if status != 0:
-    return status
- 
-  status = runUtil(certutil, ["-L", "-d", tempDbDir, "-n", "pgo temporary ca", "-a", "-o", pgoCAPathSrc, "-f", pwfilePath])
-  if status != 0:
-    return status
- 
-  status = runUtil(pk12util, ["-o", pgoCAModulePathSrc, "-n", "pgo temporary ca", "-d", tempDbDir, "-w", pwfilePath, "-k", pwfilePath])
-  if status != 0:
-    return status
-    
-  unlinkDbFiles(tempDbDir)
-  os.unlink(pwfilePath)
-  os.unlink(rndfilePath)
-  os.rmdir(tempDbDir)
+    status = runUtil(certutil, ["-L", "-d", tempDbDir, "-n", "pgo temporary ca", "-a", "-o", pgoCAPathSrc, "-f", pwfile.name])
+    if status:
+      return status
+
+    status = runUtil(pk12util, ["-o", pgoCAModulePathSrc, "-n", "pgo temporary ca", "-d", tempDbDir, "-w", pwfile.name, "-k", pwfile.name])
+    if status:
+      return status
+
+  shutil.rmtree(tempDbDir)
   return 0
 
 
-def createSSLServerCertificate(profileDir, srcDir):
-  certutil = DIST_BIN + "/certutil" + BIN_SUFFIX
-  pk12util = DIST_BIN + "/pk12util" + BIN_SUFFIX
+def createSSLServerCertificate(build, srcDir):
+  certutil = build.get_binary_path(what="certutil")
+  pk12util = build.get_binary_path(what="pk12util")
 
-  pwfilePath = os.path.join(profileDir, ".crtdbpw")
-  rndfilePath = os.path.join(profileDir, ".rndfile")
-  pgoCAPath = os.path.join(srcDir, "pgoca.p12")
-  
-  pwfile = open(pwfilePath, "w")
-  pwfile.write("\n")
-  pwfile.close()
+  with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
+    pgoCAPath = os.path.join(srcDir, "pgoca.p12")
+
+    pwfile.write("\n")
+
+    if not dbFilesExist(srcDir):
+      # Make sure all DB files from src are really deleted
+      unlinkDbFiles(srcDir)
 
-  if not dbFilesExist(srcDir):
-    # Make sure all DB files from src are really deleted
-    unlinkDbFiles(srcDir)
-    
-    # Create certification database for ssltunnel
-    status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfilePath])
-    if status != 0:
-      return status
-  
-    status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfilePath, "-d", srcDir, "-k", pwfilePath])
-    if status != 0:
-      return status
+      # Create certification database for ssltunnel
+      status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfile.name])
+      if status:
+        return status
+
+      status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfile.name, "-d", srcDir, "-k", pwfile.name])
+      if status:
+        return status
+
+    # Generate automatic certificate
+    locations = ServerLocations(os.path.join(build.topsrcdir,
+                                             "build", "pgo",
+                                             "server-locations.txt"))
+    iterator = iter(locations)
+
+    # Skips the first entry, I don't know why: bug 879740
+    iterator.next()
 
-  # Generate automatic certificate
-  locations = automation.readLocations(os.path.join(profileDir, "server-locations.txt"))
-  locations.pop(0)
-  locationsParam = ""
-  firstLocation = ""
-  for loc in locations:
-    if loc.scheme == "https" and "nocert" not in loc.options:
-      customCertOption = False
-      customCertRE = re.compile("^cert=(?:\w+)")
-      for option in loc.options:
-        match = customCertRE.match(option)
-        if match:
-          customCertOption = True
-          break
+    locationsParam = ""
+    firstLocation = ""
+    for loc in iterator:
+      if loc.scheme == "https" and "nocert" not in loc.options:
+        customCertOption = False
+        customCertRE = re.compile("^cert=(?:\w+)")
+        for option in loc.options:
+          match = customCertRE.match(option)
+          if match:
+            customCertOption = True
+            break
+
+        if not customCertOption:
+          if len(locationsParam) > 0:
+            locationsParam += ","
+          locationsParam += loc.host
 
-      if not customCertOption:
-        if len(locationsParam) > 0:
-          locationsParam += ","
-        locationsParam += loc.host
-        
-        if firstLocation == "":
-          firstLocation = loc.host
-      
-  if firstLocation == "":
-    print "Nothing to generate, no automatic secure hosts specified"
-  else:
-    createRandomFile(rndfilePath);
-    
-    runUtil(certutil, ["-D", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfilePath, "-f", pwfilePath])
-    # Ignore the result, the certificate may not be present when new database is being built
-    
-    status = runUtil(certutil, ["-S", "-s", "CN=%s" % firstLocation, "-t", "Pu,,", "-c", "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v", "120", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfilePath, "-f", pwfilePath])
-    if status != 0:
-      return status
-    
-  os.unlink(pwfilePath)
-  os.unlink(rndfilePath)
+          if firstLocation == "":
+            firstLocation = loc.host
+
+    if not firstLocation:
+      print "Nothing to generate, no automatic secure hosts specified"
+    else:
+      createRandomFile(rndfile)
+
+      runUtil(certutil, ["-D", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
+      # Ignore the result, the certificate may not be present when new database is being built
+
+      status = runUtil(certutil, ["-S", "-s", "CN=%s" % firstLocation, "-t", "Pu,,", "-c", "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v", "120", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
+      if status:
+        return status
+
   return 0
 
-
 if len(sys.argv) == 1:
   print "Specify --gen-server or --gen-ca"
   sys.exit(1)
 
+build = MozbuildObject.from_environment()
+certdir = os.path.join(build.topsrcdir, "build", "pgo", "certs")
 if sys.argv[1] == "--gen-server":
-  certificateStatus = createSSLServerCertificate(PROFILE_DIR, CERTS_SRC_DIR)
-  if certificateStatus != 0:
+  certificateStatus = createSSLServerCertificate(build, certdir)
+  if certificateStatus:
     print "TEST-UNEXPECTED-FAIL | SSL Server Certificate generation"
-  
+
   sys.exit(certificateStatus)
-  
+
 if sys.argv[1] == "--gen-ca":
-  certificateStatus = createCertificateAuthority(PROFILE_DIR, CERTS_SRC_DIR)
-  if certificateStatus != 0:
+  certificateStatus = createCertificateAuthority(build, certdir)
+  if certificateStatus:
     print "TEST-UNEXPECTED-FAIL | Certificate Authority generation"
   else:
     print "\n\n"
     print "==================================================="
     print " IMPORTANT:"
     print " To use this new certificate authority in tests"
     print " run 'make' at testing/mochitest"
     print "==================================================="
deleted file mode 100644
--- a/build/pgo/js-input/Makefile.in
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEPTH		= @DEPTH@
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-include $(topsrcdir)/config/rules.mk
-
-_PROFILE_DIR = $(DEPTH)/_profile/pgo/js-input
-
-_PGO_FILES = 	\
-  3d-cube.html \
-  3d-morph.html \
-  3d-raytrace.html \
-  3d-thingy.html \
-  access-binary-trees.html \
-  access-fannkuch.html \
-  access-nbody.html \
-  access-nsieve.html \
-  bitops-3bit-bits-in-byte.html \
-  bitops-bits-in-byte.html \
-  bitops-bitwise-and.html \
-  bitops-nsieve-bits.html \
-  controlflow-recursive.html \
-  crypto-aes.html \
-  crypto-md5.html \
-  crypto-sha1.html \
-  crypto-otp.html \
-  date-format-tofte.html \
-  date-format-xparb.html \
-  math-cordic.html \
-  math-partial-sums.html \
-  math-spectral-norm.html \
-  regexp-dna.html \
-  string-base64.html \
-  string-fasta.html \
-  string-tagcloud.html \
-  string-unpack-code.html \
-  string-validate-input.html \
-  key.gif \
-  valid-xhtml10.png \
-  $(NULL)
-
-libs:: $(_PGO_FILES)
-	$(INSTALL) $^ $(_PROFILE_DIR)
deleted file mode 100644
--- a/build/pgo/js-input/moz.build
+++ /dev/null
@@ -1,6 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
deleted file mode 100644
--- a/build/pgo/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DIRS += ['blueprint', 'js-input']
--- a/build/pgo/profileserver.py
+++ b/build/pgo/profileserver.py
@@ -1,59 +1,71 @@
-#literal #!/usr/bin/python
+#!/usr/bin/python
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-import SimpleHTTPServer
-import SocketServer
+from mozprofile import FirefoxProfile, Profile, Preferences
+from mozprofile.permissions import ServerLocations
+from mozrunner import FirefoxRunner, CLI
+from mozhttpd import MozHttpd
+import json
 import socket
 import threading
 import os
 import sys
 import shutil
+import tempfile
 from datetime import datetime
-
-SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
-sys.path.insert(0, SCRIPT_DIR)
-from automation import Automation
-from automationutils import getDebuggerInfo, addCommonOptions
+from mozbuild.base import MozbuildObject
 
 PORT = 8888
-PROFILE_DIRECTORY = os.path.abspath(os.path.join(SCRIPT_DIR, "./pgoprofile"))
-MOZ_JAR_LOG_FILE = os.path.abspath(os.getenv("JARLOG_FILE"))
-os.chdir(SCRIPT_DIR)
-
-class EasyServer(SocketServer.TCPServer):
-  allow_reuse_address = True
 
 if __name__ == '__main__':
-  from optparse import OptionParser
-  automation = Automation()
+  cli = CLI()
+  debug_args, interactive = cli.debugger_arguments()
 
-  parser = OptionParser()
-  addCommonOptions(parser)
+  build = MozbuildObject.from_environment()
+  httpd = MozHttpd(port=PORT,
+                   docroot=os.path.join(build.topsrcdir, "build", "pgo"))
+  httpd.start(block=False)
 
-  options, args = parser.parse_args()
-
-  debuggerInfo = getDebuggerInfo(".", options.debugger, options.debuggerArgs,
-          options.debuggerInteractive)
+  locations = ServerLocations()
+  locations.add_host(host='127.0.0.1',
+                     port=PORT,
+                     options='primary,privileged')
 
-  httpd = EasyServer(("", PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
-  t = threading.Thread(target=httpd.serve_forever)
-  t.setDaemon(True) # don't hang on exit
-  t.start()
-  
-  automation.setServerInfo("localhost", PORT)
-  automation.initializeProfile(PROFILE_DIRECTORY)
-  browserEnv = automation.environment()
-  browserEnv["XPCOM_DEBUG_BREAK"] = "warn"
-  browserEnv["MOZ_JAR_LOG_FILE"] = MOZ_JAR_LOG_FILE
+  #TODO: mozfile.TemporaryDirectory
+  profilePath = tempfile.mkdtemp()
+  try:
+    #TODO: refactor this into mozprofile
+    prefpath = os.path.join(build.topsrcdir, "testing", "profiles", "prefs_general.js")
+    prefs = {}
+    prefs.update(Preferences.read_prefs(prefpath))
+    interpolation = { "server": "%s:%d" % httpd.httpd.server_address,
+                      "OOP": "false"}
+    prefs = json.loads(json.dumps(prefs) % interpolation)
+    for pref in prefs:
+      prefs[pref] = Preferences.cast(prefs[pref])
+    profile = FirefoxProfile(profile=profilePath,
+                             preferences=prefs,
+                             #addons=[os.path.join(here, 'extension')],
+                             locations=locations)
 
-  url = "http://localhost:%d/index.html" % PORT
-  appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)
-  status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
-                             debuggerInfo=debuggerInfo,
-                             # the profiling HTML doesn't output anything,
-                             # so let's just run this without a timeout
-                             timeout = None)
-  sys.exit(status)
+    env = os.environ.copy()
+    env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
+    env["XPCOM_DEBUG_BREAK"] = "warn"
+    jarlog = os.getenv("JARLOG_FILE")
+    if jarlog:
+      env["MOZ_JAR_LOG_FILE"] = os.path.abspath(jarlog)
+      print "jarlog: %s" % env["MOZ_JAR_LOG_FILE"]
+
+    cmdargs = ["http://localhost:%d/index.html" % PORT]
+    runner = FirefoxRunner(profile=profile,
+                           binary=build.get_binary_path(where="staged-package"),
+                           cmdargs=cmdargs,
+                           env=env)
+    runner.start(debug_args=debug_args, interactive=interactive)
+    runner.wait()
+    httpd.stop()
+  finally:
+    shutil.rmtree(profilePath)
--- a/configure.in
+++ b/configure.in
@@ -57,16 +57,17 @@ NSS_VERSION=3
 
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=1.2.0
 PERL_VERSION=5.006
 CAIRO_VERSION=1.10
 PANGO_VERSION=1.14.0
 GTK2_VERSION=2.10.0
+GTK3_VERSION=3.0.0
 WINDRES_VERSION=2.14.90
 W32API_VERSION=3.14
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 GIO_VERSION=2.20
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
@@ -4473,23 +4474,25 @@ MOZ_ARG_HEADER(Toolkit Options)
 	MOZ_ARG_ENABLE_STRING(default-toolkit,
 	[  --enable-default-toolkit=TK
                           Select default toolkit
                           Platform specific defaults:
                             Mac OS X - cairo-cocoa
                             OS/2 - cairo-os2
                             Win32 - cairo-windows
                             * - cairo-gtk2
+                            * - cairo-gtk3
                             * - cairo-qt],
     [ _DEFAULT_TOOLKIT=$enableval ],
     [ _DEFAULT_TOOLKIT=$_PLATFORM_DEFAULT_TOOLKIT])
 
     if test "$_DEFAULT_TOOLKIT" = "cairo-windows" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-x11" \
+        -o "$_DEFAULT_TOOLKIT" = "cairo-gtk3" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-qt" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-os2" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-uikit" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-android" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gonk"
     then
         dnl nglayout only supports building with one toolkit,
@@ -4516,18 +4519,39 @@ cairo-windows)
     MOZ_WEBGL=1
     MOZ_PDF_PRINTING=1
     MOZ_INSTRUMENT_EVENT_LOOP=1
     if test -n "$GNU_CC"; then
         MOZ_FOLD_LIBS=
     fi
     ;;
 
+cairo-gtk3)
+    MOZ_WIDGET_TOOLKIT=gtk3
+    MOZ_ENABLE_GTK=1
+    MOZ_ENABLE_GTK3=1
+    MOZ_ENABLE_XREMOTE=1
+    MOZ_WEBGL=1
+    MOZ_GL_DEFAULT_PROVIDER=GLX
+
+    AC_DEFINE(MOZ_X11)
+    MOZ_X11=1
+    USE_FC_FREETYPE=1
+
+    TK_CFLAGS='$(MOZ_GTK3_CFLAGS)'
+    TK_LIBS='$(MOZ_GTK3_LIBS)'
+    MOZ_WIDGET_GTK=3
+    AC_DEFINE_UNQUOTED(MOZ_WIDGET_GTK,$MOZ_WIDGET_GTK)
+    MOZ_PDF_PRINTING=1
+    MOZ_INSTRUMENT_EVENT_LOOP=1
+    ;;
+
 cairo-gtk2|cairo-gtk2-x11)
     MOZ_WIDGET_TOOLKIT=gtk2
+    MOZ_ENABLE_GTK=1
     MOZ_ENABLE_GTK2=1
     MOZ_ENABLE_XREMOTE=1
     MOZ_WEBGL=1
     MOZ_GL_DEFAULT_PROVIDER=GLX
 
     AC_DEFINE(MOZ_X11)
     MOZ_X11=1
     USE_FC_FREETYPE=1
@@ -4633,16 +4657,19 @@ if test "$MOZ_ENABLE_XREMOTE"; then
     AC_DEFINE(MOZ_ENABLE_XREMOTE)
 fi
 
 if test "$MOZ_INSTRUMENT_EVENT_LOOP"; then
    AC_DEFINE(MOZ_INSTRUMENT_EVENT_LOOP)
 fi
 
 if test "$COMPILE_ENVIRONMENT"; then
+  if test "$MOZ_ENABLE_GTK3"; then
+    PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
+  fi
   if test "$MOZ_ENABLE_GTK2"; then
     if test "$MOZ_X11"; then
       GDK_PACKAGES=gdk-x11-2.0
     fi
 
     PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
   fi
 
@@ -4660,17 +4687,17 @@ MOZ_ARG_WITH_BOOL(arm-kuser,
 if test -n "$USE_ARM_KUSER"; then
    AC_DEFINE(USE_ARM_KUSER)
 fi
 
 dnl ========================================================
 dnl = startup-notification support module
 dnl ========================================================
 
-if test "$MOZ_ENABLE_GTK2"
+if test "$MOZ_ENABLE_GTK"
 then
     MOZ_ENABLE_STARTUP_NOTIFICATION=
 
     MOZ_ARG_ENABLE_BOOL(startup-notification,
     [  --enable-startup-notification
                           Enable startup-notification support (default: disabled) ],
         MOZ_ENABLE_STARTUP_NOTIFICATION=force,
         MOZ_ENABLE_STARTUP_NOTIFICATION=)
@@ -4800,23 +4827,27 @@ incorrect])
     fi
 fi
 
 AC_SUBST(GTK_CONFIG)
 AC_SUBST(TK_CFLAGS)
 AC_SUBST(TK_LIBS)
 
 AC_SUBST(MOZ_ENABLE_GTK2)
+AC_SUBST(MOZ_ENABLE_GTK3)
+AC_SUBST(MOZ_ENABLE_GTK)
 AC_SUBST(MOZ_ENABLE_QT)
 AC_SUBST(MOZ_ENABLE_QTNETWORK)
 AC_SUBST(MOZ_ENABLE_QMSYSTEM2)
 AC_SUBST(MOZ_ENABLE_QTMOBILITY)
 AC_SUBST(MOZ_ENABLE_XREMOTE)
 AC_SUBST(MOZ_GTK2_CFLAGS)
 AC_SUBST(MOZ_GTK2_LIBS)
+AC_SUBST(MOZ_GTK3_CFLAGS)
+AC_SUBST(MOZ_GTK3_LIBS)
 AC_SUBST(MOZ_WIDGET_GTK)
 AC_SUBST(MOZ_QT_CFLAGS)
 AC_SUBST(MOZ_QT_LIBS)
 
 AC_SUBST(MOC)
 AC_SUBST(RCC)
 
 AC_SUBST(MOZ_X11)
@@ -4899,17 +4930,17 @@ dnl ====================================
 MOZ_ARG_DISABLE_BOOL(pango,
 [  --disable-pango         Disable usage of Pango ],
     MOZ_PANGO=,
     MOZ_PANGO=1)
 
 dnl ========================================================
 dnl = Pango
 dnl ========================================================
-if test "$MOZ_ENABLE_GTK2" -o "$MOZ_ENABLE_QT"
+if test "$MOZ_ENABLE_GTK" -o "$MOZ_ENABLE_QT"
 then
     AC_SUBST(MOZ_PANGO)
 
     if test "$MOZ_PANGO"
     then
         PKG_CHECK_MODULES(_PANGOCHK, pango >= $PANGO_VERSION)
 
         PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION pangocairo >= $PANGO_VERSION)
@@ -4926,17 +4957,17 @@ fi
 dnl ========================================================
 dnl = GnomeVFS, GIO and GConf support module
 dnl ========================================================
 
 if test "$MOZ_X11"
 then
     dnl build the GIO extension by default only when the
     dnl GTK2 toolkit is in use.
-    if test "$MOZ_ENABLE_GTK2"
+    if test "$MOZ_ENABLE_GTK"
     then
         MOZ_ENABLE_GIO=1
         MOZ_ENABLE_GCONF=1
     fi
 
     dnl ========================================================
     dnl = GnomeVFS support module
     dnl ========================================================
@@ -4967,17 +4998,17 @@ then
     dnl ========================================================
     dnl = GIO support module
     dnl ========================================================
     MOZ_ARG_DISABLE_BOOL(gio,
     [  --disable-gio           Disable GIO support],
         MOZ_ENABLE_GIO=,
         MOZ_ENABLE_GIO=force)
 
-    if test "$MOZ_ENABLE_GIO" -a "$MOZ_ENABLE_GTK2"
+    if test "$MOZ_ENABLE_GIO" -a "$MOZ_ENABLE_GTK"
     then
         PKG_CHECK_MODULES(_GTKCHECK, gtk+-2.0 >= 2.14, ,
                           [AC_MSG_ERROR([* * * Could not find gtk+-2.0 > 2.14. Required for build with gio.])])
         PKG_CHECK_MODULES(MOZ_GIO, gio-2.0 >= $GIO_VERSION,[
             MOZ_GIO_LIBS=`echo $MOZ_GIO_LIBS | sed 's/-llinc\>//'`
             MOZ_ENABLE_GIO=1
             AC_DEFINE(MOZ_ENABLE_GIO)
         ],[
@@ -5023,17 +5054,17 @@ then
     AC_SUBST(MOZ_GCONF_CFLAGS)
     AC_SUBST(MOZ_GCONF_LIBS)
 fi
 
 dnl ========================================================
 dnl = libproxy support
 dnl ========================================================
 
-if test "$MOZ_ENABLE_GTK2" -o "$MOZ_ENABLE_QT"
+if test "$MOZ_ENABLE_GTK" -o "$MOZ_ENABLE_QT"
 then
     MOZ_ENABLE_LIBPROXY=
 
     MOZ_ARG_ENABLE_BOOL(libproxy,
     [  --enable-libproxy         Enable libproxy support ],
     MOZ_ENABLE_LIBPROXY=1,
     MOZ_ENABLE_LIBPROXY=)
 
@@ -5056,17 +5087,17 @@ then
     MOZ_ENABLE_GNOME_COMPONENT=1
 fi
 AC_SUBST(MOZ_ENABLE_GNOME_COMPONENT)
 
 dnl ========================================================
 dnl = libgnomeui support module
 dnl ========================================================
 
-if test "$MOZ_ENABLE_GTK2"
+if test "$MOZ_ENABLE_GTK"
 then
     MOZ_ARG_ENABLE_BOOL(gnomeui,
     [  --enable-gnomeui        Enable libgnomeui instead of GIO & GTK for icon theme support ],
         MOZ_ENABLE_GNOMEUI=force,
         MOZ_ENABLE_GNOMEUI=)
 
     if test "$MOZ_ENABLE_GNOMEUI"
     then
@@ -5089,17 +5120,17 @@ fi
 
 AC_SUBST(MOZ_ENABLE_GNOMEUI)
 AC_SUBST(MOZ_GNOMEUI_CFLAGS)
 
 dnl ========================================================
 dnl = dbus support
 dnl ========================================================
 
-if test "$MOZ_ENABLE_GTK2" -o "$MOZ_ENABLE_QT"
+if test "$MOZ_ENABLE_GTK" -o "$MOZ_ENABLE_QT"
 then
     MOZ_ENABLE_DBUS=1
 
     MOZ_ARG_DISABLE_BOOL(dbus,
     [  --disable-dbus          Disable dbus support ],
         MOZ_ENABLE_DBUS=,
         MOZ_ENABLE_DBUS=1)
 
@@ -5972,17 +6003,17 @@ dnl ====================================
 case $target in
 i?86-*-mingw*|x86_64-*-mingw*)
   MOZ_CRASHREPORTER=1
   ;;
 i?86-apple-darwin*|x86_64-apple-darwin*)
   MOZ_CRASHREPORTER=1
   ;;
 i?86-*-linux*|x86_64-*-linux*|arm-*-linux*)
-  if test "$MOZ_ENABLE_GTK2"; then
+  if test "$MOZ_ENABLE_GTK"; then
     MOZ_CRASHREPORTER=1
   fi
   ;;
 *-android*|*-linuxandroid*)
   MOZ_CRASHREPORTER=1
   ;;
 *solaris*)
   MOZ_CRASHREPORTER=1
@@ -8996,17 +9027,17 @@ elif test "$OS_ARCH" != "WINNT" -a "$OS_
   AC_DEFINE(XP_UNIX)
 fi
 
 if test "$MOZ_DEBUG"; then
     AC_DEFINE(MOZ_REFLOW_PERF)
     AC_DEFINE(MOZ_REFLOW_PERF_DSP)
 fi
 
-if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK2" ; then
+if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK" ; then
     AC_DEFINE(MOZ_ACCESSIBILITY_ATK)
     ATK_FULL_VERSION=`$PKG_CONFIG --modversion atk`
     ATK_MAJOR_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $1 }'`
     ATK_MINOR_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $2 }'`
     ATK_REV_VERSION=`echo ${ATK_FULL_VERSION} | $AWK -F\. '{ print $3 }'`
     AC_DEFINE_UNQUOTED(ATK_MAJOR_VERSION, $ATK_MAJOR_VERSION)
     AC_DEFINE_UNQUOTED(ATK_MINOR_VERSION, $ATK_MINOR_VERSION)
     AC_DEFINE_UNQUOTED(ATK_REV_VERSION, $ATK_REV_VERSION)
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6424,16 +6424,19 @@ nsContentUtils::ReleaseWrapper(void* aSc
 {
   if (aCache->PreservingWrapper()) {
     // PreserveWrapper puts new DOM bindings in the JS holders hash, but they
     // can also be in the DOM expando hash, so we need to try to remove them
     // from both here.
     JSObject* obj = aCache->GetWrapperPreserveColor();
     if (aCache->IsDOMBinding() && obj && js::IsProxy(obj)) {
         DOMProxyHandler::GetAndClearExpandoObject(obj);
+        if (!aCache->PreservingWrapper()) {
+          return;
+        }
     }
     aCache->SetPreservingWrapper(false);
     DropJSObjects(aScriptObjectHolder);
   }
 }
 
 // static
 int32_t
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -829,16 +829,17 @@ GK_ATOM(parentfocused, "parentfocused")
 GK_ATOM(parsetype, "parsetype")
 GK_ATOM(pattern, "pattern")
 GK_ATOM(patternSeparator, "pattern-separator")
 GK_ATOM(perMille, "per-mille")
 GK_ATOM(percent, "percent")
 GK_ATOM(persist, "persist")
 GK_ATOM(phase, "phase")
 GK_ATOM(ping, "ping")
+GK_ATOM(pinned,"pinned")
 GK_ATOM(placeholder, "placeholder")
 GK_ATOM(plaintext, "plaintext")
 GK_ATOM(playbackrate, "playbackrate")
 GK_ATOM(pointSize, "point-size")
 GK_ATOM(poly, "poly")
 GK_ATOM(polygon, "polygon")
 GK_ATOM(popup, "popup")
 GK_ATOM(popupalign, "popupalign")
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -11,16 +11,17 @@
 #include "AccessCheck.h"
 #include "nsIConsoleService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsError.h"
 #include "nsIGfxInfo.h"
+#include "nsIWidget.h"
 
 #include "nsIPropertyBag.h"
 #include "nsIVariant.h"
 
 #include "imgIEncoder.h"
 
 #include "gfxContext.h"
 #include "gfxPattern.h"
@@ -44,16 +45,20 @@
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/ProcessPriorityManager.h"
 
 #include "Layers.h"
 
+#ifdef MOZ_WIDGET_GONK
+#include "mozilla/layers/ShadowLayers.h"
+#endif
+
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
 
 NS_IMETHODIMP
 WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
@@ -458,16 +463,30 @@ WebGLContext::SetDimensions(int32_t widt
 
     // we should really have this behind a
     // |gfxPlatform::GetPlatform()->GetScreenDepth() == 16| check, but
     // for now it's just behind a pref for testing/evaluation.
     caps.bpp16 = prefer16bit;
 
     caps.preserve = mOptions.preserveDrawingBuffer;
 
+#ifdef MOZ_WIDGET_GONK
+    nsIWidget *docWidget = nsContentUtils::WidgetForDocument(mCanvasElement->OwnerDoc());
+    if (docWidget) {
+        layers::LayerManager *layerManager = docWidget->GetLayerManager();
+        if (layerManager) {
+            // XXX we really want "AsSurfaceAllocator" here for generality
+            layers::ShadowLayerForwarder *forwarder = layerManager->AsShadowForwarder();
+            if (forwarder) {
+                caps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
+            }
+        }
+    }
+#endif
+
     bool forceMSAA =
         Preferences::GetBool("webgl.msaa-force", false);
 
     int32_t status;
     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     if (mOptions.antialias &&
         gfxInfo &&
         NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_MSAA, &status))) {
--- a/content/events/src/moz.build
+++ b/content/events/src/moz.build
@@ -33,16 +33,17 @@ CPP_SOURCES += [
     'nsDOMCommandEvent.cpp',
     'nsDOMCompositionEvent.cpp',
     'nsDOMDataContainerEvent.cpp',
     'nsDOMDataTransfer.cpp',
     'nsDOMDeviceMotionEvent.cpp',
     'nsDOMDragEvent.cpp',
     'nsDOMEvent.cpp',
     'nsDOMEventTargetHelper.cpp',
+    'nsDOMFocusEvent.cpp',
     'nsDOMKeyboardEvent.cpp',
     'nsDOMMessageEvent.cpp',
     'nsDOMMouseEvent.cpp',
     'nsDOMMouseScrollEvent.cpp',
     'nsDOMMutationEvent.cpp',
     'nsDOMNotifyAudioAvailableEvent.cpp',
     'nsDOMNotifyPaintEvent.cpp',
     'nsDOMScrollAreaEvent.cpp',
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -156,16 +156,19 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
         static_cast<nsMouseEvent_base*>(tmp->mEvent)->relatedTarget = nullptr;
         break;
       case NS_CLIPBOARD_EVENT:
         static_cast<nsClipboardEvent*>(tmp->mEvent)->clipboardData = nullptr;
         break;
       case NS_MUTATION_EVENT:
         static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode = nullptr;
         break;
+      case NS_FOCUS_EVENT:
+        static_cast<nsFocusEvent*>(tmp->mEvent)->relatedTarget = nullptr;
+        break;
       default:
         break;
     }
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mExplicitOriginalTarget);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@@ -198,16 +201,21 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
         cb.NoteXPCOMChild(
           static_cast<nsClipboardEvent*>(tmp->mEvent)->clipboardData);
         break;
       case NS_MUTATION_EVENT:
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedNode");
         cb.NoteXPCOMChild(
           static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode);
         break;
+      case NS_FOCUS_EVENT:
+        NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->relatedTarget");
+        cb.NoteXPCOMChild(
+          static_cast<nsFocusEvent*>(tmp->mEvent)->relatedTarget);
+        break;
       default:
         break;
     }
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMFocusEvent.cpp
@@ -0,0 +1,87 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsDOMFocusEvent.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+NS_IMPL_ISUPPORTS_INHERITED1(nsDOMFocusEvent, nsDOMUIEvent, nsIDOMFocusEvent)
+
+nsDOMFocusEvent::nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
+                                 nsPresContext* aPresContext, nsFocusEvent* aEvent)
+  : nsDOMUIEvent(aOwner, aPresContext, aEvent ?
+                 static_cast<nsGUIEvent*>(aEvent) :
+                 static_cast<nsGUIEvent*>(new nsFocusEvent(false, NS_FOCUS_CONTENT)))
+{
+  if (aEvent) {
+    mEventIsInternal = false;
+  } else {
+    mEventIsInternal = true;
+    mEvent->time = PR_Now();
+  }
+  SetIsDOMBinding();
+}
+
+nsDOMFocusEvent::~nsDOMFocusEvent()
+{
+  if (mEventIsInternal && mEvent) {
+    delete static_cast<nsFocusEvent*>(mEvent);
+    mEvent = nullptr;
+  }
+}
+
+/* readonly attribute nsIDOMEventTarget relatedTarget; */
+NS_IMETHODIMP
+nsDOMFocusEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
+{
+  NS_ENSURE_ARG_POINTER(aRelatedTarget);
+  NS_IF_ADDREF(*aRelatedTarget = GetRelatedTarget());
+  return NS_OK;
+}
+
+mozilla::dom::EventTarget*
+nsDOMFocusEvent::GetRelatedTarget()
+{
+  return static_cast<nsFocusEvent*>(mEvent)->relatedTarget;
+}
+
+nsresult
+nsDOMFocusEvent::InitFocusEvent(const nsAString& aType,
+                                bool aCanBubble,
+                                bool aCancelable,
+                                nsIDOMWindow* aView,
+                                int32_t aDetail,
+                                mozilla::dom::EventTarget* aRelatedTarget)
+{
+  nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
+  NS_ENSURE_SUCCESS(rv, rv);
+  static_cast<nsFocusEvent*>(mEvent)->relatedTarget = aRelatedTarget;
+  return NS_OK;
+}
+
+already_AddRefed<nsDOMFocusEvent>
+nsDOMFocusEvent::Constructor(const mozilla::dom::GlobalObject& aGlobal,
+                             const nsAString& aType,
+                             const mozilla::dom::FocusEventInit& aParam,
+                             mozilla::ErrorResult& aRv)
+{
+  nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.Get());
+  nsRefPtr<nsDOMFocusEvent> e = new nsDOMFocusEvent(t, nullptr, nullptr);
+  bool trusted = e->Init(t);
+  aRv = e->InitFocusEvent(aType, aParam.mBubbles, aParam.mCancelable, aParam.mView,
+                          aParam.mDetail, aParam.mRelatedTarget);
+  e->SetTrusted(trusted);
+  return e.forget();
+}
+
+nsresult NS_NewDOMFocusEvent(nsIDOMEvent** aInstancePtrResult,
+                             mozilla::dom::EventTarget* aOwner,
+                             nsPresContext* aPresContext,
+                             nsFocusEvent* aEvent)
+{
+  nsDOMFocusEvent* it = new nsDOMFocusEvent(aOwner, aPresContext, aEvent);
+  return CallQueryInterface(it, aInstancePtrResult);
+}
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMFocusEvent.h
@@ -0,0 +1,47 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* 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/. */
+#ifndef nsDOMFocusEvent_h_
+#define nsDOMFocusEvent_h_
+
+#include "nsDOMUIEvent.h"
+#include "nsIDOMFocusEvent.h"
+#include "mozilla/dom/FocusEventBinding.h"
+
+class nsDOMFocusEvent : public nsDOMUIEvent,
+                        public nsIDOMFocusEvent
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMFOCUSEVENT
+
+  // Forward to base class
+  NS_FORWARD_TO_NSDOMUIEVENT
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
+  {
+    return mozilla::dom::FocusEventBinding::Wrap(aCx, aScope, this);
+  }
+
+  nsDOMFocusEvent(mozilla::dom::EventTarget* aOwner,
+                  nsPresContext* aPresContext, nsFocusEvent* aEvent);
+
+  mozilla::dom::EventTarget* GetRelatedTarget();
+
+  static already_AddRefed<nsDOMFocusEvent> Constructor(const mozilla::dom::GlobalObject& aGlobal,
+                                                       const nsAString& aType,
+                                                       const mozilla::dom::FocusEventInit& aParam,
+                                                       mozilla::ErrorResult& aRv);
+protected:
+  nsresult InitFocusEvent(const nsAString& aType,
+                          bool aCanBubble,
+                          bool aCancelable,
+                          nsIDOMWindow* aView,
+                          int32_t aDetail,
+                          mozilla::dom::EventTarget* aRelatedTarget);
+  ~nsDOMFocusEvent();
+};
+
+#endif /* !defined(nsDOMFocusEvent_h_) */
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -725,16 +725,19 @@ nsEventDispatcher::CreateEvent(mozilla::
                                     static_cast<nsKeyEvent*>(aEvent));
     case NS_COMPOSITION_EVENT:
       return NS_NewDOMCompositionEvent(
         aDOMEvent, aOwner,
         aPresContext, static_cast<nsCompositionEvent*>(aEvent));
     case NS_MOUSE_EVENT:
       return NS_NewDOMMouseEvent(aDOMEvent, aOwner, aPresContext,
                                  static_cast<nsInputEvent*>(aEvent));
+    case NS_FOCUS_EVENT:
+      return NS_NewDOMFocusEvent(aDOMEvent, aOwner, aPresContext,
+                                 static_cast<nsFocusEvent*>(aEvent));
     case NS_MOUSE_SCROLL_EVENT:
       return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext,
                                  static_cast<nsInputEvent*>(aEvent));
     case NS_WHEEL_EVENT:
       return NS_NewDOMWheelEvent(aDOMEvent, aOwner, aPresContext,
                                  static_cast<widget::WheelEvent*>(aEvent));
     case NS_DRAG_EVENT:
       return NS_NewDOMDragEvent(aDOMEvent, aOwner, aPresContext,
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -98,16 +98,17 @@ MOCHITEST_FILES = \
 		test_bug603008.html \
 		test_bug716822.html \
 		test_bug742376.html \
 		test_dragstart.html \
 		test_bug812744.html \
 		test_addEventListenerExtraArg.html \
 		test_focus_disabled.html \
 		test_bug847597.html \
+		test_bug855741.html \
 		$(NULL)
 
 MOCHITEST_CHROME_FILES = \
 		test_bug336682_2.xul \
 		test_bug336682.js \
 		test_bug586961.xul \
 		test_bug415498.xul \
 		bug415498-doc1.html \
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug855741.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=855741
+-->
+<head>
+  <title>Test for Bug 855741</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/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>
+<input type="text" id="testTarget"  value="focus">
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 855741 **/
+function testFocusEvent(event) {
+  ok(('relatedTarget' in event), 'FocusEvent.relatedTarget exists');
+
+  if (event.construct_test == true) {
+    ok(event.relatedTarget == $("content"), 'FocusEvent.relatedTarget is ' + $("content").id);
+  }
+}
+
+function testUIEvent(event) {
+  ok((event.detail == 0),
+     'UIEvent.detail should be 0 in ' + event.target.value + ' event');
+
+  ok((event.defaultView == null),
+     'UIEvent.defaultView should be null in ' + event.target.value + ' event');
+}
+
+function testEventType(event, type) {
+  ok((event.type == type), 'Event.type match: ' + type);
+}
+
+function eventhandle(event) {
+  testFocusEvent(event);
+  testUIEvent(event);
+  testEventType(event, event.target.value);
+
+  if (event.target.value == 'blur') {
+    event.target.value = 'focus';
+  } else {
+    event.target.value = 'blur';
+  }
+}
+
+//
+// event handler:
+//
+$("testTarget").addEventListener("focus", eventhandle, true);
+$("testTarget").addEventListener("blur", eventhandle, true);
+
+//
+// FocusEvent structure test
+//
+$("testTarget").focus();
+$("testTarget").blur();
+
+//
+// Focus/Blur constructor test
+//
+var focus_event = new FocusEvent("focus",
+                                 {bubbles: true,
+                                  cancelable: true,
+                                  relatedTarget: $("content")});
+focus_event.construct_test = true;
+
+var blur_event = new FocusEvent("blur",
+                                {bubbles: true,
+                                 cancelable: true,
+                                 relatedTarget: $("content")});
+blur_event.construct_test = true;
+
+// create cycle referece for leak test
+$("content").foo_focus = focus_event;
+$("content").foo_blur = blur_event;
+
+$("testTarget").dispatchEvent(focus_event);
+$("testTarget").dispatchEvent(blur_event);
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/media/AudioNodeEngine.cpp
+++ b/content/media/AudioNodeEngine.cpp
@@ -108,19 +108,19 @@ AudioBlockPanStereoToStereo(const float 
                             float aGainL, float aGainR, bool aIsOnTheLeft,
                             float aOutputL[WEBAUDIO_BLOCK_SIZE],
                             float aOutputR[WEBAUDIO_BLOCK_SIZE])
 {
   uint32_t i;
 
   if (aIsOnTheLeft) {
     for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
-      *aOutputL++ = *aInputL++ + *aInputR * aGainL;
+      *aOutputL++ = *aInputL++ + *aInputR++ * aGainL;
       *aOutputR++ = *aInputR++ * aGainR;
     }
   } else {
     for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
-      *aOutputL++ = *aInputL * aGainL;
+      *aOutputL++ = *aInputL++ * aGainL;
       *aOutputR++ = *aInputR++ + *aInputL++ * aGainR;
     }
   }
 }
 }
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -34,18 +34,18 @@ PRLogModuleInfo *gOmxDecoderLog;
 using namespace MPAPI;
 using namespace mozilla;
 
 namespace mozilla {
 namespace layers {
 
 VideoGraphicBuffer::VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
                                        android::MediaBuffer *aBuffer,
-                                       SurfaceDescriptor *aDescriptor)
-  : GraphicBufferLocked(*aDescriptor),
+                                       SurfaceDescriptor& aDescriptor)
+  : GraphicBufferLocked(aDescriptor),
     mMediaBuffer(aBuffer),
     mOmxDecoder(aOmxDecoder)
 {
   mMediaBuffer->add_ref();
 }
 
 VideoGraphicBuffer::~VideoGraphicBuffer()
 {
@@ -587,21 +587,21 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
     if ((mVideoBuffer->graphicBuffer().get())) {
       descriptor = mNativeWindow->getSurfaceDescriptorFromBuffer(mVideoBuffer->graphicBuffer().get());
     }
 
     if (descriptor) {
       // Change the descriptor's size to video's size. There are cases that
       // GraphicBuffer's size and actual video size is different.
       // See Bug 850566.
-      const mozilla::layers::SurfaceDescriptorGralloc& grallocDesc = descriptor->get_SurfaceDescriptorGralloc();
-      mozilla::layers::SurfaceDescriptor newDescriptor = mozilla::layers::SurfaceDescriptorGralloc(grallocDesc.bufferParent(),
-                                                               grallocDesc.bufferChild(), nsIntSize(mVideoWidth, mVideoHeight), grallocDesc.external());
+      mozilla::layers::SurfaceDescriptorGralloc newDescriptor = descriptor->get_SurfaceDescriptorGralloc();
+      newDescriptor.size() = nsIntSize(mVideoWidth, mVideoHeight);
 
-      aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, &newDescriptor);
+      mozilla::layers::SurfaceDescriptor descWrapper(newDescriptor);
+      aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, descWrapper);
       aFrame->mRotation = mVideoRotation;
       aFrame->mTimeUs = timeUs;
       aFrame->mKeyFrame = keyFrame;
       aFrame->Y.mWidth = mVideoWidth;
       aFrame->Y.mHeight = mVideoHeight;
     } else {
       char *data = static_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
       size_t length = mVideoBuffer->range_length();
--- a/content/media/omx/OmxDecoder.h
+++ b/content/media/omx/OmxDecoder.h
@@ -22,17 +22,17 @@ namespace layers {
 
 class VideoGraphicBuffer : public GraphicBufferLocked {
   // XXX change this to an actual smart pointer at some point
   android::MediaBuffer *mMediaBuffer;
   android::wp<android::OmxDecoder> mOmxDecoder;
   public:
     VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
                        android::MediaBuffer *aBuffer,
-                       SurfaceDescriptor *aDescriptor);
+                       SurfaceDescriptor& aDescriptor);
     ~VideoGraphicBuffer();
     void Unlock();
 };
 
 }
 }
 
 namespace android {
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/877527.html
@@ -0,0 +1,37 @@
+<script>
+try { o1 = new window.AudioContext(2, 5, 44100); } catch(e) { }
+try { o2 = o1.createChannelMerger(1); } catch(e) { }
+try { o3 = o1.createDelay(10); } catch(e) { }
+try { o4 = o1.createBuffer(2, 2048, 8000); } catch(e) { }
+try { o5 = o1.createPanner(); } catch(e) { }
+try { o6 = o1.createBufferSource(); } catch(e) { }
+try { o7 = (function() {
+var buf = o1.createBuffer(1, 50000, o1.sampleRate);
+for(var j=0; j<1; ++j) {
+for(var i=0; i<50000; ++i) { buf.getChannelData(j)[i] = Math.sin(i * (9.8));}
+}
+return buf;
+})(); } catch(e) { }
+try { o6.buffer = o7; } catch(e) { }
+try { o6.connect(o5); } catch(e) { }
+try { o5.connect(o1.destination); } catch(e) { }
+try { o1.listener.speedOfSound = 0.0000019073486328125; } catch(e) { }
+try { o6.loop = true; } catch(e) { }
+try { o8 = (function() {
+var buf = o1.createBuffer(2, 1000, o1.sampleRate);
+for(var j=0; j<2; ++j) {
+for(var i=0; i<1000; ++i) { buf.getChannelData(j)[i] = Math.sin(i * (1));}
+}
+return buf;
+})(); } catch(e) { }
+try { o6.buffer = o7; } catch(e) { }
+try { o6.connect(o5); } catch(e) { }
+try { o5.connect(o1.destination); } catch(e) { }
+try { o6.loopEnd = 1.4901161193847656e-8; } catch(e) { }
+try { o6.connect(o1.destination); } catch(e) { }
+try { o6.buffer = o8; } catch(e) { }
+try { o5.setPosition(0.36, o1.destination.context.destination.channelCountMode, o1.destination.context.destination.channelInterpretation) } catch(e) { }
+try { o2.channelCountMode = 'explicit'; } catch(e) { }
+try { o1.listener.speedOfSound = 4; } catch(e) { }
+try { o1.startRendering(); } catch(e) { }
+</script>
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -31,8 +31,9 @@ load 876215.html
 load 876249.html
 load 876252.html
 load 876834.html
 load 877820.html
 load 878014.html
 load 878328.html
 load 878407.html
 load 878478.html
+load 877527.html
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 sw=2 et tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsDOMClassInfo_h___
 #define nsDOMClassInfo_h___
 
+#include "mozilla/Attributes.h"
 #include "nsIDOMClassInfo.h"
 #include "nsIXPCScriptable.h"
 #include "jsapi.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptContext.h"
 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
 #include "nsIScriptGlobalObject.h"
 #include "xpcpublic.h"
@@ -134,21 +135,21 @@ public:
     return sXPConnect;
   }
 
 protected:
   friend nsIClassInfo* NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID);
 
   const nsDOMClassInfoData* mData;
 
-  virtual void PreserveWrapper(nsISupports *aNative)
+  virtual void PreserveWrapper(nsISupports *aNative) MOZ_OVERRIDE
   {
   }
 
-  virtual uint32_t GetInterfacesBitmap()
+  virtual uint32_t GetInterfacesBitmap() MOZ_OVERRIDE
   {
     return mData->mInterfacesBitmap;
   }
 
   static nsresult Init();
   static nsresult RegisterClassProtos(int32_t aDOMClassInfoID);
   static nsresult RegisterExternalClasses();
   nsresult ResolveConstructor(JSContext *cx, JSObject *obj,
@@ -280,21 +281,21 @@ protected:
   {
   }
 
   virtual ~nsEventTargetSH()
   {
   }
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
   NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
 
-  virtual void PreserveWrapper(nsISupports *aNative);
+  virtual void PreserveWrapper(nsISupports *aNative) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsEventTargetSH(aData);
   }
 };
 
 // Makes sure that the wrapper is preserved if new properties are added.
@@ -305,21 +306,21 @@ protected:
   {
   }
 
   virtual ~nsEventSH()
   {
   }
 public:
   NS_IMETHOD PreCreate(nsISupports* aNativeObj, JSContext* aCx,
-                       JSObject* aGlobalObj, JSObject** aParentObj);
+                       JSObject* aGlobalObj, JSObject** aParentObj) MOZ_OVERRIDE;
   NS_IMETHOD AddProperty(nsIXPConnectWrappedNative* aWrapper, JSContext* aCx,
-                         JSObject* aObj, jsid Id, jsval* aVp, bool* aRetval);
+                         JSObject* aObj, jsid Id, jsval* aVp, bool* aRetval) MOZ_OVERRIDE;
 
-  virtual void PreserveWrapper(nsISupports *aNative);
+  virtual void PreserveWrapper(nsISupports *aNative) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsEventSH(aData);
   }
 };
 
 // Window scriptable helper
@@ -336,43 +337,43 @@ protected:
   }
 
   static nsresult GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                                 JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                                 bool *did_resolve);
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
 #ifdef DEBUG
   NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj)
+                        JSObject *obj) MOZ_OVERRIDE
   {
     nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
 
     NS_ASSERTION(!sgo || sgo->GetGlobalJSObject() == nullptr,
                  "Multiple wrappers created for global object!");
 
     return NS_OK;
   }
-  virtual uint32_t GetScriptableFlags()
+  virtual uint32_t GetScriptableFlags() MOZ_OVERRIDE
   {
     return nsDOMGenericSH::GetScriptableFlags() |
            nsIXPCScriptable::WANT_POSTCREATE;
   }
 #endif
   NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, bool *_retval);
+                       JSObject *obj, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
-                      JSObject *obj);
+                      JSObject *obj) MOZ_OVERRIDE;
   NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
-                         JSObject * obj, JSObject * *_retval);
+                         JSObject * obj, JSObject * *_retval) MOZ_OVERRIDE;
 
   static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
                                               JSHandleId id, unsigned flags,
                                               JS::MutableHandle<JSObject*> objp);
   static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
                                                JSHandleId id, JSMutableHandleValue vp);
   static JSBool InvalidateGlobalScopePolluter(JSContext *cx,
                                               JS::Handle<JSObject*> obj);
@@ -395,20 +396,20 @@ protected:
 
   virtual ~nsLocationSH()
   {
   }
 
 public:
   NS_IMETHOD CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsid id, uint32_t mode,
-                         jsval *vp, bool *_retval);
+                         jsval *vp, bool *_retval) MOZ_OVERRIDE;
 
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
   NS_IMETHODIMP AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                             JSObject *obj, jsid id, jsval *vp, bool *_retval);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsLocationSH(aData);
   }
 };
@@ -424,20 +425,20 @@ protected:
   }
 
   virtual ~nsNavigatorSH()
   {
   }
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNavigatorSH(aData);
   }
 };
 
 // DOM Node helper, this class deals with setting the parent for the
@@ -451,25 +452,25 @@ protected:
   }
 
   virtual ~nsNodeSH()
   {
   }
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
   NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
-  NS_IMETHOD GetFlags(uint32_t *aFlags);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
+  NS_IMETHOD GetFlags(uint32_t *aFlags) MOZ_OVERRIDE;
 
-  virtual void PreserveWrapper(nsISupports *aNative);
+  virtual void PreserveWrapper(nsISupports *aNative) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNodeSH(aData);
   }
 };
 
 
@@ -483,21 +484,21 @@ protected:
   }
 
   virtual ~nsElementSH()
   {
   }
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
   NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj);
+                        JSObject *obj) MOZ_OVERRIDE;
   NS_IMETHOD PostTransplant(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                            JSObject *obj);
+                            JSObject *obj) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsElementSH(aData);
   }
 };
 
 
@@ -512,19 +513,19 @@ protected:
 
   virtual ~nsGenericArraySH()
   {
   }
   
 public:
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, bool *_retval);
+                       JSObject *obj, bool *_retval) MOZ_OVERRIDE;
   
   virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                              JSObject *obj, uint32_t *length);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsGenericArraySH(aData);
   }
@@ -546,17 +547,17 @@ protected:
 
   // Subclasses need to override this, if the implementation can't fail it's
   // allowed to not set *aResult.
   virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
                                  nsWrapperCache **aCache, nsresult *aResult) = 0;
 
 public:
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
 
 private:
   // Not implemented, nothing should create an instance of this class.
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData);
 };
 
 
 // NamedArray helper
@@ -569,26 +570,26 @@ protected:
   }
 
   virtual ~nsNamedArraySH()
   {
   }
 
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
 
   virtual nsISupports* GetNamedItem(nsISupports *aNative,
                                     const nsAString& aName,
                                     nsWrapperCache **cache,
                                     nsresult *aResult) = 0;
 
 public:
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
 
 private:
   // Not implemented, nothing should create an instance of this class.
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData);
 };
 
 
 // HTMLDocument helper
@@ -628,25 +629,25 @@ protected:
 
   virtual ~nsHTMLFormElementSH()
   {
   }
 
 public:
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsid id, jsval *vp,
-                         bool *_retval);
+                         bool *_retval) MOZ_OVERRIDE;
 
   NS_IMETHOD NewEnumerate(nsIXPConnectWrappedNative *wrapper,
                           JSContext *cx, JSObject *obj,
                           uint32_t enum_op, jsval *statep,
-                          jsid *idp, bool *_retval);
+                          jsid *idp, bool *_retval) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsHTMLFormElementSH(aData);
   }
 };
 
 
@@ -659,23 +660,23 @@ protected:
   {
   }
 
   virtual ~nsPluginSH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
+                                 nsWrapperCache **aCache, nsresult *aResult) MOZ_OVERRIDE;
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsISupports* GetNamedItem(nsISupports *aNative,
                                     const nsAString& aName,
                                     nsWrapperCache **cache,
-                                    nsresult *aResult);
+                                    nsresult *aResult) MOZ_OVERRIDE;
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsPluginSH(aData);
   }
 };
 
@@ -689,23 +690,23 @@ protected:
   {
   }
 
   virtual ~nsPluginArraySH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
+                                 nsWrapperCache **aCache, nsresult *aResult) MOZ_OVERRIDE;
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsISupports* GetNamedItem(nsISupports *aNative,
                                     const nsAString& aName,
                                     nsWrapperCache **cache,
-                                    nsresult *aResult);
+                                    nsresult *aResult) MOZ_OVERRIDE;
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsPluginArraySH(aData);
   }
 };
 
@@ -719,23 +720,23 @@ protected:
   {
   }
 
   virtual ~nsMimeTypeArraySH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
+                                 nsWrapperCache **aCache, nsresult *aResult) MOZ_OVERRIDE;
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsISupports* GetNamedItem(nsISupports *aNative,
                                     const nsAString& aName,
                                     nsWrapperCache **cache,
-                                    nsresult *aResult);
+                                    nsresult *aResult) MOZ_OVERRIDE;
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsMimeTypeArraySH(aData);
   }
 };
 
@@ -753,17 +754,17 @@ protected:
   {
   }
 
   virtual nsresult GetStringAt(nsISupports *aNative, int32_t aIndex,
                                nsAString& aResult) = 0;
 
 public:
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
 };
 
 
 // History helper
 
 class nsHistorySH : public nsStringArraySH
 {
 protected:
@@ -771,23 +772,23 @@ protected:
   {
   }
 
   virtual ~nsHistorySH()
   {
   }
 
   virtual nsresult GetStringAt(nsISupports *aNative, int32_t aIndex,
-                               nsAString& aResult);
+                               nsAString& aResult) MOZ_OVERRIDE;
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsHistorySH(aData);
   }
 };
 
 // StringList scriptable helper
@@ -799,17 +800,17 @@ protected:
   {
   }
 
   virtual ~nsStringListSH()
   {
   }
 
   virtual nsresult GetStringAt(nsISupports *aNative, int32_t aIndex,
-                               nsAString& aResult);
+                               nsAString& aResult) MOZ_OVERRIDE;
 
 public:
   // Inherit GetProperty, Enumerate from nsStringArraySH
   
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStringListSH(aData);
   }
@@ -825,17 +826,17 @@ protected:
   {
   }
 
   virtual ~nsMediaListSH()
   {
   }
 
   virtual nsresult GetStringAt(nsISupports *aNative, int32_t aIndex,
-                               nsAString& aResult);
+                               nsAString& aResult) MOZ_OVERRIDE;
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsMediaListSH(aData);
   }
 };
 
@@ -849,17 +850,17 @@ protected:
   {
   }
 
   virtual ~nsStyleSheetListSH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
+                                 nsWrapperCache **aCache, nsresult *aResult) MOZ_OVERRIDE;
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStyleSheetListSH(aData);
   }
 };
 
@@ -873,17 +874,17 @@ protected:
   {
   }
 
   virtual ~nsCSSRuleListSH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
+                                 nsWrapperCache **aCache, nsresult *aResult) MOZ_OVERRIDE;
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsCSSRuleListSH(aData);
   }
 };
 
@@ -894,17 +895,17 @@ class nsDOMTouchListSH : public nsArrayS
   {
   }
 
   virtual ~nsDOMTouchListSH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
+                                 nsWrapperCache **aCache, nsresult *aResult) MOZ_OVERRIDE;
 
   public:
   static nsIClassInfo* doCreate(nsDOMClassInfoData* aData)
   {
     return new nsDOMTouchListSH(aData);
   }
 };
 
@@ -918,26 +919,26 @@ protected:
   }
 
   virtual ~nsStorage2SH()
   {
   }
 
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
+                         JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, bool *_retval);
+                         JSObject *obj, jsid id, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                           JSObject *obj, uint32_t enum_op, jsval *statep,
-                          jsid *idp, bool *_retval);
+                          jsid *idp, bool *_retval) MOZ_OVERRIDE;
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStorage2SH(aData);
   }
 };
 
@@ -970,29 +971,29 @@ class nsDOMConstructorSH : public nsDOMG
 {
 protected:
   nsDOMConstructorSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
   {
   }
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
-  NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto)
+                       JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
+  NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto) MOZ_OVERRIDE
   {
     return NS_OK;
   }
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
+                        JSObject **objp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                  JSObject *obj, const JS::CallArgs &args, bool *_retval);
+                  JSObject *obj, const JS::CallArgs &args, bool *_retval) MOZ_OVERRIDE;
 
   NS_IMETHOD Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, const JS::CallArgs &args, bool *_retval);
+                       JSObject *obj, const JS::CallArgs &args, bool *_retval) MOZ_OVERRIDE;
 
   NS_IMETHOD HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, const jsval &val, bool *bp,
                          bool *_retval);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsDOMConstructorSH(aData);
@@ -1006,17 +1007,17 @@ protected:
   {
   }
 
   virtual ~nsNonDOMObjectSH()
   {
   }
 
 public:
-  NS_IMETHOD GetFlags(uint32_t *aFlags);
+  NS_IMETHOD GetFlags(uint32_t *aFlags) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNonDOMObjectSH(aData);
   }
 };
 
 #endif /* nsDOMClassInfo_h___ */
--- a/dom/base/nsDOMScriptObjectFactory.h
+++ b/dom/base/nsDOMScriptObjectFactory.h
@@ -31,26 +31,26 @@ public:
   nsDOMScriptObjectFactory();
 
   NS_DECL_ISUPPORTS
 
   // nsIObserver
   NS_DECL_NSIOBSERVER
 
   // nsIDOMScriptObjectFactory
-  NS_IMETHOD_(nsISupports *) GetClassInfoInstance(nsDOMClassInfoID aID);
-  NS_IMETHOD_(nsISupports *) GetExternalClassInfoInstance(const nsAString& aName);
+  NS_IMETHOD_(nsISupports *) GetClassInfoInstance(nsDOMClassInfoID aID) MOZ_OVERRIDE;
+  NS_IMETHOD_(nsISupports *) GetExternalClassInfoInstance(const nsAString& aName) MOZ_OVERRIDE;
 
   NS_IMETHOD RegisterDOMClassInfo(const char *aName,
                                   nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
                                   const nsIID *aProtoChainInterface,
                                   const nsIID **aInterfaces,
                                   uint32_t aScriptableFlags,
                                   bool aHasClassInterface,
-                                  const nsCID *aConstructorCID);
+                                  const nsCID *aConstructorCID) MOZ_OVERRIDE;
 };
 
 class nsDOMExceptionProvider MOZ_FINAL : public nsIExceptionProvider
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIEXCEPTIONPROVIDER
 };
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -59,17 +59,16 @@
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #endif
 
 #include "Layers.h"
 #include "nsIIOService.h"
 
 #include "mozilla/dom/Element.h"
-#include "mozilla/dom/indexedDB/FileInfo.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "GeckoProfiler.h"
 #include "nsDOMBlobBuilder.h"
 #include "nsIDOMFileHandle.h"
 #include "nsPrintfCString.h"
 #include "nsViewportInfo.h"
 #include "nsIFormControl.h"
@@ -2863,38 +2862,25 @@ nsDOMWindowUtils::GetFileReferences(cons
   nsCString origin;
   nsresult rv = quota::QuotaManager::GetASCIIOriginFromWindow(window, origin);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
     indexedDB::IndexedDatabaseManager::Get();
 
   if (mgr) {
-    nsRefPtr<indexedDB::FileManager> fileManager =
-      mgr->GetFileManager(origin, aDatabaseName);
-
-    if (fileManager) {
-      nsRefPtr<indexedDB::FileInfo> fileInfo = fileManager->GetFileInfo(aId);
-
-      if (fileInfo) {
-        fileInfo->GetReferences(aRefCnt, aDBRefCnt, aSliceRefCnt);
-
-        if (*aRefCnt != -1) {
-          // We added an extra temp ref, so account for that accordingly.
-          (*aRefCnt)--;
-        }
-
-        *aResult = true;
-        return NS_OK;
-      }
-    }
+    rv = mgr->BlockAndGetFileReferences(origin, aDatabaseName, aId, aRefCnt,
+                                        aDBRefCnt, aSliceRefCnt, aResult);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
-
-  *aRefCnt = *aDBRefCnt = *aSliceRefCnt = -1;
-  *aResult = false;
+  else {
+    *aRefCnt = *aDBRefCnt = *aSliceRefCnt = -1;
+    *aResult = false;
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::IsIncrementalGCEnabled(JSContext* cx, bool* aResult)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -43,65 +43,65 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSContext,
                                                          nsIScriptContext)
 
   virtual nsresult EvaluateString(const nsAString& aScript,
                                   JS::Handle<JSObject*> aScopeObject,
                                   JS::CompileOptions &aOptions,
                                   bool aCoerceToString,
-                                  JS::Value* aRetValue);
+                                  JS::Value* aRetValue) MOZ_OVERRIDE;
 
   virtual nsresult CompileScript(const PRUnichar* aText,
                                  int32_t aTextLength,
                                  nsIPrincipal *principal,
                                  const char *aURL,
                                  uint32_t aLineNo,
                                  uint32_t aVersion,
                                  JS::MutableHandle<JSScript*> aScriptObject,
-                                 bool aSaveSource = false);
+                                 bool aSaveSource = false) MOZ_OVERRIDE;
   virtual nsresult ExecuteScript(JSScript* aScriptObject,
-                                 JSObject* aScopeObject);
+                                 JSObject* aScopeObject) MOZ_OVERRIDE;
 
   virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
                                             JS::Handle<JSObject*> aScope,
                                             JS::Handle<JSObject*> aHandler,
-                                            JS::MutableHandle<JSObject*> aBoundHandler);
+                                            JS::MutableHandle<JSObject*> aBoundHandler) MOZ_OVERRIDE;
 
-  virtual nsIScriptGlobalObject *GetGlobalObject();
+  virtual nsIScriptGlobalObject *GetGlobalObject() MOZ_OVERRIDE;
   inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; }
 
-  virtual JSContext* GetNativeContext();
-  virtual JSObject* GetNativeGlobal();
-  virtual nsresult InitContext();
-  virtual bool IsContextInitialized();
+  virtual JSContext* GetNativeContext() MOZ_OVERRIDE;
+  virtual JSObject* GetNativeGlobal() MOZ_OVERRIDE;
+  virtual nsresult InitContext() MOZ_OVERRIDE;
+  virtual bool IsContextInitialized() MOZ_OVERRIDE;
 
-  virtual void ScriptEvaluated(bool aTerminated);
-  virtual bool GetScriptsEnabled();
-  virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts);
+  virtual void ScriptEvaluated(bool aTerminated) MOZ_OVERRIDE;
+  virtual bool GetScriptsEnabled() MOZ_OVERRIDE;
+  virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts) MOZ_OVERRIDE;
 
-  virtual nsresult SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, nsISupports* aVal);
+  virtual nsresult SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, nsISupports* aVal) MOZ_OVERRIDE;
 
-  virtual bool GetProcessingScriptTag();
-  virtual void SetProcessingScriptTag(bool aResult);
+  virtual bool GetProcessingScriptTag() MOZ_OVERRIDE;
+  virtual void SetProcessingScriptTag(bool aResult) MOZ_OVERRIDE;
 
-  virtual bool GetExecutingScript();
+  virtual bool GetExecutingScript() MOZ_OVERRIDE;
 
-  virtual nsresult InitClasses(JS::Handle<JSObject*> aGlobalObj);
+  virtual nsresult InitClasses(JS::Handle<JSObject*> aGlobalObj) MOZ_OVERRIDE;
 
-  virtual void WillInitializeContext();
-  virtual void DidInitializeContext();
+  virtual void WillInitializeContext() MOZ_OVERRIDE;
+  virtual void DidInitializeContext() MOZ_OVERRIDE;
 
   virtual nsresult Serialize(nsIObjectOutputStream* aStream,
-                             JS::Handle<JSScript*> aScriptObject);
+                             JS::Handle<JSScript*> aScriptObject) MOZ_OVERRIDE;
   virtual nsresult Deserialize(nsIObjectInputStream* aStream,
-                               JS::MutableHandle<JSScript*> aResult);
+                               JS::MutableHandle<JSScript*> aResult) MOZ_OVERRIDE;
 
-  virtual void EnterModalState();
-  virtual void LeaveModalState();
+  virtual void EnterModalState() MOZ_OVERRIDE;
+  virtual void LeaveModalState() MOZ_OVERRIDE;
 
   NS_DECL_NSIXPCSCRIPTNOTIFY
 
   static void LoadStart();
   static void LoadEnd();
 
   enum IsCompartment {
     CompartmentGC,
@@ -139,17 +139,17 @@ public:
   static void MaybePokeCC();
   static void KillCCTimer();
   static void KillFullGCTimer();
   static void KillInterSliceGCTimer();
 
   // Calling LikelyShortLivingObjectCreated() makes a GC more likely.
   static void LikelyShortLivingObjectCreated();
 
-  virtual void GC(JS::gcreason::Reason aReason);
+  virtual void GC(JS::gcreason::Reason aReason) MOZ_OVERRIDE;
 
   static uint32_t CleanupsSinceLastGC();
 
   nsIScriptGlobalObject* GetCachedGlobalObject()
   {
     // Verify that we have a global so that this
     // does always return a null when GetGlobalObject() is null.
     JSObject* global = GetNativeGlobal();
@@ -218,17 +218,17 @@ public:
   static JSRuntime *sRuntime;
 
 public:
   // nsISupports
   NS_DECL_ISUPPORTS
 
   virtual already_AddRefed<nsIScriptContext>
   CreateContext(bool aGCOnDestruction,
-                nsIScriptGlobalObject* aGlobalObject);
+                nsIScriptGlobalObject* aGlobalObject) MOZ_OVERRIDE;
 
   static void Startup();
   static void Shutdown();
   // Setup all the statics etc - safe to call multiple times after Startup()
   static nsresult Init();
   // Get the NameSpaceManager, creating if necessary
   static nsScriptNameSpaceManager* GetNameSpaceManager();
 };
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -9,16 +9,17 @@
 
 class nsPIDOMWindow;
 class nsIDOMEventListener;
 class nsEventListenerManager;
 class nsIDOMEvent;
 class nsEventChainPreVisitor;
 class nsEventChainPostVisitor;
 
+#include "mozilla/Attributes.h"
 #include "nsIDOMEventTarget.h"
 #include "nsEventListenerManager.h"
 #include "nsPIWindowRoot.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsWindowRoot : public nsPIWindowRoot
 {
 public:
@@ -31,30 +32,30 @@ public:
   virtual void AddEventListener(const nsAString& aType,
                                 nsIDOMEventListener* aListener,
                                 bool aUseCapture,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
 
   // nsPIWindowRoot
 
-  virtual nsPIDOMWindow* GetWindow();
+  virtual nsPIDOMWindow* GetWindow() MOZ_OVERRIDE;
 
-  virtual nsresult GetControllers(nsIControllers** aResult);
+  virtual nsresult GetControllers(nsIControllers** aResult) MOZ_OVERRIDE;
   virtual nsresult GetControllerForCommand(const char * aCommand,
-                                           nsIController** _retval);
+                                           nsIController** _retval) MOZ_OVERRIDE;
 
-  virtual nsIDOMNode* GetPopupNode();
-  virtual void SetPopupNode(nsIDOMNode* aNode);
+  virtual nsIDOMNode* GetPopupNode() MOZ_OVERRIDE;
+  virtual void SetPopupNode(nsIDOMNode* aNode) MOZ_OVERRIDE;
 
-  virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget)
+  virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) MOZ_OVERRIDE
   {
     mParent = aTarget;
   }
-  virtual mozilla::dom::EventTarget* GetParentTarget() { return mParent; }
+  virtual mozilla::dom::EventTarget* GetParentTarget() MOZ_OVERRIDE { return mParent; }
   virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE;
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsWindowRoot,
                                                          nsIDOMEventTarget)
 
 protected:
   // Members
   nsPIDOMWindow* mWindow; // [Weak]. The window will hold on to us and let go when it dies.
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -385,16 +385,20 @@ DOMInterfaces = {
     'nativeType': 'nsFormData'
 },
 {
     'workers': True,
     'skipGen': True,
     'nativeType': 'JSObject'
 }],
 
+'FocusEvent': {
+    'nativeType': 'nsDOMFocusEvent',
+},
+
 'GainNode': {
     'resultNotAddRefed': [ 'gain' ],
 },
 
 'Gamepad': {
     'nativeType': 'nsDOMGamepad',
 },
 
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -76,27 +76,33 @@ DOMProxyHandler::GetAndClearExpandoObjec
   MOZ_ASSERT(IsDOMProxy(obj), "expected a DOM proxy object");
   JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
   if (v.isUndefined()) {
     return nullptr;
   }
 
   if (v.isObject()) {
     js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, UndefinedValue());
+    xpc::GetObjectScope(obj)->RemoveDOMExpandoObject(obj);
   } else {
     js::ExpandoAndGeneration* expandoAndGeneration =
       static_cast<js::ExpandoAndGeneration*>(v.toPrivate());
     v = expandoAndGeneration->expando;
     if (v.isUndefined()) {
       return nullptr;
     }
+
+    nsISupports* native = UnwrapDOMObject<nsISupports>(obj);
+    nsWrapperCache* cache;
+    CallQueryInterface(native, &cache);
+    cache->SetPreservingWrapper(false);
+    nsContentUtils::DropJSObjects(native);
     expandoAndGeneration->expando = UndefinedValue();
   }
 
-  xpc::GetObjectScope(obj)->RemoveDOMExpandoObject(obj);
 
   return &v.toObject();
 }
 
 // static
 JSObject*
 DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj)
 {
@@ -117,30 +123,33 @@ DOMProxyHandler::EnsureExpandoObject(JSC
   }
 
   JS::Rooted<JSObject*> expando(cx,
     JS_NewObjectWithGivenProto(cx, nullptr, nullptr, js::GetObjectParent(obj)));
   if (!expando) {
     return nullptr;
   }
 
+  nsISupports* native = UnwrapDOMObject<nsISupports>(obj);
+  nsWrapperCache* cache;
+  CallQueryInterface(native, &cache);
+  if (expandoAndGeneration) {
+    nsContentUtils::PreserveWrapper(native, cache);
+    expandoAndGeneration->expando.setObject(*expando);
+
+    return expando;
+  }
+
   XPCWrappedNativeScope* scope = xpc::GetObjectScope(obj);
   if (!scope->RegisterDOMExpandoObject(obj)) {
     return nullptr;
   }
 
-  nsWrapperCache* cache;
-  CallQueryInterface(UnwrapDOMObject<nsISupports>(obj), &cache);
   cache->SetPreservingWrapper(true);
-
-  if (expandoAndGeneration) {
-    expandoAndGeneration->expando.setObject(*expando);
-  } else {
-    js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando));
-  }
+  js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando));
 
   return expando;
 }
 
 bool
 DOMProxyHandler::isExtensible(JSObject *proxy)
 {
   return true; // always extensible per WebIDL
--- a/dom/bindings/DOMJSProxyHandler.h
+++ b/dom/bindings/DOMJSProxyHandler.h
@@ -132,15 +132,12 @@ FillPropertyDescriptor(JSPropertyDescrip
 
 inline void
 FillPropertyDescriptor(JSPropertyDescriptor* desc, JSObject* obj, JS::Value v, bool readonly)
 {
   desc->value = v;
   FillPropertyDescriptor(desc, obj, readonly);
 }
 
-JSObject*
-EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj);
-
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_DOMProxyHandler_h */
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothadapter_h__
 #define mozilla_dom_bluetooth_bluetoothadapter_h__
 
+#include "mozilla/Attributes.h"
 #include "BluetoothCommon.h"
 #include "BluetoothPropertyContainer.h"
 #include "nsCOMPtr.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothAdapter.h"
 
 class nsIEventTarget;
 class nsIDOMDOMRequest;
@@ -43,17 +44,17 @@ public:
 
   nsISupports*
   ToISupports()
   {
     return static_cast<EventTarget*>(this);
   }
 
   void Unroot();
-  virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);  
+  virtual void SetPropertyByValue(const BluetoothNamedValue& aValue) MOZ_OVERRIDE;  
 private:
 
   BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue);
   ~BluetoothAdapter();
 
   void Root();
   nsresult StartStopDiscovery(bool aStart, nsIDOMDOMRequest** aRequest);
   nsresult PairUnpair(bool aPair,
--- a/dom/bluetooth/BluetoothDevice.h
+++ b/dom/bluetooth/BluetoothDevice.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothdevice_h__
 #define mozilla_dom_bluetooth_bluetoothdevice_h__
 
+#include "mozilla/Attributes.h"
 #include "BluetoothCommon.h"
 #include "BluetoothPropertyContainer.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothDevice.h"
 #include "nsString.h"
 
 class nsIDOMDOMRequest;
 
@@ -43,17 +44,17 @@ public:
   void Notify(const BluetoothSignal& aParam);
 
   nsISupports*
   ToISupports()
   {
     return static_cast<EventTarget*>(this);
   }
 
-  void SetPropertyByValue(const BluetoothNamedValue& aValue);
+  void SetPropertyByValue(const BluetoothNamedValue& aValue) MOZ_OVERRIDE;
 
   void Unroot();
 private:
   BluetoothDevice(nsPIDOMWindow* aOwner, const nsAString& aAdapterPath,
                   const BluetoothValue& aValue);
   ~BluetoothDevice();
   void Root();
 
--- a/dom/bluetooth/BluetoothManager.h
+++ b/dom/bluetooth/BluetoothManager.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothmanager_h__
 #define mozilla_dom_bluetooth_bluetoothmanager_h__
 
+#include "mozilla/Attributes.h"
 #include "BluetoothCommon.h"
 #include "BluetoothPropertyContainer.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothManager.h"
 #include "mozilla/Observer.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
@@ -26,17 +27,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMBLUETOOTHMANAGER
 
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
 
   static already_AddRefed<BluetoothManager>
   Create(nsPIDOMWindow* aWindow);
   void Notify(const BluetoothSignal& aData);
-  virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);
+  virtual void SetPropertyByValue(const BluetoothNamedValue& aValue) MOZ_OVERRIDE;
 private:
   BluetoothManager(nsPIDOMWindow* aWindow);
   ~BluetoothManager();
 };
 
 END_BLUETOOTH_NAMESPACE
 
 nsresult NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
--- a/dom/bluetooth/BluetoothReplyRunnable.h
+++ b/dom/bluetooth/BluetoothReplyRunnable.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothreplyrunnable_h__
 #define mozilla_dom_bluetooth_bluetoothreplyrunnable_h__
 
+#include "mozilla/Attributes.h"
 #include "BluetoothCommon.h"
 #include "nsThreadUtils.h"
 #include "jsapi.h"
 
 class nsIDOMDOMRequest;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
@@ -53,17 +54,17 @@ private:
 
 class BluetoothVoidReplyRunnable : public BluetoothReplyRunnable
 {
 public:
   BluetoothVoidReplyRunnable(nsIDOMDOMRequest* aReq);
  ~BluetoothVoidReplyRunnable();
 
 protected:
-  virtual bool ParseSuccessfulReply(JS::Value* aValue)
+  virtual bool ParseSuccessfulReply(JS::Value* aValue) MOZ_OVERRIDE
   {
     *aValue = JSVAL_VOID;
     return true;
   }
 };
 
 END_BLUETOOTH_NAMESPACE
 
--- a/dom/bluetooth/gonk/BluetoothGonkService.h
+++ b/dom/bluetooth/gonk/BluetoothGonkService.h
@@ -13,16 +13,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef mozilla_dom_bluetooth_bluetoothgonkservice_h__
 #define mozilla_dom_bluetooth_bluetoothgonkservice_h__
 
+#include "mozilla/Attributes.h"
 #include "BluetoothCommon.h"
 #include "BluetoothDBusService.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 /**
  * BluetoothService functions are used to dispatch messages to Bluetooth DOM
  * objects on the main thread, as well as provide platform independent access
@@ -36,28 +37,28 @@ class BluetoothGonkService : public Blue
 {
 public:
   /**
    * Set up variables and start the platform specific connection. Must
    * be called from non-main thread.
    *
    * @return NS_OK if connection starts successfully, NS_ERROR_FAILURE otherwise
    */
-  virtual nsresult StartInternal();
+  virtual nsresult StartInternal() MOZ_OVERRIDE;
 
   /**
    * Stop the platform specific connection. Must be called from non-main thread.
    *
    * @return NS_OK if connection starts successfully, NS_ERROR_FAILURE otherwise
    */
-  virtual nsresult StopInternal();
+  virtual nsresult StopInternal() MOZ_OVERRIDE;
 
   /**
    * Get status of Bluetooth. Must be called from non-main thread.
    *
    * @return true if Bluetooth is enabled, false otherwise
    */
-  virtual bool IsEnabledInternal();
+  virtual bool IsEnabledInternal() MOZ_OVERRIDE;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothdbuseventservice_h__
 #define mozilla_dom_bluetooth_bluetoothdbuseventservice_h__
 
+#include "mozilla/Attributes.h"
 #include "BluetoothCommon.h"
 #include "mozilla/ipc/RawDBusConnection.h"
 #include "BluetoothService.h"
 
 class DBusMessage;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
@@ -21,48 +22,48 @@ BEGIN_BLUETOOTH_NAMESPACE
  */
 
 class BluetoothDBusService : public BluetoothService
                            , private mozilla::ipc::RawDBusConnection
 {
 public:
   bool IsReady();
 
-  virtual nsresult StartInternal();
+  virtual nsresult StartInternal() MOZ_OVERRIDE;
 
-  virtual nsresult StopInternal();
+  virtual nsresult StopInternal() MOZ_OVERRIDE;
 
-  virtual bool IsEnabledInternal();
+  virtual bool IsEnabledInternal() MOZ_OVERRIDE;
 
   virtual nsresult GetDefaultAdapterPathInternal(
-                                             BluetoothReplyRunnable* aRunnable);
+                                             BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
-                                             BluetoothReplyRunnable* aRunnable);
+                                             BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult GetPairedDevicePropertiesInternal(
                                      const nsTArray<nsString>& aDeviceAddresses,
-                                     BluetoothReplyRunnable* aRunnable);
+                                     BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
-  virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
+  virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
-  virtual nsresult StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
+  virtual nsresult StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
-  GetDevicePropertiesInternal(const BluetoothSignal& aSignal);
+  GetDevicePropertiesInternal(const BluetoothSignal& aSignal) MOZ_OVERRIDE;
 
   virtual nsresult
   SetProperty(BluetoothObjectType aType,
               const BluetoothNamedValue& aValue,
-              BluetoothReplyRunnable* aRunnable);
+              BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
-                nsAString& aDevicePath);
+                nsAString& aDevicePath) MOZ_OVERRIDE;
 
   static bool
   AddServiceRecords(const char* serviceName,
                     unsigned long long uuidMsb,
                     unsigned long long uuidLsb,
                     int channel);
 
   static bool
@@ -77,88 +78,88 @@ public:
 
   static bool
   RemoveReservedServicesInternal(const nsTArray<uint32_t>& aServiceHandles);
 
   virtual nsresult
   GetScoSocket(const nsAString& aObjectPath,
                bool aAuth,
                bool aEncrypt,
-               mozilla::ipc::UnixSocketConsumer* aConsumer);
+               mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE;
 
   virtual nsresult
   GetServiceChannel(const nsAString& aDeviceAddress,
                     const nsAString& aServiceUuid,
-                    BluetoothProfileManagerBase* aManager);
+                    BluetoothProfileManagerBase* aManager) MOZ_OVERRIDE;
 
   virtual bool
   UpdateSdpRecords(const nsAString& aDeviceAddress,
-                   BluetoothProfileManagerBase* aManager);
+                   BluetoothProfileManagerBase* aManager) MOZ_OVERRIDE;
 
   virtual nsresult
   CreatePairedDeviceInternal(const nsAString& aDeviceAddress,
                              int aTimeout,
-                             BluetoothReplyRunnable* aRunnable);
+                             BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
   RemoveDeviceInternal(const nsAString& aDeviceObjectPath,
-                       BluetoothReplyRunnable* aRunnable);
+                       BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
-                     BluetoothReplyRunnable* aRunnable);
+                     BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
-                     BluetoothReplyRunnable* aRunnable);
+                     BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
-                                 BluetoothReplyRunnable* aRunnable);
+                                 BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
-                           BluetoothReplyRunnable* aRunnable);
+                           BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
-  PrepareAdapterInternal();
+  PrepareAdapterInternal() MOZ_OVERRIDE;
 
   virtual void
   Connect(const nsAString& aDeviceAddress,
           const uint16_t aProfileId,
           BluetoothReplyRunnable* aRunnable);
 
   virtual bool
-  IsConnected(uint16_t aProfileId);
+  IsConnected(uint16_t aProfileId) MOZ_OVERRIDE;
 
   virtual void
   Disconnect(const uint16_t aProfileId, BluetoothReplyRunnable* aRunnable);
 
   virtual void
   SendFile(const nsAString& aDeviceAddress,
            BlobParent* aBlobParent,
            BlobChild* aBlobChild,
-           BluetoothReplyRunnable* aRunnable);
+           BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
   StopSendingFile(const nsAString& aDeviceAddress,
-                  BluetoothReplyRunnable* aRunnable);
+                  BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
   ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
-                       BluetoothReplyRunnable* aRunnable);
+                       BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
-  ConnectSco(BluetoothReplyRunnable* aRunnable);
+  ConnectSco(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
-  DisconnectSco(BluetoothReplyRunnable* aRunnable);
+  DisconnectSco(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
-  IsScoConnected(BluetoothReplyRunnable* aRunnable);
+  IsScoConnected(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
 private:
   nsresult SendGetPropertyMessage(const nsAString& aPath,
                                   const char* aInterface,
                                   void (*aCB)(DBusMessage *, void *),
                                   BluetoothReplyRunnable* aRunnable);
   nsresult SendDiscoveryMessage(const char* aMessageName,
                                 BluetoothReplyRunnable* aRunnable);
--- a/dom/browser-element/BrowserElementPanning.js
+++ b/dom/browser-element/BrowserElementPanning.js
@@ -367,20 +367,23 @@ const ContentPanning = {
   },
 
   _generateCallback: function cp_generateCallback(content) {
     let firstScroll = true;
     let target;
     let isScrolling = false;
     let oldX, oldY, newX, newY;
     let win, doc, htmlNode, bodyNode;
-    let xScrollable = content.scrollWidth > content.clientWidth;
-    let yScrollable = content.scrollHeight > content.clientHeight;
+    let xScrollable;
+    let yScrollable;
 
     function doScroll(node, delta) {
+      // recalculate scrolling direction
+      xScrollable = node.scrollWidth > node.clientWidth;
+      yScrollable = node.scrollHeight > node.clientHeight;
       if (node instanceof Ci.nsIDOMHTMLElement) {
         newX = oldX = node.scrollLeft, newY = oldY = node.scrollTop;
         if (xScrollable) {
            node.scrollLeft += delta.x;
            newX = node.scrollLeft;
         }
         if (yScrollable) {
            node.scrollTop += delta.y;
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DOM_CAMERA_CAMERACONTROLIMPL_H
 #define DOM_CAMERA_CAMERACONTROLIMPL_H
 
+#include "mozilla/Attributes.h"
 #include "nsDOMFile.h"
 #include "nsProxyRelease.h"
 #include "DictionaryHelpers.h"
 #include "nsIDOMDeviceStorage.h"
 #include "DOMCameraManager.h"
 #include "DOMCameraPreview.h"
 #include "ICameraControl.h"
 #include "CameraCommon.h"
@@ -160,17 +161,17 @@ class CameraErrorResult : public nsRunna
 {
 public:
   CameraErrorResult(nsMainThreadPtrHandle<nsICameraErrorCallback> onError, const nsString& aErrorMsg, uint64_t aWindowId)
     : mOnErrorCb(onError)
     , mErrorMsg(aErrorMsg)
     , mWindowId(aWindowId)
   { }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mOnErrorCb.get() && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
       mOnErrorCb->HandleEvent(mErrorMsg);
     }
     return NS_OK;
   }
@@ -197,17 +198,17 @@ public:
   }
 
   virtual ~GetPreviewStreamResult()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   // Run() method is implementation specific.
-  NS_IMETHOD Run();
+  NS_IMETHOD Run() MOZ_OVERRIDE;
 
 protected:
   nsRefPtr<CameraControlImpl> mCameraControl;
   uint32_t mWidth;
   uint32_t mHeight;
   uint32_t mFramesPerSecond;
   nsMainThreadPtrHandle<nsICameraPreviewStreamCallback> mOnSuccessCb;
   uint64_t mWindowId;
@@ -226,17 +227,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~GetPreviewStreamTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     nsresult rv = mCameraControl->GetPreviewStreamImpl(this);
 
     if (NS_FAILED(rv)) {
       nsCOMPtr<nsIRunnable> cameraErrorResult = new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE"), mCameraControl->GetWindowId());
       rv = NS_DispatchToMainThread(cameraErrorResult);
       NS_ENSURE_SUCCESS(rv, rv);
     }
@@ -256,17 +257,17 @@ public:
   AutoFocusResult(bool aSuccess, nsMainThreadPtrHandle<nsICameraAutoFocusCallback> onSuccess, uint64_t aWindowId)
     : mSuccess(aSuccess)
     , mOnSuccessCb(onSuccess)
     , mWindowId(aWindowId)
   { }
 
   virtual ~AutoFocusResult() { }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mOnSuccessCb.get() && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
       mOnSuccessCb->HandleEvent(mSuccess);
     }
     return NS_OK;
   }
@@ -290,17 +291,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~AutoFocusTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->AutoFocusImpl(this);
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     if (NS_FAILED(rv)) {
       nsCOMPtr<nsIRunnable> cameraErrorResult = new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE"), mCameraControl->GetWindowId());
       rv = NS_DispatchToMainThread(cameraErrorResult);
@@ -329,17 +330,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~TakePictureResult()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
     if (mOnSuccessCb.get() && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
       nsCOMPtr<nsIDOMBlob> image = new nsDOMMemoryFile(static_cast<void*>(mData), static_cast<uint64_t>(mLength), mMimeType);
       mOnSuccessCb->HandleEvent(image);
     } else {
@@ -375,17 +376,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~TakePictureTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->TakePictureImpl(this);
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     if (NS_FAILED(rv)) {
       nsCOMPtr<nsIRunnable> cameraErrorResult = new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE"), mCameraControl->GetWindowId());
       rv = NS_DispatchToMainThread(cameraErrorResult);
@@ -411,17 +412,17 @@ class StartRecordingResult : public nsRu
 public:
   StartRecordingResult(nsMainThreadPtrHandle<nsICameraStartRecordingCallback> onSuccess, uint64_t aWindowId)
     : mOnSuccessCb(onSuccess)
     , mWindowId(aWindowId)
   { }
 
   virtual ~StartRecordingResult() { }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mOnSuccessCb.get() && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
       mOnSuccessCb->HandleEvent();
     }
     return NS_OK;
   }
@@ -447,17 +448,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~StartRecordingTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->StartRecordingImpl(this);
     DOM_CAMERA_LOGT("%s:%d : result %d\n", __func__, __LINE__, rv);
 
     // dispatch the callback
     nsCOMPtr<nsIRunnable> startRecordingResult;
     if (NS_SUCCEEDED(rv)) {
@@ -491,17 +492,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~StopRecordingTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->StopRecordingImpl(this);
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
@@ -520,17 +521,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~StartPreviewTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->StartPreviewImpl(this);
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
@@ -549,17 +550,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~StopPreviewTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     mCameraControl->StopPreviewImpl(this);
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     return NS_OK;
   }
 
@@ -572,17 +573,17 @@ class GetPreviewStreamVideoModeTask : pu
 public:
   GetPreviewStreamVideoModeTask(CameraControlImpl* aCameraControl, idl::CameraRecorderOptions aOptions,  nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
     : mCameraControl(aCameraControl)
     , mOptions(aOptions)
     , mOnSuccessCb(new nsMainThreadPtrHolder<nsICameraPreviewStreamCallback>(onSuccess))
     , mOnErrorCb(new nsMainThreadPtrHolder<nsICameraErrorCallback>(onError))
   { }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGI("%s:%d -- BEFORE IMPL\n", __func__, __LINE__);
     nsresult rv = mCameraControl->GetPreviewStreamVideoModeImpl(this);
     DOM_CAMERA_LOGI("%s:%d -- AFTER IMPL : rv = %d\n", __func__, __LINE__, rv);
 
     if (NS_FAILED(rv)) {
       nsCOMPtr<nsIRunnable> cameraErrorResult = new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE"), mCameraControl->GetWindowId());
       rv = NS_DispatchToMainThread(cameraErrorResult);
@@ -608,17 +609,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~ReleaseHardwareResult()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mOnSuccessCb.get() && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
       mOnSuccessCb->HandleEvent();
     }
     return NS_OK;
   }
@@ -640,17 +641,17 @@ public:
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~ReleaseHardwareTask()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->ReleaseHardwareImpl(this);
     DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     if (NS_FAILED(rv)) {
       nsCOMPtr<nsIRunnable> cameraErrorResult = new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE"), mCameraControl->GetWindowId());
       rv = NS_DispatchToMainThread(cameraErrorResult);
@@ -671,17 +672,17 @@ public:
   CameraRecorderStateChange(nsMainThreadPtrHandle<nsICameraRecorderStateChange> onStateChange, const nsString& aStateMsg, int32_t aStatus, int32_t aTrackNumber, uint64_t aWindowId)
     : mOnStateChangeCb(onStateChange)
     , mStateMsg(aStateMsg)
     , mStatus(aStatus)
     , mTrackNumber(aTrackNumber)
     , mWindowId(aWindowId)
   { }
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mOnStateChangeCb.get() && nsDOMCameraManager::IsWindowStillActive(mWindowId)) {
       // For now, just pass the state message and swallow mStatus and mTrackNumber
       mOnStateChangeCb->HandleStateChange(mStateMsg);
     }
     return NS_OK;
--- a/dom/camera/DOMCameraManager.h
+++ b/dom/camera/DOMCameraManager.h
@@ -76,17 +76,17 @@ class GetCameraTask : public nsRunnable
 public:
   GetCameraTask(uint32_t aCameraId, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, nsIThread* aCameraThread)
     : mCameraId(aCameraId)
     , mOnSuccessCb(onSuccess)
     , mOnErrorCb(onError)
     , mCameraThread(aCameraThread)
   { }
 
-  NS_IMETHOD Run();
+  NS_IMETHOD Run() MOZ_OVERRIDE;
 
 protected:
   uint32_t mCameraId;
   nsCOMPtr<nsICameraGetCameraCallback> mOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
   nsCOMPtr<nsIThread> mCameraThread;
 };
 
--- a/dom/devicestorage/DeviceStorageRequestParent.h
+++ b/dom/devicestorage/DeviceStorageRequestParent.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef mozilla_dom_devicestorage_DeviceStorageRequestParent_h
 #define mozilla_dom_devicestorage_DeviceStorageRequestParent_h
 
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/devicestorage/PDeviceStorageRequestParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 
 #include "nsThreadUtils.h"
 #include "nsDeviceStorage.h"
 #include "nsTArray.h"
 
@@ -45,17 +46,17 @@ private:
       : mParent(aParent)
     {
       mCanceled = !(mParent->AddRunnable(this));
     }
 
     virtual ~CancelableRunnable() {
     }
 
-    NS_IMETHOD Run() {
+    NS_IMETHOD Run() MOZ_OVERRIDE {
       nsresult rv = NS_OK;
       if (!mCanceled) {
         rv = CancelableRun();
         mParent->RemoveRunnable(this);
       }
       return rv;
     }
 
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsDeviceStorage_h
 #define nsDeviceStorage_h
 
 class nsPIDOMWindow;
+#include "mozilla/Attributes.h"
 #include "PCOMContentPermissionRequestChild.h"
 
 #include "DOMRequest.h"
 #include "DOMCursor.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIClassInfo.h"
@@ -67,17 +68,17 @@ public:
     public:
       InvalidateRunnable(DeviceStorageUsedSpaceCache* aCache, 
                          const nsAString& aStorageName)
         : mCache(aCache)
         , mStorageName(aStorageName) {}
 
       ~InvalidateRunnable() {}
 
-      NS_IMETHOD Run()
+      NS_IMETHOD Run() MOZ_OVERRIDE
       {
         mozilla::RefPtr<DeviceStorageUsedSpaceCache::CacheEntry> cacheEntry;
         cacheEntry = mCache->GetCacheEntry(mStorageName);
         if (cacheEntry) {
           cacheEntry->mDirty = true;
         }
         return NS_OK;
       }
@@ -164,17 +165,17 @@ private:
 class ContinueCursorEvent MOZ_FINAL : public nsRunnable
 {
 public:
   ContinueCursorEvent(already_AddRefed<mozilla::dom::DOMRequest> aRequest);
   ContinueCursorEvent(mozilla::dom::DOMRequest* aRequest);
   ~ContinueCursorEvent();
   void Continue();
 
-  NS_IMETHOD Run();
+  NS_IMETHOD Run() MOZ_OVERRIDE;
 private:
   already_AddRefed<DeviceStorageFile> GetNextFile();
   nsRefPtr<mozilla::dom::DOMRequest> mRequest;
 };
 
 class nsDOMDeviceStorageCursor MOZ_FINAL
   : public mozilla::dom::DOMCursor
   , public nsIContentPermissionRequest
@@ -194,22 +195,22 @@ public:
                            DeviceStorageFile* aFile,
                            PRTime aSince);
 
 
   nsTArray<nsRefPtr<DeviceStorageFile> > mFiles;
   bool mOkToCallContinue;
   PRTime mSince;
 
-  virtual bool Recv__delete__(const bool& allow);
-  virtual void IPDLRelease();
+  virtual bool Recv__delete__(const bool& allow) MOZ_OVERRIDE;
+  virtual void IPDLRelease() MOZ_OVERRIDE;
 
   void GetStorageType(nsAString & aType);
 
-  void RequestComplete();
+  void RequestComplete() MOZ_OVERRIDE;
 
 private:
   ~nsDOMDeviceStorageCursor();
 
   nsRefPtr<DeviceStorageFile> mFile;
   nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
--- a/dom/file/ArchiveRequest.h
+++ b/dom/file/ArchiveRequest.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_domarchiverequest_h__
 #define mozilla_dom_file_domarchiverequest_h__
 
+#include "mozilla/Attributes.h"
 #include "ArchiveReader.h"
 #include "DOMRequest.h"
 
 #include "FileCommon.h"
 
 
 BEGIN_FILE_NAMESPACE
 
@@ -35,17 +36,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ArchiveRequest, DOMRequest)
 
   ArchiveRequest(nsIDOMWindow* aWindow,
                  ArchiveReader* aReader);
 
   // nsIDOMEventTarget
-  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
 
 public:
   // This is called by the DOMArchiveRequestEvent
   void Run();
 
   // Set the types for this request
   void OpGetFilenames();
   void OpGetFile(const nsAString& aFilename);
--- a/dom/file/ArchiveZipEvent.h
+++ b/dom/file/ArchiveZipEvent.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_domarchivezipevent_h__
 #define mozilla_dom_file_domarchivezipevent_h__
 
+#include "mozilla/Attributes.h"
 #include "ArchiveEvent.h"
 
 #include "FileCommon.h"
 #include "zipstruct.h"
 
 #include "DictionaryHelpers.h"
 
 BEGIN_FILE_NAMESPACE
@@ -22,20 +23,20 @@ BEGIN_FILE_NAMESPACE
 class ArchiveZipItem : public ArchiveItem
 {
 public:
   ArchiveZipItem(const char* aFilename,
                  const ZipCentral& aCentralStruct,
                  const nsAString& aEncoding);
   virtual ~ArchiveZipItem();
 
-  nsresult GetFilename(nsString& aFilename);
+  nsresult GetFilename(nsString& aFilename) MOZ_OVERRIDE;
 
   // From zipItem to DOMFile:
-  virtual nsIDOMFile* File(ArchiveReader* aArchiveReader);
+  virtual nsIDOMFile* File(ArchiveReader* aArchiveReader) MOZ_OVERRIDE;
 
 public: // for the event
   static uint32_t StrToInt32(const uint8_t* aStr);
   static uint16_t StrToInt16(const uint8_t* aStr);
 
 private:
   nsresult ConvertFilename();
 
@@ -52,17 +53,17 @@ private: // data
  * ArchiveReaderEvent implements the ArchiveReaderEvent for the ZIP format
  */
 class ArchiveReaderZipEvent : public ArchiveReaderEvent
 {
 public:
   ArchiveReaderZipEvent(ArchiveReader* aArchiveReader,
                         const nsAString& aEncoding);
 
-  nsresult Exec();
+  nsresult Exec() MOZ_OVERRIDE;
 
 private:
   nsString mEncoding;
 };
 
 END_FILE_NAMESPACE
 
 #endif // mozilla_dom_file_domarchivezipevent_h__
--- a/dom/file/ArchiveZipFile.h
+++ b/dom/file/ArchiveZipFile.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_domarchivefile_h__
 #define mozilla_dom_file_domarchivefile_h__
 
+#include "mozilla/Attributes.h"
 #include "nsDOMFile.h"
 
 #include "ArchiveReader.h"
 
 #include "FileCommon.h"
 #include "zipstruct.h"
 
 BEGIN_FILE_NAMESPACE
@@ -52,25 +53,25 @@ public:
   }
 
   virtual ~ArchiveZipFile()
   {
     MOZ_COUNT_DTOR(ArchiveZipFile);
   }
 
   // Overrides:
-  NS_IMETHOD GetInternalStream(nsIInputStream**);
+  NS_IMETHOD GetInternalStream(nsIInputStream**) MOZ_OVERRIDE;
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ArchiveZipFile, nsDOMFileCC)
 
 protected:
   virtual already_AddRefed<nsIDOMBlob> CreateSlice(uint64_t aStart,
                                                    uint64_t aLength,
-                                                   const nsAString& aContentType);
+                                                   const nsAString& aContentType) MOZ_OVERRIDE;
 
 private: // Data
   ZipCentral mCentral;
   nsRefPtr<ArchiveReader> mArchiveReader;
 
   nsString mFilename;
 };
 
--- a/dom/file/DOMFileHandle.h
+++ b/dom/file/DOMFileHandle.h
@@ -2,35 +2,36 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_domfilehandle_h__
 #define mozilla_dom_file_domfilehandle_h__
 
+#include "mozilla/Attributes.h"
 #include "FileCommon.h"
 
 #include "FileHandle.h"
 
 BEGIN_FILE_NAMESPACE
 
 class DOMFileHandle : public FileHandle
 {
 public:
   static already_AddRefed<DOMFileHandle>
   Create(nsPIDOMWindow* aWindow,
          nsIFileStorage* aFileStorage,
          nsIFile* aFile);
 
   virtual already_AddRefed<nsISupports>
-  CreateStream(nsIFile* aFile, bool aReadOnly);
+  CreateStream(nsIFile* aFile, bool aReadOnly) MOZ_OVERRIDE;
 
   virtual already_AddRefed<nsIDOMFile>
-  CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize);
+  CreateFileObject(LockedFile* aLockedFile, uint32_t aFileSize) MOZ_OVERRIDE;
 
 protected:
   DOMFileHandle()
   { }
 
   ~DOMFileHandle()
   { }
 };
--- a/dom/file/File.h
+++ b/dom/file/File.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_file_h__
 #define mozilla_dom_file_file_h__
 
+#include "mozilla/Attributes.h"
 #include "FileCommon.h"
 
 #include "nsDOMFile.h"
 
 #include "LockedFile.h"
 
 BEGIN_FILE_NAMESPACE
 
@@ -43,47 +44,47 @@ public:
   {
     NS_ASSERTION(mFile, "Null file!");
     NS_ASSERTION(mLockedFile, "Null locked file!");
     mFileInfos.AppendElement(aFileInfo);
   }
 
   // Overrides
   NS_IMETHOD
-  GetMozFullPathInternal(nsAString& aFullPath);
+  GetMozFullPathInternal(nsAString& aFullPath) MOZ_OVERRIDE;
 
   NS_IMETHOD
-  GetInternalStream(nsIInputStream** aStream);
+  GetInternalStream(nsIInputStream** aStream) MOZ_OVERRIDE;
 
 protected:
   // Create slice
   File(const File* aOther, uint64_t aStart, uint64_t aLength,
        const nsAString& aContentType);
 
   virtual ~File()
   { }
 
   virtual already_AddRefed<nsIDOMBlob>
   CreateSlice(uint64_t aStart, uint64_t aLength,
-              const nsAString& aContentType);
+              const nsAString& aContentType) MOZ_OVERRIDE;
 
   virtual bool
-  IsStoredFile() const
+  IsStoredFile() const MOZ_OVERRIDE
   {
     return mStoredFile;
   }
 
   virtual bool
-  IsWholeFile() const
+  IsWholeFile() const MOZ_OVERRIDE
   {
     return mWholeFile;
   }
 
   virtual bool
-  IsSnapshot() const
+  IsSnapshot() const MOZ_OVERRIDE
   {
     return true;
   }
 
 private:
   nsCOMPtr<nsIFile> mFile;
   nsRefPtr<LockedFile> mLockedFile;
 
--- a/dom/file/FileRequest.h
+++ b/dom/file/FileRequest.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_filerequest_h__
 #define mozilla_dom_file_filerequest_h__
 
+#include "mozilla/Attributes.h"
 #include "FileCommon.h"
 
 #include "DOMRequest.h"
 
 BEGIN_FILE_NAMESPACE
 
 class FileHelper;
 class LockedFile;
@@ -22,17 +23,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileRequest, DOMRequest)
 
   static already_AddRefed<FileRequest>
   Create(nsIDOMWindow* aOwner, LockedFile* aLockedFile, bool aIsFileRequest);
 
   // nsIDOMEventTarget
   virtual nsresult
-  PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+  PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
 
   void
   OnProgress(uint64_t aProgress, uint64_t aProgressMax)
   {
     FireProgressEvent(aProgress, aProgressMax);
   }
 
   nsresult
--- a/dom/file/FileService.h
+++ b/dom/file/FileService.h
@@ -65,26 +65,26 @@ public:
 
 private:
   class LockedFileQueue MOZ_FINAL : public FileHelperListener
   {
     friend class FileService;
 
   public:
     NS_IMETHOD_(nsrefcnt)
-    AddRef();
+    AddRef() MOZ_OVERRIDE;
 
     NS_IMETHOD_(nsrefcnt)
-    Release();
+    Release() MOZ_OVERRIDE;
 
     inline nsresult
     Enqueue(FileHelper* aFileHelper);
 
     virtual void
-    OnFileHelperComplete(FileHelper* aFileHelper);
+    OnFileHelperComplete(FileHelper* aFileHelper) MOZ_OVERRIDE;
 
   private:
     inline
     LockedFileQueue(LockedFile* aLockedFile);
 
     nsresult
     ProcessQueue();
 
--- a/dom/file/LockedFile.h
+++ b/dom/file/LockedFile.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_lockedfile_h__
 #define mozilla_dom_file_lockedfile_h__
 
+#include "mozilla/Attributes.h"
 #include "FileCommon.h"
 
 #include "nsIDOMLockedFile.h"
 #include "nsIRunnable.h"
 
 #include "nsDOMEventTargetHelper.h"
 
 class nsIInputStream;
@@ -60,17 +61,17 @@ public:
 
   static already_AddRefed<LockedFile>
   Create(FileHandle* aFileHandle,
          Mode aMode,
          RequestMode aRequestMode = NORMAL);
 
   // nsIDOMEventTarget
   virtual nsresult
-  PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+  PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
 
   nsresult
   CreateParallelStream(nsISupports** aStream);
 
   nsresult
   GetOrCreateStream(nsISupports** aStream);
 
   bool
--- a/dom/file/MetadataHelper.h
+++ b/dom/file/MetadataHelper.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_file_metadatahelper_h__
 #define mozilla_dom_file_metadatahelper_h__
 
+#include "mozilla/Attributes.h"
 #include "FileCommon.h"
 
 #include "nsIFileStreams.h"
 
 #include "DictionaryHelpers.h"
 
 #include "AsyncHelper.h"
 #include "FileHelper.h"
@@ -85,34 +86,34 @@ public:
   MetadataHelper(LockedFile* aLockedFile,
                  FileRequest* aFileRequest,
                  MetadataParameters* aParams)
   : FileHelper(aLockedFile, aFileRequest),
     mParams(aParams)
   { }
 
   nsresult
-  DoAsyncRun(nsISupports* aStream);
+  DoAsyncRun(nsISupports* aStream) MOZ_OVERRIDE;
 
   nsresult
-  GetSuccessResult(JSContext* aCx, JS::Value* aVal);
+  GetSuccessResult(JSContext* aCx, JS::Value* aVal) MOZ_OVERRIDE;
 
 protected:
   class AsyncMetadataGetter : public AsyncHelper
   {
   public:
     AsyncMetadataGetter(nsISupports* aStream, MetadataParameters* aParams,
                         bool aReadWrite)
     : AsyncHelper(aStream),
       mParams(aParams), mReadWrite(aReadWrite)
     { }
 
   protected:
     nsresult
-    DoStreamWork(nsISupports* aStream);
+    DoStreamWork(nsISupports* aStream) MOZ_OVERRIDE;
 
   private:
     nsRefPtr<MetadataParameters> mParams;
     bool mReadWrite;
   };
 
   nsRefPtr<MetadataParameters> mParams;
 };
--- a/dom/indexedDB/Client.cpp
+++ b/dom/indexedDB/Client.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/dom/quota/UsageRunnable.h"
 #include "mozilla/dom/quota/Utilities.h"
 
 #include "IDBDatabase.h"
 #include "IndexedDatabaseManager.h"
 #include "TransactionThreadPool.h"
 
 USING_INDEXEDDB_NAMESPACE
+using mozilla::dom::quota::AssertIsOnIOThread;
 using mozilla::dom::quota::QuotaManager;
 
 namespace {
 
 bool
 GetDatabaseBaseFilename(const nsAString& aFilename,
                         nsAString& aDatabaseBaseFilename)
 {
@@ -41,16 +42,18 @@ GetDatabaseBaseFilename(const nsAString&
 
 // This needs to be fully qualified to not confuse trace refcnt assertions.
 NS_IMPL_ADDREF(mozilla::dom::indexedDB::Client)
 NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client)
 
 nsresult
 Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable)
 {
+  AssertIsOnIOThread();
+
   nsCOMPtr<nsIFile> directory;
   nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We need to see if there are any files in the directory already. If they
   // are database files then we need to cleanup stored files (if it's needed)
   // and also get the usage.
 
@@ -157,38 +160,64 @@ Client::InitOrigin(const nsACString& aOr
 
   return NS_OK;
 }
 
 nsresult
 Client::GetUsageForOrigin(const nsACString& aOrigin,
                           UsageRunnable* aUsageRunnable)
 {
+  AssertIsOnIOThread();
   NS_ASSERTION(aUsageRunnable, "Null pointer!");
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = GetUsageForDirectoryInternal(directory, aUsageRunnable, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
+void
+Client::OnOriginClearCompleted(const nsACString& aPattern)
+{
+  AssertIsOnIOThread();
+
+  IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+  if (mgr) {
+    mgr->InvalidateFileManagersForPattern(aPattern);
+  }
+}
+
+void
+Client::ReleaseIOThreadObjects()
+{
+  AssertIsOnIOThread();
+
+  IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+  if (mgr) {
+    mgr->InvalidateAllFileManagers();
+  }
+}
+
 bool
 Client::IsTransactionServiceActivated()
 {
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
   return !!TransactionThreadPool::Get();
 }
 
 void
 Client::WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
                                   nsIRunnable* aCallback)
 {
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!aStorages.IsEmpty(), "No storages to wait on!");
   NS_ASSERTION(aCallback, "Passed null callback!");
 
   TransactionThreadPool* pool = TransactionThreadPool::Get();
   NS_ASSERTION(pool, "Should have checked if transaction service is active!");
 
   nsTArray<nsRefPtr<IDBDatabase> > databases(aStorages.Length());
   for (uint32_t index = 0; index < aStorages.Length(); index++) {
@@ -201,61 +230,48 @@ Client::WaitForStoragesToComplete(nsTArr
   }
 
   pool->WaitForDatabasesToComplete(databases, aCallback);
 }
 
 void
 Client::AbortTransactionsForStorage(nsIOfflineStorage* aStorage)
 {
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aStorage, "Passed null storage!");
 
   TransactionThreadPool* pool = TransactionThreadPool::Get();
   NS_ASSERTION(pool, "Should have checked if transaction service is active!");
 
   IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
   NS_ASSERTION(database, "This shouldn't be null!");
 
   pool->AbortTransactionsForDatabase(database);
 }
 
 bool
 Client::HasTransactionsForStorage(nsIOfflineStorage* aStorage)
 {
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
   TransactionThreadPool* pool = TransactionThreadPool::Get();
   NS_ASSERTION(pool, "Should have checked if transaction service is active!");
 
   IDBDatabase* database = IDBDatabase::FromStorage(aStorage);
   NS_ASSERTION(database, "This shouldn't be null!");
 
   return pool->HasTransactionsForDatabase(database);
 }
 
 void
-Client::OnOriginClearCompleted(const nsACString& aPattern)
-{
-  IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
-  if (mgr) {
-    mgr->InvalidateFileManagersForPattern(aPattern);
-  }
-}
-
-void
 Client::ShutdownTransactionService()
 {
-  TransactionThreadPool::Shutdown();
-}
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-void
-Client::OnShutdownCompleted()
-{
-  IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
-  if (mgr) {
-    mgr->InvalidateAllFileManagers();
-  }
+  TransactionThreadPool::Shutdown();
 }
 
 nsresult
 Client::GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory)
 {
   QuotaManager* quotaManager = QuotaManager::Get();
   NS_ASSERTION(quotaManager, "This should never fail!");
 
--- a/dom/indexedDB/Client.h
+++ b/dom/indexedDB/Client.h
@@ -36,16 +36,22 @@ public:
   virtual nsresult
   InitOrigin(const nsACString& aOrigin,
              UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
 
   virtual nsresult
   GetUsageForOrigin(const nsACString& aOrigin,
                     UsageRunnable* aUsageRunnable) MOZ_OVERRIDE;
 
+  virtual void
+  OnOriginClearCompleted(const nsACString& aPattern) MOZ_OVERRIDE;
+
+  virtual void
+  ReleaseIOThreadObjects() MOZ_OVERRIDE;
+
   virtual bool
   IsFileServiceUtilized() MOZ_OVERRIDE
   {
     return true;
   }
 
   virtual bool
   IsTransactionServiceActivated() MOZ_OVERRIDE;
@@ -56,24 +62,18 @@ public:
 
   virtual void
   AbortTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
 
   virtual bool
   HasTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE;
 
   virtual void
-  OnOriginClearCompleted(const nsACString& aPattern) MOZ_OVERRIDE;
-
-  virtual void
   ShutdownTransactionService() MOZ_OVERRIDE;
 
-  virtual void
-  OnShutdownCompleted() MOZ_OVERRIDE;
-
 private:
   nsresult
   GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory);
 
   nsresult
   GetUsageForDirectoryInternal(nsIFile* aDirectory,
                                UsageRunnable* aUsageRunnable,
                                bool aDatabaseFiles);
--- a/dom/indexedDB/FileInfo.cpp
+++ b/dom/indexedDB/FileInfo.cpp
@@ -68,38 +68,44 @@ void
 FileInfo::UpdateReferences(nsAutoRefCnt& aRefCount, int32_t aDelta,
                            bool aClear)
 {
   if (IndexedDatabaseManager::IsClosed()) {
     NS_ERROR("Shouldn't be called after shutdown!");
     return;
   }
 
+  bool needsCleanup;
   {
     MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
 
     aRefCount = aClear ? 0 : aRefCount + aDelta;
 
     if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) {
       return;
     }
 
     mFileManager->mFileInfos.Remove(Id());
+
+    needsCleanup = !mFileManager->Invalidated();
   }
 
-  Cleanup();
+  if (needsCleanup) {
+    Cleanup();
+  }
 
   delete this;
 }
 
 void
 FileInfo::Cleanup()
 {
-  if (quota::QuotaManager::IsShuttingDown() ||
-      mFileManager->Invalidated()) {
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  if (quota::QuotaManager::IsShuttingDown()) {
     return;
   }
 
   nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
   NS_ASSERTION(mgr, "Shouldn't be null!");
 
   if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, Id()))) {
     NS_WARNING("Failed to delete file asynchronously!");
--- a/dom/indexedDB/FileInfo.h
+++ b/dom/indexedDB/FileInfo.h
@@ -22,21 +22,17 @@ class FileInfo
   friend class FileManager;
 
 public:
   FileInfo(FileManager* aFileManager)
   : mFileManager(aFileManager)
   { }
 
   virtual ~FileInfo()
-  {
-#ifdef DEBUG
-    NS_ASSERTION(NS_IsMainThread(), "File info destroyed on wrong thread!");
-#endif
-  }
+  { }
 
   static
   FileInfo* Create(FileManager* aFileManager, int64_t aId);
 
   void AddRef()
   {
     if (IndexedDatabaseManager::IsClosed()) {
       NS_AtomicIncrementRefcnt(mRefCnt);
--- a/dom/indexedDB/FileManager.cpp
+++ b/dom/indexedDB/FileManager.cpp
@@ -19,16 +19,17 @@
 #include "FileInfo.h"
 #include "IndexedDatabaseManager.h"
 #include "OpenDatabaseHelper.h"
 
 #include "IndexedDatabaseInlines.h"
 #include <algorithm>
 
 USING_INDEXEDDB_NAMESPACE
+using mozilla::dom::quota::AssertIsOnIOThread;
 
 namespace {
 
 PLDHashOperator
 EnumerateToTArray(const uint64_t& aKey,
                   FileInfo* aValue,
                   void* aUserArg)
 {
@@ -57,17 +58,17 @@ GetDirectoryFor(const nsAString& aDirect
 }
 
 } // anonymous namespace
 
 nsresult
 FileManager::Init(nsIFile* aDirectory,
                   mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(aDirectory, "Null directory!");
   NS_ASSERTION(aConnection, "Null connection!");
 
   mFileInfos.Init();
 
   bool exists;
   nsresult rv = aDirectory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -264,17 +265,17 @@ FileManager::GetFileForId(nsIFile* aDire
 }
 
 // static
 nsresult
 FileManager::InitDirectory(nsIFile* aDirectory,
                            nsIFile* aDatabaseFile,
                            const nsACString& aOrigin)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(aDirectory, "Null directory!");
   NS_ASSERTION(aDatabaseFile, "Null database file!");
 
   bool exists;
   nsresult rv = aDirectory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!exists) {
@@ -380,17 +381,17 @@ FileManager::InitDirectory(nsIFile* aDir
 
   return NS_OK;
 }
 
 // static
 nsresult
 FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
 
   bool exists;
   nsresult rv = aDirectory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!exists) {
     *aUsage = 0;
     return NS_OK;
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -35,16 +35,17 @@
 
 #include "ipc/IndexedDBChild.h"
 #include "ipc/IndexedDBParent.h"
 
 #include "mozilla/dom/IDBDatabaseBinding.h"
 
 USING_INDEXEDDB_NAMESPACE
 using mozilla::dom::ContentParent;
+using mozilla::dom::quota::AssertIsOnIOThread;
 using mozilla::dom::quota::Client;
 using mozilla::dom::quota::QuotaManager;
 using namespace mozilla::dom;
 
 namespace {
 
 class NoRequestDatabaseHelper : public AsyncConnectionHelper
 {
@@ -970,17 +971,17 @@ DeleteObjectStoreHelper::DoDatabaseWork(
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   return NS_OK;
 }
 
 nsresult
 CreateFileHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "CreateFileHelper::DoDatabaseWork");
 
   if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
     NS_WARNING("Refusing to create file because disk space is low!");
     return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
   }
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_indexeddb_idbdatabase_h__
 #define mozilla_dom_indexeddb_idbdatabase_h__
 
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
 
 #include "nsIDocument.h"
 #include "nsIFileStorage.h"
 #include "nsIIDBDatabase.h"
 #include "nsIOfflineStorage.h"
 
 #include "nsDOMEventTargetHelper.h"
@@ -74,17 +75,17 @@ public:
   static IDBDatabase*
   FromStorage(nsIFileStorage* aStorage)
   {
     nsCOMPtr<nsIOfflineStorage> storage = do_QueryInterface(aStorage);
     return storage ? FromStorage(storage) : nullptr;
   }
 
   // nsIDOMEventTarget
-  virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
+  virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
 
   DatabaseInfo* Info() const
   {
     return mDatabaseInfo;
   }
 
   const nsString& Name() const
   {
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -329,17 +329,17 @@ IgnoreWhitespace(PRUnichar c)
 
 // static
 nsresult
 IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
                                     nsIAtom* aDatabaseId,
                                     uint64_t* aVersion,
                                     ObjectStoreInfoArray& aObjectStores)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(aConnection, "Null pointer!");
 
   aObjectStores.Clear();
 
    // Load object store names and ids.
   nsCOMPtr<mozIStorageStatement> stmt;
   nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
     "SELECT name, id, key_path, auto_increment "
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_indexeddb_idbrequest_h__
 #define mozilla_dom_indexeddb_idbrequest_h__
 
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
 
 #include "nsIIDBRequest.h"
 #include "nsIIDBOpenDBRequest.h"
 #include "nsDOMEventTargetHelper.h"
 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
 #include "mozilla/dom/DOMError.h"
 
@@ -36,17 +37,17 @@ public:
 
   static
   already_AddRefed<IDBRequest> Create(nsISupports* aSource,
                                       IDBWrapperCache* aOwnerCache,
                                       IDBTransaction* aTransaction,
                                       JSContext* aCallingCx);
 
   // nsIDOMEventTarget
-  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
 
   nsISupports* Source()
   {
     return mSource;
   }
 
   void Reset();
 
@@ -134,17 +135,17 @@ public:
   Create(IDBFactory* aFactory,
          nsPIDOMWindow* aOwner,
          JS::Handle<JSObject*> aScriptOwner,
          JSContext* aCallingCx);
 
   void SetTransaction(IDBTransaction* aTransaction);
 
   // nsIDOMEventTarget
-  virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
+  virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
 
   DOMError* GetError(ErrorResult& aRv)
   {
     return IDBRequest::GetError(aRv);
   }
 
   IDBFactory*
   Factory() const
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_indexeddb_idbtransaction_h__
 #define mozilla_dom_indexeddb_idbtransaction_h__
 
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
 
 #include "mozIStorageConnection.h"
 #include "mozIStorageStatement.h"
 #include "mozIStorageFunction.h"
 #include "nsIIDBTransaction.h"
 #include "mozilla/dom/DOMError.h"
 #include "nsIRunnable.h"
@@ -93,17 +94,17 @@ public:
          Mode aMode,
          bool aDispatchDelayed)
   {
     return CreateInternal(aDatabase, aObjectStoreNames, aMode, aDispatchDelayed,
                           false);
   }
 
   // nsIDOMEventTarget
-  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
 
   void OnNewRequest();
   void OnRequestFinished();
   void OnRequestDisconnected();
 
   void RemoveObjectStore(const nsAString& aName);
 
   void SetTransactionListener(IDBTransactionListener* aListener);
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -10,16 +10,17 @@
 #include "nsIDiskSpaceWatcher.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsIFile.h"
 #include "nsIFileStorage.h"
 #include "nsIObserverService.h"
 #include "nsIScriptError.h"
 
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/CondVar.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/Utilities.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/Services.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsThreadUtils.h"
@@ -55,23 +56,62 @@ public:
 
   AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId);
 
 private:
   nsRefPtr<FileManager> mFileManager;
   int64_t mFileId;
 };
 
+class GetFileReferencesHelper MOZ_FINAL : public nsIRunnable
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIRUNNABLE
+
+  GetFileReferencesHelper(const nsACString& aOrigin,
+                          const nsAString& aDatabaseName,
+                          int64_t aFileId)
+  : mOrigin(aOrigin), mDatabaseName(aDatabaseName), mFileId(aFileId),
+    mMutex(IndexedDatabaseManager::FileMutex()),
+    mCondVar(mMutex, "GetFileReferencesHelper::mCondVar"),
+    mMemRefCnt(-1),
+    mDBRefCnt(-1),
+    mSliceRefCnt(-1),
+    mResult(false),
+    mWaiting(true)
+  { }
+
+  nsresult
+  DispatchAndReturnFileReferences(int32_t* aMemRefCnt,
+                                  int32_t* aDBRefCnt,
+                                  int32_t* aSliceRefCnt,
+                                  bool* aResult);
+
+private:
+  nsCString mOrigin;
+  nsString mDatabaseName;
+  int64_t mFileId;
+
+  mozilla::Mutex& mMutex;
+  mozilla::CondVar mCondVar;
+  int32_t mMemRefCnt;
+  int32_t mDBRefCnt;
+  int32_t mSliceRefCnt;
+  bool mResult;
+  bool mWaiting;
+};
+
 PLDHashOperator
 InvalidateAndRemoveFileManagers(
                            const nsACString& aKey,
                            nsAutoPtr<nsTArray<nsRefPtr<FileManager> > >& aValue,
                            void* aUserArg)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
   NS_ASSERTION(aValue, "Null pointer!");
 
   const nsACString* pattern =
     static_cast<const nsACString*>(aUserArg);
 
   if (!pattern || PatternMatchesOrigin(*pattern, aKey)) {
     for (uint32_t i = 0; i < aValue->Length(); i++) {
@@ -342,16 +382,18 @@ IndexedDatabaseManager::InLowDiskSpaceMo
   return !!sLowDiskSpaceMode;
 }
 #endif
 
 already_AddRefed<FileManager>
 IndexedDatabaseManager::GetFileManager(const nsACString& aOrigin,
                                        const nsAString& aDatabaseName)
 {
+  AssertIsOnIOThread();
+
   nsTArray<nsRefPtr<FileManager> >* array;
   if (!mFileManagers.Get(aOrigin, &array)) {
     return nullptr;
   }
 
   for (uint32_t i = 0; i < array->Length(); i++) {
     nsRefPtr<FileManager>& fileManager = array->ElementAt(i);
 
@@ -362,46 +404,53 @@ IndexedDatabaseManager::GetFileManager(c
   }
 
   return nullptr;
 }
 
 void
 IndexedDatabaseManager::AddFileManager(FileManager* aFileManager)
 {
+  AssertIsOnIOThread();
   NS_ASSERTION(aFileManager, "Null file manager!");
 
   nsTArray<nsRefPtr<FileManager> >* array;
   if (!mFileManagers.Get(aFileManager->Origin(), &array)) {
     array = new nsTArray<nsRefPtr<FileManager> >();
     mFileManagers.Put(aFileManager->Origin(), array);
   }
 
   array->AppendElement(aFileManager);
 }
 
 void
 IndexedDatabaseManager::InvalidateAllFileManagers()
 {
+  AssertIsOnIOThread();
+
   mFileManagers.Enumerate(InvalidateAndRemoveFileManagers, nullptr);
 }
 
 void
 IndexedDatabaseManager::InvalidateFileManagersForPattern(
                                                      const nsACString& aPattern)
 {
+  AssertIsOnIOThread();
   NS_ASSERTION(!aPattern.IsEmpty(), "Empty pattern!");
+
   mFileManagers.Enumerate(InvalidateAndRemoveFileManagers,
                           const_cast<nsACString*>(&aPattern));
 }
 
 void
 IndexedDatabaseManager::InvalidateFileManager(const nsACString& aOrigin,
                                               const nsAString& aDatabaseName)
 {
+  AssertIsOnIOThread();
+
   nsTArray<nsRefPtr<FileManager> >* array;
   if (!mFileManagers.Get(aOrigin, &array)) {
     return;
   }
 
   for (uint32_t i = 0; i < array->Length(); i++) {
     nsRefPtr<FileManager> fileManager = array->ElementAt(i);
     if (fileManager->DatabaseName().Equals(aDatabaseName)) {
@@ -439,16 +488,36 @@ IndexedDatabaseManager::AsyncDeleteFile(
 
   nsresult rv =
     quotaManager->IOThread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
+nsresult
+IndexedDatabaseManager::BlockAndGetFileReferences(
+                                                 const nsACString& aOrigin,
+                                                 const nsAString& aDatabaseName,
+                                                 int64_t aFileId,
+                                                 int32_t* aRefCnt,
+                                                 int32_t* aDBRefCnt,
+                                                 int32_t* aSliceRefCnt,
+                                                 bool* aResult)
+{
+  nsRefPtr<GetFileReferencesHelper> helper =
+    new GetFileReferencesHelper(aOrigin, aDatabaseName, aFileId);
+
+  nsresult rv = helper->DispatchAndReturnFileReferences(aRefCnt, aDBRefCnt,
+                                                        aSliceRefCnt, aResult);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
 NS_IMPL_ADDREF(IndexedDatabaseManager)
 NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy())
 NS_IMPL_QUERY_INTERFACE2(IndexedDatabaseManager, nsIIndexedDatabaseManager,
                                                  nsIObserver)
 
 NS_IMETHODIMP
 IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
 {
@@ -543,17 +612,17 @@ AsyncDeleteFileRunnable::AsyncDeleteFile
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteFileRunnable,
                               nsIRunnable)
 
 NS_IMETHODIMP
 AsyncDeleteFileRunnable::Run()
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
 
   nsCOMPtr<nsIFile> directory = mFileManager->GetDirectory();
   NS_ENSURE_TRUE(directory, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIFile> file = mFileManager->GetFileForId(directory, mFileId);
   NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
 
   nsresult rv;
@@ -580,8 +649,74 @@ AsyncDeleteFileRunnable::Run()
   file = mFileManager->GetFileForId(directory, mFileId);
   NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
 
   rv = file->Remove(false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
+
+nsresult
+GetFileReferencesHelper::DispatchAndReturnFileReferences(int32_t* aMemRefCnt,
+                                                         int32_t* aDBRefCnt,
+                                                         int32_t* aSliceRefCnt,
+                                                         bool* aResult)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  QuotaManager* quotaManager = QuotaManager::Get();
+  NS_ASSERTION(quotaManager, "Shouldn't be null!");
+
+  nsresult rv =
+    quotaManager->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mozilla::MutexAutoLock autolock(mMutex);
+  while (mWaiting) {
+    mCondVar.Wait();
+  }
+
+  *aMemRefCnt = mMemRefCnt;
+  *aDBRefCnt = mDBRefCnt;
+  *aSliceRefCnt = mSliceRefCnt;
+  *aResult = mResult;
+
+  return NS_OK;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(GetFileReferencesHelper,
+                              nsIRunnable)
+
+NS_IMETHODIMP
+GetFileReferencesHelper::Run()
+{
+  AssertIsOnIOThread();
+
+  IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+  NS_ASSERTION(mgr, "This should never fail!");
+
+  nsRefPtr<FileManager> fileManager =
+    mgr->GetFileManager(mOrigin, mDatabaseName);
+
+  if (fileManager) {
+    nsRefPtr<FileInfo> fileInfo = fileManager->GetFileInfo(mFileId);
+
+    if (fileInfo) {
+      fileInfo->GetReferences(&mMemRefCnt, &mDBRefCnt, &mSliceRefCnt);
+
+      if (mMemRefCnt != -1) {
+        // We added an extra temp ref, so account for that accordingly.
+        mMemRefCnt--;
+      }
+
+      mResult = true;
+    }
+  }
+
+  mozilla::MutexAutoLock lock(mMutex);
+  NS_ASSERTION(mWaiting, "Huh?!");
+
+  mWaiting = false;
+  mCondVar.Notify();
+
+  return NS_OK;
+}
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -91,16 +91,28 @@ public:
   void
   InvalidateFileManager(const nsACString& aOrigin,
                         const nsAString& aDatabaseName);
 
   nsresult
   AsyncDeleteFile(FileManager* aFileManager,
                   int64_t aFileId);
 
+  // Don't call this method in real code, it blocks the main thread!
+  // It is intended to be used by mochitests to test correctness of the special
+  // reference counting of stored blobs/files.
+  nsresult
+  BlockAndGetFileReferences(const nsACString& aOrigin,
+                            const nsAString& aDatabaseName,
+                            int64_t aFileId,
+                            int32_t* aRefCnt,
+                            int32_t* aDBRefCnt,
+                            int32_t* aSliceRefCnt,
+                            bool* aResult);
+
   static mozilla::Mutex&
   FileMutex()
   {
     IndexedDatabaseManager* mgr = Get();
     NS_ASSERTION(mgr, "Must have a manager here!");
 
     return mgr->mFileMutex;
   }
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -91,17 +91,17 @@ GetDatabaseFilename(const nsAString& aNa
   aDatabaseFilename.Append(NS_ConvertASCIItoUTF16(substring));
 
   return NS_OK;
 }
 
 nsresult
 CreateFileTables(mozIStorageConnection* aDBConn)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "CreateFileTables");
 
   // Table `file`
   nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE file ("
       "id INTEGER PRIMARY KEY, "
@@ -153,17 +153,17 @@ CreateFileTables(mozIStorageConnection* 
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 CreateTables(mozIStorageConnection* aDBConn)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(aDBConn, "Passing a null database connection!");
 
   PROFILER_LABEL("IndexedDB", "CreateTables");
 
   // Table `database`
   nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE database ("
@@ -270,17 +270,17 @@ CreateTables(mozIStorageConnection* aDBC
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 UpgradeSchemaFrom4To5(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom4To5");
 
   nsresult rv;
 
   // All we changed is the type of the version column, so lets try to
   // convert that to an integer, and if we fail, set it to 0.
@@ -359,17 +359,17 @@ UpgradeSchemaFrom4To5(mozIStorageConnect
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 UpgradeSchemaFrom5To6(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom5To6");
 
   // First, drop all the indexes we're no longer going to use.
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "DROP INDEX key_index;"
   ));
@@ -717,17 +717,17 @@ UpgradeSchemaFrom5To6(mozIStorageConnect
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 UpgradeSchemaFrom6To7(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom6To7");
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TEMPORARY TABLE temp_upgrade ("
       "id, "
       "name, "
@@ -776,17 +776,17 @@ UpgradeSchemaFrom6To7(mozIStorageConnect
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 UpgradeSchemaFrom7To8(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom7To8");
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TEMPORARY TABLE temp_upgrade ("
       "id, "
       "object_store_id, "
@@ -900,17 +900,17 @@ public:
   }
 };
 
 NS_IMPL_ISUPPORTS1(CompressDataBlobsFunction, mozIStorageFunction)
 
 nsresult
 UpgradeSchemaFrom8To9_0(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom8To9_0");
 
   // We no longer use the dataVersion column.
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "UPDATE database SET dataVersion = 0;"
   ));
@@ -941,17 +941,17 @@ UpgradeSchemaFrom8To9_0(mozIStorageConne
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 UpgradeSchemaFrom9_0To10_0(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom9_0To10_0");
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "ALTER TABLE object_data ADD COLUMN file_ids TEXT;"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -968,17 +968,17 @@ UpgradeSchemaFrom9_0To10_0(mozIStorageCo
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 UpgradeSchemaFrom10_0To11_0(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom10_0To11_0");
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TEMPORARY TABLE temp_upgrade ("
       "id, "
       "object_store_id, "
@@ -1158,17 +1158,17 @@ public:
   }
 };
 
 NS_IMPL_ISUPPORTS1(EncodeKeysFunction, mozIStorageFunction)
 
 nsresult
 UpgradeSchemaFrom11_0To12_0(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom11_0To12_0");
 
   NS_NAMED_LITERAL_CSTRING(encoderName, "encode");
 
   nsCOMPtr<mozIStorageFunction> encoder = new EncodeKeysFunction();
 
@@ -1375,17 +1375,17 @@ UpgradeSchemaFrom11_0To12_0(mozIStorageC
 
   return NS_OK;
 }
 
 nsresult
 UpgradeSchemaFrom12_0To13_0(mozIStorageConnection* aConnection,
                             bool* aVacuumNeeded)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom12_0To13_0");
 
   nsresult rv;
 
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
   int32_t defaultPageSize;
@@ -1712,25 +1712,17 @@ OpenDatabaseHelper::RunImmediately()
 
   mState = eFiringEvents;
   return this->Run();
 }
 
 nsresult
 OpenDatabaseHelper::DoDatabaseWork()
 {
-#ifdef DEBUG
-  {
-    bool correctThread;
-    NS_ASSERTION(NS_SUCCEEDED(QuotaManager::Get()->IOThread()->
-                              IsOnCurrentThread(&correctThread)) &&
-                 correctThread,
-                 "Running on the wrong thread!");
-  }
-#endif
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "OpenDatabaseHelper::DoDatabaseWork");
 
   mState = eFiringEvents; // In case we fail somewhere along the line.
 
   if (QuotaManager::IsShuttingDown()) {
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -1866,17 +1858,17 @@ OpenDatabaseHelper::DoDatabaseWork()
 nsresult
 OpenDatabaseHelper::CreateDatabaseConnection(
                                         nsIFile* aDBFile,
                                         nsIFile* aFMDirectory,
                                         const nsAString& aName,
                                         const nsACString& aOrigin,
                                         mozIStorageConnection** aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "OpenDatabaseHelper::CreateDatabaseConnection");
 
   nsresult rv;
   bool exists;
 
   if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
@@ -2167,21 +2159,16 @@ OpenDatabaseHelper::Run()
       }
 
       case eDeleteCompleted: {
         // Destroy the database now (we should have the only ref).
         mDatabase = nullptr;
 
         DatabaseInfo::Remove(mDatabaseId);
 
-        IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
-        NS_ASSERTION(mgr, "This should never fail!");
-
-        mgr->InvalidateFileManager(mASCIIOrigin, mName);
-
         mState = eFiringEvents;
         break;
       }
 
       case eFiringEvents: {
         // Notify the request that we're done, but only if we didn't just
         // finish a [SetVersion/DeleteDatabase]Helper.  In that case, the
         // helper tells the request that it is done, and we avoid calling
@@ -2574,17 +2561,17 @@ SetVersionHelper::NotifyTransactionPostC
   return rv;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(DeleteDatabaseHelper, AsyncConnectionHelper);
 
 nsresult
 DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(!aConnection, "How did we get a connection here?");
 
   PROFILER_LABEL("IndexedDB", "DeleteDatabaseHelper::DoDatabaseWork");
 
   const StoragePrivilege& privilege = mOpenHelper->Privilege();
 
   QuotaManager* quotaManager = QuotaManager::Get();
@@ -2678,16 +2665,21 @@ DeleteDatabaseHelper::DoDatabaseWork(moz
     if (privilege != Chrome) {
       QuotaManager* quotaManager = QuotaManager::Get();
       NS_ASSERTION(quotaManager, "Shouldn't be null!");
 
       quotaManager->DecreaseUsageForOrigin(mASCIIOrigin, usage);
     }
   }
 
+  IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
+  NS_ASSERTION(mgr, "This should never fail!");
+
+  mgr->InvalidateFileManager(mASCIIOrigin, mName);
+
   return NS_OK;
 }
 
 nsresult
 DeleteDatabaseHelper::GetSuccessResult(JSContext* aCx, jsval* aVal)
 {
   return NS_OK;
 }
--- a/dom/indexedDB/ipc/IndexedDBParent.h
+++ b/dom/indexedDB/ipc/IndexedDBParent.h
@@ -92,17 +92,17 @@ public:
 
   void
   NoteDyingActor()
   {
     mActor = NULL;
   }
 
   NS_IMETHOD
-  HandleEvent(nsIDOMEvent* aEvent)
+  HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE
   {
     return mActor ? mActor->HandleEvent(aEvent) : NS_OK;
   }
 
 protected:
   virtual ~WeakEventListener()
   { }
 };
--- a/dom/interfaces/events/moz.build
+++ b/dom/interfaces/events/moz.build
@@ -20,16 +20,17 @@ XPIDL_SOURCES += [
     'nsIDOMDeviceMotionEvent.idl',
     'nsIDOMDeviceOrientationEvent.idl',
     'nsIDOMDeviceProximityEvent.idl',
     'nsIDOMDragEvent.idl',
     'nsIDOMElementReplaceEvent.idl',
     'nsIDOMEvent.idl',
     'nsIDOMEventListener.idl',
     'nsIDOMEventTarget.idl',
+    'nsIDOMFocusEvent.idl',
     'nsIDOMGamepadAxisMoveEvent.idl',
     'nsIDOMGamepadButtonEvent.idl',
     'nsIDOMGamepadEvent.idl',
     'nsIDOMHashChangeEvent.idl',
     'nsIDOMKeyEvent.idl',
     'nsIDOMMessageEvent.idl',
     'nsIDOMMouseEvent.idl',
     'nsIDOMMouseScrollEvent.idl',
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -275,16 +275,21 @@ NS_NewDOMUIEvent(nsIDOMEvent** aInstance
                  nsPresContext* aPresContext,
                  class nsGUIEvent* aEvent);
 nsresult
 NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult,
                     mozilla::dom::EventTarget* aOwner,
                     nsPresContext* aPresContext,
                     class nsInputEvent* aEvent);
 nsresult
+NS_NewDOMFocusEvent(nsIDOMEvent** aInstancePtrResult,
+                    mozilla::dom::EventTarget* aOwner,
+                    nsPresContext* aPresContext,
+                    class nsFocusEvent* aEvent);
+nsresult
 NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult,
                           mozilla::dom::EventTarget* aOwner,
                           nsPresContext* aPresContext,
                           class nsInputEvent* aEvent);
 nsresult
 NS_NewDOMWheelEvent(nsIDOMEvent** aInstancePtrResult,
                     mozilla::dom::EventTarget* aOwner,
                     nsPresContext* aPresContext,
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/events/nsIDOMFocusEvent.idl
@@ -0,0 +1,12 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMUIEvent.idl"
+
+[scriptable, builtinclass, uuid(4faecbd6-1bcd-42d8-bc66-ec6b95050063)]
+interface nsIDOMFocusEvent : nsIDOMUIEvent
+{
+  readonly attribute nsIDOMEventTarget  relatedTarget;
+};
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -106,20 +106,20 @@ public:
     NS_DECL_NSIOBSERVER
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
 
     /**
      * MessageManagerCallback methods that we override.
      */
     virtual bool DoSendAsyncMessage(const nsAString& aMessage,
-                                    const mozilla::dom::StructuredCloneData& aData);
-    virtual bool CheckPermission(const nsAString& aPermission);
-    virtual bool CheckManifestURL(const nsAString& aManifestURL);
-    virtual bool CheckAppHasPermission(const nsAString& aPermission);
+                                    const mozilla::dom::StructuredCloneData& aData) MOZ_OVERRIDE;
+    virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE;
+    virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE;
+    virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE;
 
     /** Notify that a tab is beginning its destruction sequence. */
     void NotifyTabDestroying(PBrowserParent* aTab);
     /** Notify that a tab was destroyed during normal operation. */
     void NotifyTabDestroyed(PBrowserParent* aTab,
                             bool aNotifiedDestroying);
 
     TestShellParent* CreateTestShell();
@@ -162,17 +162,17 @@ public:
      * Get a user-friendly name for this ContentParent.  We make no guarantees
      * about this name: It might not be unique, apps can spoof special names,
      * etc.  So please don't use this name to make any decisions about the
      * ContentParent based on the value returned here.
      */
     void FriendlyName(nsAString& aName);
 
 protected:
-    void OnChannelConnected(int32_t pid);
+    void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
     virtual void ActorDestroy(ActorDestroyReason why);
 
 private:
     static nsDataHashtable<nsStringHashKey, ContentParent*> *sAppContentParents;
     static nsTArray<ContentParent*>* sNonAppContentParents;
     static nsTArray<ContentParent*>* sPrivateContent;
     static LinkedList<ContentParent> sContentParents;
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -86,50 +86,50 @@ public:
                              JSContext* aCx,
                              uint8_t aArgc,
                              JS::Value* aRetval)
   {
     return mMessageManager
       ? mMessageManager->SendSyncMessage(aMessageName, aObject, aCx, aArgc, aRetval)
       : NS_ERROR_NULL_POINTER;
   }
-  NS_IMETHOD GetContent(nsIDOMWindow** aContent);
-  NS_IMETHOD GetDocShell(nsIDocShell** aDocShell);
-  NS_IMETHOD Dump(const nsAString& aStr)
+  NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE;
+  NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) MOZ_OVERRIDE;
+  NS_IMETHOD Dump(const nsAString& aStr) MOZ_OVERRIDE
   {
     return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
   }
-  NS_IMETHOD PrivateNoteIntentionalCrash();
+  NS_IMETHOD PrivateNoteIntentionalCrash() MOZ_OVERRIDE;
   NS_IMETHOD Btoa(const nsAString& aBinaryData,
-                  nsAString& aAsciiBase64String);
+                  nsAString& aAsciiBase64String) MOZ_OVERRIDE;
   NS_IMETHOD Atob(const nsAString& aAsciiString,
-                  nsAString& aBinaryData);
+                  nsAString& aBinaryData) MOZ_OVERRIDE;
 
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               bool aUseCapture)
   {
     // By default add listeners only for trusted events!
     return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
                                                     aUseCapture, false, 2);
   }
   using nsDOMEventTargetHelper::AddEventListener;
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               bool aUseCapture, bool aWantsUntrusted,
-                              uint8_t optional_argc)
+                              uint8_t optional_argc) MOZ_OVERRIDE
   {
     return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
                                                     aUseCapture,
                                                     aWantsUntrusted,
                                                     optional_argc);
   }
 
-  virtual JSContext* GetJSContextForEventHandlers();
-  virtual nsIPrincipal* GetPrincipal();
+  virtual JSContext* GetJSContextForEventHandlers() MOZ_OVERRIDE;
+  virtual nsIPrincipal* GetPrincipal() MOZ_OVERRIDE;
 
   nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
   TabChild* mTabChild;
 };
 
 class ContentListener MOZ_FINAL : public nsIDOMEventListener
 {
 public:
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -207,17 +207,17 @@ class GetUserMediaNotificationEvent: pub
     : mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback),
       mStatus(aStatus) {}
     virtual ~GetUserMediaNotificationEvent()
     {
 
     }
 
     NS_IMETHOD
-    Run()
+    Run() MOZ_OVERRIDE
     {
       NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
       // Make sure mStream is cleared and our reference to the DOMMediaStream
       // is dropped on the main thread, no matter what happens in this method.
       // Otherwise this object might be destroyed off the main thread,
       // releasing DOMMediaStream off the main thread, which is not allowed.
       nsRefPtr<DOMMediaStream> stream = mStream.forget();
 
@@ -286,17 +286,17 @@ public:
     {}
 
   ~MediaOperationRunnable()
   {
     // MediaStreams can be released on any thread.
   }
 
   NS_IMETHOD
-  Run()
+  Run() MOZ_OVERRIDE
   {
     SourceMediaStream *source = mListener->GetSourceStream();
     // No locking between these is required as all the callbacks for the
     // same MediaStream will occur on the same thread.
     if (!source) // means the stream was never Activated()
       return NS_OK;
 
     switch (mType) {
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -2,16 +2,17 @@
 // vim:set ts=2 sts=2 sw=2 et cin:
 /* 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/. */
 
 #ifndef nsPluginInstanceOwner_h_
 #define nsPluginInstanceOwner_h_
 
+#include "mozilla/Attributes.h"
 #include "npapi.h"
 #include "nsCOMPtr.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsIPluginTagInfo.h"
 #include "nsIPrivacyTransitionObserver.h"
 #include "nsIDOMEventListener.h"
 #include "nsPluginHost.h"
 #include "nsPluginNativeWindow.h"
@@ -55,29 +56,29 @@ public:
   virtual ~nsPluginInstanceOwner();
   
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGININSTANCEOWNER
   NS_DECL_NSIPRIVACYTRANSITIONOBSERVER
   
   NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
                     nsIInputStream *aPostStream, 
-                    void *aHeadersData, uint32_t aHeadersDataLen);
+                    void *aHeadersData, uint32_t aHeadersDataLen) MOZ_OVERRIDE;
   
-  NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
+  NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg) MOZ_OVERRIDE;
   
-  NPError    ShowNativeContextMenu(NPMenu* menu, void* event);
+  NPError    ShowNativeContextMenu(NPMenu* menu, void* event) MOZ_OVERRIDE;
   
   NPBool     ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
-                          double *destX, double *destY, NPCoordinateSpace destSpace);
+                          double *destX, double *destY, NPCoordinateSpace destSpace) MOZ_OVERRIDE;
   
   virtual NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
-                                   void *initData, NPAsyncSurface *surface);
-  virtual NPError FinalizeAsyncSurface(NPAsyncSurface *surface);
-  virtual void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed);
+                                   void *initData, NPAsyncSurface *surface) MOZ_OVERRIDE;
+  virtual NPError FinalizeAsyncSurface(NPAsyncSurface *surface) MOZ_OVERRIDE;
+  virtual void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) MOZ_OVERRIDE;
 
   //nsIPluginTagInfo interface
   NS_DECL_NSIPLUGINTAGINFO
   
   // nsIDOMEventListener interfaces 
   NS_DECL_NSIDOMEVENTLISTENER
   
   nsresult ProcessMouseDown(nsIDOMEvent* aKeyEvent);
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef nsPluginTags_h_
 #define nsPluginTags_h_
 
+#include "mozilla/Attributes.h"
 #include "nscore.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsIPluginTag.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsITimer.h"
 #include "nsIDOMMimeType.h"
@@ -105,36 +106,36 @@ public:
     CopyUTF8toUTF16(aTag->mMimeDescriptions[aMimeTypeIndex], mDescription);
     CopyUTF8toUTF16(aTag->mExtensions[aMimeTypeIndex], mSuffixes);
     CopyUTF8toUTF16(aTag->mMimeTypes[aMimeTypeIndex], mType);
   }
 
   virtual ~DOMMimeTypeImpl() {
   }
 
-  NS_METHOD GetDescription(nsAString& aDescription)
+  NS_METHOD GetDescription(nsAString& aDescription) MOZ_OVERRIDE
   {
     aDescription.Assign(mDescription);
     return NS_OK;
   }
 
-  NS_METHOD GetEnabledPlugin(nsIDOMPlugin** aEnabledPlugin)
+  NS_METHOD GetEnabledPlugin(nsIDOMPlugin** aEnabledPlugin) MOZ_OVERRIDE
   {
     // this has to be implemented by the DOM version.
     *aEnabledPlugin = nullptr;
     return NS_OK;
   }
 
-  NS_METHOD GetSuffixes(nsAString& aSuffixes)
+  NS_METHOD GetSuffixes(nsAString& aSuffixes) MOZ_OVERRIDE
   {
     aSuffixes.Assign(mSuffixes);
     return NS_OK;
   }
 
-  NS_METHOD GetType(nsAString& aType)
+  NS_METHOD GetType(nsAString& aType) MOZ_OVERRIDE
   {
     aType.Assign(mType);
     return NS_OK;
   }
 private:
   nsString mDescription;
   nsString mSuffixes;
   nsString mType;
--- a/dom/plugins/ipc/PluginProcessParent.h
+++ b/dom/plugins/ipc/PluginProcessParent.h
@@ -2,16 +2,17 @@
  * vim: sw=4 ts=4 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/. */
 
 #ifndef dom_plugins_PluginProcessParent_h
 #define dom_plugins_PluginProcessParent_h 1
 
+#include "mozilla/Attributes.h"
 #include "base/basictypes.h"
 
 #include "base/file_path.h"
 #include "base/scoped_ptr.h"
 #include "base/thread.h"
 #include "base/waitable_event.h"
 #include "chrome/common/child_process_host.h"
 
@@ -30,17 +31,17 @@ public:
     /**
      * Synchronously launch the plugin process. If the process fails to launch
      * after timeoutMs, this method will return false.
      */
     bool Launch(int32_t timeoutMs);
 
     void Delete();
 
-    virtual bool CanShutdown()
+    virtual bool CanShutdown() MOZ_OVERRIDE
     {
         return true;
     }
 
     const std::string& GetPluginFilePath() { return mPluginFilePath; }
 
     using mozilla::ipc::GeckoChildProcessHost::GetShutDownEvent;
     using mozilla::ipc::GeckoChildProcessHost::GetChannel;
--- a/dom/quota/Client.h
+++ b/dom/quota/Client.h
@@ -63,23 +63,31 @@ public:
     }
     else {
       return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
   }
 
+  // Methods which are called on the IO thred.
   virtual nsresult
   InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable) = 0;
 
   virtual nsresult
   GetUsageForOrigin(const nsACString& aOrigin,
                     UsageRunnable* aUsageRunnable) = 0;
 
+  virtual void
+  OnOriginClearCompleted(const nsACString& aPattern) = 0;
+
+  virtual void
+  ReleaseIOThreadObjects() = 0;
+
+  // Methods which are called on the main thred.
   virtual bool
   IsFileServiceUtilized() = 0;
 
   virtual bool
   IsTransactionServiceActivated() = 0;
 
   virtual void
   WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
@@ -87,24 +95,18 @@ public:
 
   virtual void
   AbortTransactionsForStorage(nsIOfflineStorage* aStorage) = 0;
 
   virtual bool
   HasTransactionsForStorage(nsIOfflineStorage* aStorage) = 0;
 
   virtual void
-  OnOriginClearCompleted(const nsACString& aPattern) = 0;
-
-  virtual void
   ShutdownTransactionService() = 0;
 
-  virtual void
-  OnShutdownCompleted() = 0;
-
 protected:
   virtual ~Client()
   { }
 };
 
 END_QUOTA_NAMESPACE
 
 #endif // mozilla_dom_quota_client_h__
--- a/dom/quota/QuotaCommon.h
+++ b/dom/quota/QuotaCommon.h
@@ -15,9 +15,22 @@
 
 #define BEGIN_QUOTA_NAMESPACE \
   namespace mozilla { namespace dom { namespace quota {
 #define END_QUOTA_NAMESPACE \
   } /* namespace quota */ } /* namespace dom */ } /* namespace mozilla */
 #define USING_QUOTA_NAMESPACE \
   using namespace mozilla::dom::quota;
 
+BEGIN_QUOTA_NAMESPACE
+
+#ifdef DEBUG
+void
+AssertIsOnIOThread();
+#else
+inline void
+AssertIsOnIOThread()
+{ }
+#endif
+
+END_QUOTA_NAMESPACE
+
 #endif // mozilla_dom_quota_quotacommon_h__
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -235,16 +235,30 @@ public:
   nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIUsageCallback> mCallback;
   uint32_t mAppId;
   OriginOrPatternString mOrigin;
   CallbackState mCallbackState;
   bool mInMozBrowserOnly;
 };
 
+#ifdef DEBUG
+void
+AssertIsOnIOThread()
+{
+  QuotaManager* quotaManager = QuotaManager::Get();
+  NS_ASSERTION(quotaManager, "Must have a manager here!");
+
+  bool correctThread;
+  NS_ASSERTION(NS_SUCCEEDED(quotaManager->IOThread()->
+                            IsOnCurrentThread(&correctThread)) && correctThread,
+               "Running on the wrong thread!");
+}
+#endif
+
 END_QUOTA_NAMESPACE
 
 namespace {
 
 QuotaManager* gInstance = nullptr;
 int32_t gShutdown = 0;
 
 int32_t gStorageQuotaMB = DEFAULT_QUOTA_MB;
@@ -821,24 +835,17 @@ QuotaManager::GetDirectoryForOrigin(cons
   return NS_OK;
 }
 
 nsresult
 QuotaManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
                                         bool aTrackQuota,
                                         nsIFile** aDirectory)
 {
-#ifdef DEBUG
-  {
-    bool correctThread;
-    NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) &&
-                 correctThread,
-                 "Running on the wrong thread!");
-  }
-#endif
+  AssertIsOnIOThread();
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = GetDirectoryForOrigin(aOrigin, getter_AddRefs(directory));
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool exists;
   rv = directory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -943,32 +950,30 @@ QuotaManager::EnsureOriginIsInitialized(
 
   mInitializedOrigins.AppendElement(aOrigin);
 
   NS_ADDREF(*aDirectory = directory);
   return NS_OK;
 }
 
 void
-QuotaManager::UninitializeOriginsByPattern(const nsACString& aPattern)
+QuotaManager::OriginClearCompleted(const nsACString& aPattern)
 {
-#ifdef DEBUG
-  {
-    bool correctThread;
-    NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) &&
-                 correctThread,
-                 "Running on the wrong thread!");
-  }
-#endif
-
-  for (int32_t i = mInitializedOrigins.Length() - 1; i >= 0; i--) {
+  AssertIsOnIOThread();
+
+  int32_t i;
+  for (i = mInitializedOrigins.Length() - 1; i >= 0; i--) {
     if (PatternMatchesOrigin(aPattern, mInitializedOrigins[i])) {
       mInitializedOrigins.RemoveElementAt(i);
     }
   }
+
+  for (i = 0; i < Client::TYPE_MAX; i++) {
+    mClients[i]->OnOriginClearCompleted(aPattern);
+  }
 }
 
 already_AddRefed<mozilla::dom::quota::Client>
 QuotaManager::GetClient(Client::Type aClientType)
 {
   nsRefPtr<Client> client = mClients.SafeElementAt(aClientType);
   return client.forget();
 }
@@ -1223,16 +1228,27 @@ QuotaManager::Observe(nsISupports* aSubj
             if (!NS_ProcessNextEvent(thread)) {
               NS_ERROR("Failed to process next event!");
               break;
             }
           }
         }
       }
 
+      // Give clients a chance to cleanup IO thread only objects.
+      nsCOMPtr<nsIRunnable> runnable =
+        NS_NewRunnableMethod(this, &QuotaManager::ReleaseIOThreadObjects);
+      if (!runnable) {
+        NS_WARNING("Failed to create runnable!");
+      }
+
+      if (NS_FAILED(mIOThread->Dispatch(runnable, NS_DISPATCH_NORMAL))) {
+        NS_WARNING("Failed to dispatch runnable!");
+      }
+
       // Make sure to join with our IO thread.
       if (NS_FAILED(mIOThread->Shutdown())) {
         NS_WARNING("Failed to shutdown IO thread!");
       }
 
       // Kick off the shutdown timer.
       if (NS_FAILED(mShutdownTimer->Init(this, DEFAULT_SHUTDOWN_TIMER_MS,
                                          nsITimer::TYPE_ONE_SHOT))) {
@@ -1246,20 +1262,16 @@ QuotaManager::Observe(nsISupports* aSubj
       }
 
       // Cancel the timer regardless of whether it actually fired.
       if (NS_FAILED(mShutdownTimer->Cancel())) {
         NS_WARNING("Failed to cancel shutdown timer!");
       }
     }
 
-    for (uint32_t index = 0; index < Client::TYPE_MAX; index++) {
-      mClients[index]->OnShutdownCompleted();
-    }
-
     return NS_OK;
   }
 
   if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) {
     NS_ASSERTION(IsMainProcess(), "Should only happen in the main process!");
 
     NS_WARNING("Some storage operations are taking longer than expected "
                "during shutdown and will be aborted!");
@@ -1815,17 +1827,17 @@ OriginClearRunnable::InvalidateOpenedSto
   for (uint32_t index = 0; index < storages.Length(); index++) {
     storages[index]->Invalidate();
   }
 }
 
 void
 OriginClearRunnable::DeleteFiles(QuotaManager* aQuotaManager)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+  AssertIsOnIOThread();
   NS_ASSERTION(aQuotaManager, "Don't pass me null!");
 
   nsresult rv;
 
   nsCOMPtr<nsIFile> directory =
     do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS_VOID(rv);
 
@@ -1873,17 +1885,17 @@ OriginClearRunnable::DeleteFiles(QuotaMa
       // This should never fail if we've closed all storage connections
       // correctly...
       NS_ERROR("Failed to remove directory!");
     }
   }
 
   aQuotaManager->RemoveQuotaForPattern(mOriginOrPattern);
 
-  aQuotaManager->UninitializeOriginsByPattern(mOriginOrPattern);
+  aQuotaManager->OriginClearCompleted(mOriginOrPattern);
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(OriginClearRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 OriginClearRunnable::Run()
 {
   PROFILER_LABEL("Quota", "OriginClearRunnable::Run");
@@ -1908,17 +1920,17 @@ OriginClearRunnable::Run()
         quotaManager->AcquireExclusiveAccess(mOriginOrPattern, this,
                                              InvalidateOpenedStorages, nullptr);
       NS_ENSURE_SUCCESS(rv, rv);
 
       return NS_OK;
     }
 
     case IO: {
-      NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+      AssertIsOnIOThread();
 
       AdvanceState();
 
       DeleteFiles(quotaManager);
 
       // Now dispatch back to the main thread.
       if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
         NS_WARNING("Failed to dispatch to main thread!");
@@ -1926,20 +1938,16 @@ OriginClearRunnable::Run()
       }
 
       return NS_OK;
     }
 
     case Complete: {
       NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-      for (uint32_t index = 0; index < Client::TYPE_MAX; index++) {
-        quotaManager->mClients[index]->OnOriginClearCompleted(mOriginOrPattern);
-      }
-
       // Tell the QuotaManager that we're done.
       quotaManager->AllowNextSynchronizedOp(mOriginOrPattern, nullptr);
 
       return NS_OK;
     }
 
     default:
       NS_ERROR("Unknown state value!");
@@ -2004,17 +2012,17 @@ AsyncUsageRunnable::RunInternal()
       if (NS_FAILED(rv)) {
         NS_WARNING("Failed to dispatch to the IO thread!");
       }
 
       return NS_OK;
     }
 
     case IO: {
-      NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
+      AssertIsOnIOThread();
 
       AdvanceState();
 
       // Get the directory that contains all the storage files we care about.
       nsCOMPtr<nsIFile> directory;
       rv = quotaManager->GetDirectoryForOrigin(mOrigin,
                                                getter_AddRefs(directory));
       NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -191,17 +191,17 @@ public:
                         nsIFile** aDirectory) const;
 
   nsresult
   EnsureOriginIsInitialized(const nsACString& aOrigin,
                             bool aTrackQuota,
                             nsIFile** aDirectory);
 
   void
-  UninitializeOriginsByPattern(const nsACString& aPattern);
+  OriginClearCompleted(const nsACString& aPattern);
 
   nsIThread*
   IOThread()
   {
     NS_ASSERTION(mIOThread, "This should never be null!");
     return mIOThread;
   }
 
@@ -288,16 +288,26 @@ private:
                      nsISupports* aId);
 
   nsresult
   ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly);
 
   nsresult
   MaybeUpgradeOriginDirectory(nsIFile* aDirectory);
 
+  void
+  ReleaseIOThreadObjects()
+  {
+    AssertIsOnIOThread();
+
+    for (uint32_t index = 0; index < Client::TYPE_MAX; index++) {
+      mClients[index]->ReleaseIOThreadObjects();
+    }
+  }
+
   static void
   GetOriginPatternString(uint32_t aAppId,
                          MozBrowserPatternFlag aBrowserFlag,
                          const nsACString& aOrigin,
                          nsAutoCString& _retval);
 
   // TLS storage index for the current thread's window.
   unsigned int mCurrentWindowIndex;
--- a/dom/src/events/nsJSEventListener.h
+++ b/dom/src/events/nsJSEventListener.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef nsJSEventListener_h__
 #define nsJSEventListener_h__
 
+#include "mozilla/Attributes.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIJSEventListener.h"
 #include "nsIDOMEventListener.h"
 #include "jsapi.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 #include "nsIScriptContext.h"
 #include "nsCycleCollectionParticipant.h"
@@ -27,17 +28,17 @@ public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMEventListener interface
   NS_DECL_NSIDOMEVENTLISTENER
 
   // nsIJSEventListener
 
-  virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+  virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE
   {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsJSEventListener)
 
 protected:
   virtual void UpdateScopeObject(JS::Handle<JSObject*> aScopeObject);
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -78,18 +78,18 @@ class nsGeolocationRequest
   bool WantsHighAccuracy() {return mOptions && mOptions->enableHighAccuracy;}
   bool IsActive() {return !mCleared;}
   bool Allowed() {return mAllowed;}
   void SetTimeoutTimer();
   nsIPrincipal* GetPrincipal();
 
   ~nsGeolocationRequest();
 
-  bool Recv__delete__(const bool& allow);
-  void IPDLRelease() { Release(); }
+  virtual bool Recv__delete__(const bool& allow) MOZ_OVERRIDE;
+  virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
 
   int32_t WatchId() { return mWatchId; }
  private:
 
   void NotifyError(int16_t errorCode);
   bool mAllowed;
   bool mCleared;
   bool mIsWatchPositionRequest;
--- a/dom/src/jsurl/nsJSProtocolHandler.h
+++ b/dom/src/jsurl/nsJSProtocolHandler.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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/. */
 
 #ifndef nsJSProtocolHandler_h___
 #define nsJSProtocolHandler_h___
 
+#include "mozilla/Attributes.h"
 #include "nsIProtocolHandler.h"
 #include "nsITextToSubURI.h"
 #include "nsIURI.h"
 #include "nsIMutable.h"
 #include "nsISerializable.h"
 #include "nsIClassInfo.h"
 #include "nsSimpleURI.h"
 
@@ -73,28 +74,28 @@ public:
     nsIURI* GetBaseURI() const
     {
         return mBaseURI;
     }
 
     NS_DECL_ISUPPORTS_INHERITED
 
     // nsIURI overrides
-    virtual nsSimpleURI* StartClone(RefHandlingEnum refHandlingMode);
+    virtual nsSimpleURI* StartClone(RefHandlingEnum refHandlingMode) MOZ_OVERRIDE;
 
     // nsISerializable overrides
-    NS_IMETHOD Read(nsIObjectInputStream* aStream);
-    NS_IMETHOD Write(nsIObjectOutputStream* aStream);
+    NS_IMETHOD Read(nsIObjectInputStream* aStream) MOZ_OVERRIDE;
+    NS_IMETHOD Write(nsIObjectOutputStream* aStream) MOZ_OVERRIDE;
 
     // Override the nsIClassInfo method GetClassIDNoAlloc to make sure our
     // nsISerializable impl works right.
-    NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc);
+    NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) MOZ_OVERRIDE;
     //NS_IMETHOD QueryInterface( const nsIID& aIID, void** aInstancePtr );
 
 protected:
     virtual nsresult EqualsInternal(nsIURI* other,
                                     RefHandlingEnum refHandlingMode,
-                                    bool* result);
+                                    bool* result) MOZ_OVERRIDE;
 private:
     nsCOMPtr<nsIURI> mBaseURI;
 };
 
 #endif /* nsJSProtocolHandler_h___ */
--- a/dom/src/notification/DesktopNotification.h
+++ b/dom/src/notification/DesktopNotification.h
@@ -151,39 +151,39 @@ class DesktopNotificationRequest : publi
 {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
   DesktopNotificationRequest(DesktopNotification* notification)
     : mDesktopNotification(notification) {}
 
-  NS_IMETHOD Run()
+  NS_IMETHOD Run() MOZ_OVERRIDE
   {
     nsCOMPtr<nsIContentPermissionPrompt> prompt =
       do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
     if (prompt) {
       prompt->Prompt(this);
     }
     return NS_OK;
   }
 
   ~DesktopNotificationRequest()
   {
   }
 
- bool Recv__delete__(const bool& allow)
+ virtual bool Recv__delete__(const bool& allow) MOZ_OVERRIDE
  {
    if (allow)
      (void) Allow();
    else
      (void) Cancel();
    return true;
  }
- void IPDLRelease() { Release(); }
+ virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
 
   nsRefPtr<DesktopNotification> mDesktopNotification;
 };
 
 class AlertServiceObserver: public nsIObserver
 {
  public:
   NS_DECL_ISUPPORTS
--- a/dom/src/storage/DOMStorage.h
+++ b/dom/src/storage/DOMStorage.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #ifndef nsDOMStorage_h___
 #define nsDOMStorage_h___
 
+#include "mozilla/Attributes.h"
 #include "nsIDOMStorage.h"
 #include "nsPIDOMStorage.h"
 #include "nsWeakReference.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -20,25 +21,25 @@ class DOMStorageCache;
 class DOMStorage MOZ_FINAL : public nsIDOMStorage
                            , public nsPIDOMStorage
                            , public nsSupportsWeakReference
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMSTORAGE
 
   // nsPIDOMStorage
-  virtual StorageType GetType() const;
-  virtual DOMStorageManager* GetManager() const { return mManager; }
-  virtual const DOMStorageCache* GetCache() const { return mCache; }
+  virtual StorageType GetType() const MOZ_OVERRIDE;
+  virtual DOMStorageManager* GetManager() const MOZ_OVERRIDE { return mManager; }
+  virtual const DOMStorageCache* GetCache() const MOZ_OVERRIDE { return mCache; }
 
-  virtual nsTArray<nsString>* GetKeys();
-  virtual nsIPrincipal* GetPrincipal();
-  virtual bool PrincipalEquals(nsIPrincipal* aPrincipal);
-  virtual bool CanAccess(nsIPrincipal* aPrincipal);
-  virtual bool IsPrivate() { return mIsPrivate; }
+  virtual nsTArray<nsString>* GetKeys() MOZ_OVERRIDE;
+  virtual nsIPrincipal* GetPrincipal() MOZ_OVERRIDE;
+  virtual bool PrincipalEquals(nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
+  virtual bool CanAccess(nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
+  virtual bool IsPrivate() MOZ_OVERRIDE { return mIsPrivate; }
 
   DOMStorage(DOMStorageManager* aManager,
              DOMStorageCache* aCache,
              const nsAString& aDocumentURI,
              nsIPrincipal* aPrincipal,
              bool aIsPrivate);
   ~DOMStorage();
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -121,16 +121,17 @@ var interfaceNamesInGlobalScope =
     "EventListenerInfo",
     "EventSource",
     "EventTarget",
     "File",
     "FileHandle",
     "FileList",
     "FileReader",
     "FileRequest",
+    "FocusEvent",
     "FontFace",
     "FontFaceList",
     "FormData",
     "Gamepad",
     "GamepadAxisMoveEvent",
     "GamepadButtonEvent",
     "GamepadEvent",
     "GeoGeolocation",
new file mode 100644
--- /dev/null
+++ b/dom/webidl/FocusEvent.webidl
@@ -0,0 +1,21 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * For more information on this interface please see
+ * http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+[Constructor(DOMString typeArg, optional FocusEventInit focusEventInitDict)]
+interface FocusEvent : UIEvent {
+  // Introduced in DOM Level 3:
+  readonly attribute EventTarget?   relatedTarget;
+};
+
+dictionary FocusEventInit : UIEventInit {
+    EventTarget? relatedTarget = null;
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -77,16 +77,17 @@ webidl_files = \
   EventSource.webidl \
   EventTarget.webidl \
   File.webidl \
   FileHandle.webidl \
   FileList.webidl \
   FileReader.webidl \
   FileReaderSync.webidl \
   FileRequest.webidl \
+  FocusEvent.webidl \
   FormData.webidl \
   Function.webidl \
   GainNode.webidl \
   Geolocation.webidl \
   HTMLAnchorElement.webidl \
   HTMLAppletElement.webidl \
   HTMLAreaElement.webidl \
   HTMLAudioElement.webidl \
--- a/dom/workers/FileReaderSync.h
+++ b/dom/workers/FileReaderSync.h
@@ -48,14 +48,14 @@ public:
                           ErrorResult& aRv);
   void ReadAsText(JS::Handle<JSObject*> aBlob,
                   const Optional<nsAString>& aEncoding,
                   nsAString& aResult, ErrorResult& aRv);
   void ReadAsDataURL(JS::Handle<JSObject*> aBlob, nsAString& aResult,
                      ErrorResult& aRv);
 
   // From nsICharsetDetectionObserver
-  NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf);
+  NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf) MOZ_OVERRIDE;
 };
 
 END_WORKERS_NAMESPACE
 
 #endif // mozilla_dom_workers_filereadersync_h__
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1,16 +1,17 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* 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/. */
 
 #ifndef mozilla_dom_workers_workerprivate_h__
 #define mozilla_dom_workers_workerprivate_h__
 
+#include "mozilla/Attributes.h"
 #include "Workers.h"
 
 #include "nsIContentSecurityPolicy.h"
 #include "nsIRunnable.h"
 #include "nsIThread.h"
 #include "nsIThreadInternal.h"
 #include "nsPIDOMWindow.h"
 
@@ -128,17 +129,17 @@ protected:
                    aClearingBehavior),
     mSyncQueueKey(aSyncQueueKey), mBypassSyncQueue(aBypassSyncQueue)
   { }
 
   virtual ~WorkerSyncRunnable()
   { }
 
   virtual bool
-  DispatchInternal();
+  DispatchInternal() MOZ_OVERRIDE;
 };
 
 class MainThreadSyncRunnable : public WorkerSyncRunnable
 {
 public:
   MainThreadSyncRunnable(WorkerPrivate* aWorkerPrivate,
                          ClearingBehavior aClearingBehavior,
                          uint32_t aSyncQueueKey,
@@ -171,17 +172,17 @@ protected:
                         BusyBehavior aBusyBehavior)
   : WorkerRunnable(aWorkerPrivate, aTarget, aBusyBehavior, SkipWhenClearing)
   { }
 
   virtual ~WorkerControlRunnable()
   { }
 
   virtual bool
-  DispatchInternal();
+  DispatchInternal() MOZ_OVERRIDE;
 };
 
 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
 // object. It exists to avoid changing a lot of code to use Mutex* instead of
 // Mutex&.
 class SharedMutex
 {
   typedef mozilla::Mutex Mutex;
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -5,16 +5,20 @@
 
 #include "GLScreenBuffer.h"
 
 #include <cstring>
 #include "gfxImageSurface.h"
 #include "GLContext.h"
 #include "SharedSurfaceGL.h"
 #include "SurfaceStream.h"
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#include "nsXULAppAPI.h"
+#endif
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gl {
 
 GLScreenBuffer*
 GLScreenBuffer::Create(GLContext* gl,
@@ -22,17 +26,30 @@ GLScreenBuffer::Create(GLContext* gl,
                      const SurfaceCaps& caps)
 {
     if (caps.antialias &&
         !gl->SupportsFramebufferMultisample())
     {
         return nullptr;
     }
 
-    SurfaceFactory_GL* factory = new SurfaceFactory_Basic(gl, caps);
+    SurfaceFactory_GL* factory = nullptr;
+
+#ifdef MOZ_WIDGET_GONK
+    /* On B2G, we want a Gralloc factory, and we want one right at the start */
+    if (!factory &&
+        XRE_GetProcessType() != GeckoProcessType_Default)
+    {
+        factory = new SurfaceFactory_Gralloc(gl, caps);
+    }
+#endif
+
+    if (!factory)
+        factory = new SurfaceFactory_Basic(gl, caps);
+
     SurfaceStream* stream = SurfaceStream::CreateForType(
         SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
                                           caps.preserve),
         nullptr);
 
     return new GLScreenBuffer(gl, caps, factory, stream);
 }
 
--- a/gfx/gl/Makefile.in
+++ b/gfx/gl/Makefile.in
@@ -74,12 +74,14 @@ CMMSRCS += GLContextProvider$(GL_PROVIDE
 endif
 
 ifdef MOZ_ANDROID_OMTC
 DEFINES += -DMOZ_ANDROID_OMTC
 endif
 
 include $(topsrcdir)/config/rules.mk
 
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
 DEFINES := $(filter-out -DUNICODE,$(DEFINES))
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
 CFLAGS   += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
new file mode 100644
--- /dev/null
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -0,0 +1,167 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Preferences.h"
+
+#include "SharedSurfaceGralloc.h"
+
+#include "GLContext.h"
+#include "SharedSurfaceGL.h"
+#include "SurfaceFactory.h"
+#include "GLLibraryEGL.h"
+#include "mozilla/layers/ShadowLayers.h"
+
+#include "ui/GraphicBuffer.h"
+#include "../layers/ipc/ShadowLayers.h"
+
+#define DEBUG_GRALLOC
+#ifdef DEBUG_GRALLOC
+#define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0)
+#else
+#define DEBUG_PRINT(...) do { } while (0)
+#endif
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace gl;
+using namespace layers;
+using namespace android;
+
+static bool sForceReadPixelsToFence = false;
+
+
+SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
+                                               const SurfaceCaps& caps,
+                                               layers::ISurfaceAllocator* allocator)
+    : SurfaceFactory_GL(prodGL, SharedSurfaceType::Gralloc, caps)
+{
+    if (caps.surfaceAllocator) {
+        allocator = caps.surfaceAllocator;
+    }
+
+    MOZ_ASSERT(allocator);
+
+    mAllocator = allocator;
+}
+
+SharedSurface_Gralloc*
+SharedSurface_Gralloc::Create(GLContext* prodGL,
+                              const GLFormats& formats,
+                              const gfxIntSize& size,
+                              bool hasAlpha,
+                              ISurfaceAllocator* allocator)
+{
+    static bool runOnce = true;
+    if (runOnce) {
+        sForceReadPixelsToFence = false;
+        mozilla::Preferences::AddBoolVarCache(&sForceReadPixelsToFence,
+                                              "gfx.gralloc.fence-with-readpixels");
+        runOnce = false;
+    }
+
+    GLLibraryEGL* egl = prodGL->GetLibraryEGL();
+    MOZ_ASSERT(egl);
+
+    DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
+
+    if (!HasExtensions(egl, prodGL))
+        return nullptr;
+
+    SurfaceDescriptor baseDesc;
+    SurfaceDescriptorGralloc desc;
+
+    gfxASurface::gfxContentType type = hasAlpha ? gfxASurface::CONTENT_COLOR_ALPHA
+                                                : gfxASurface::CONTENT_COLOR;
+    if (!allocator->AllocSurfaceDescriptorWithCaps(size, type, USING_GL_RENDERING_ONLY, &baseDesc))
+        return false;
+
+    if (baseDesc.type() != SurfaceDescriptor::TSurfaceDescriptorGralloc) {
+        allocator->DestroySharedSurface(&baseDesc);
+        return false;
+    }
+
+    desc = baseDesc.get_SurfaceDescriptorGralloc();
+
+    sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(desc);
+
+    EGLDisplay display = egl->Display();
+    EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
+    EGLint attrs[] = {
+        LOCAL_EGL_NONE, LOCAL_EGL_NONE
+    };
+    EGLImage image = egl->fCreateImage(display,
+                                       EGL_NO_CONTEXT,
+                                       LOCAL_EGL_NATIVE_BUFFER_ANDROID,
+                                       clientBuffer, attrs);
+    if (!image) {
+        allocator->DestroySharedSurface(&baseDesc);
+        return nullptr;
+    }
+
+    prodGL->MakeCurrent();
+    GLuint prodTex = 0;
+    prodGL->fGenTextures(1, &prodTex);
+    ScopedBindTexture autoTex(prodGL, prodTex);
+    prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
+
+    egl->fDestroyImage(display, image);
+
+    SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, desc, prodTex);
+
+    DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p, GraphicBuffer %p.\n", surf, buffer.get());
+
+    return surf;
+}
+
+
+bool
+SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
+{
+    return egl->HasKHRImageBase() &&
+           gl->IsExtensionSupported(GLContext::OES_EGL_image);
+}
+
+SharedSurface_Gralloc::~SharedSurface_Gralloc()
+{
+
+    DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
+
+    mGL->MakeCurrent();
+    mGL->fDeleteTextures(1, (GLuint*)&mProdTex);
+
+    SurfaceDescriptor desc(mDesc);
+    mAllocator->DestroySharedSurface(&desc);
+}
+
+void
+SharedSurface_Gralloc::Fence()
+{
+    // We should be able to rely on genlock write locks/read locks.
+    // But they're broken on some configs, and even a glFinish doesn't
+    // work.  glReadPixels seems to, though.
+    if (sForceReadPixelsToFence) {
+        mGL->MakeCurrent();
+        // read a 1x1 pixel
+        unsigned char pixels[4];
+        mGL->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &pixels[0]);
+    }
+}
+
+bool
+SharedSurface_Gralloc::WaitSync()
+{
+    return true;
+}
+
+void
+SharedSurface_Gralloc::LockProdImpl()
+{
+}
+
+void
+SharedSurface_Gralloc::UnlockProdImpl()
+{
+}
+
new file mode 100644
--- /dev/null
+++ b/gfx/gl/SharedSurfaceGralloc.h
@@ -0,0 +1,111 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* 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/. */
+
+#ifndef SHARED_SURFACE_GRALLOC_H_
+#define SHARED_SURFACE_GRALLOC_H_
+
+#include "SharedSurfaceGL.h"
+#include "mozilla/layers/LayersSurfaces.h"
+
+namespace mozilla {
+namespace layers {
+class ISurfaceAllocator;
+class SurfaceDescriptorGralloc;
+}
+
+namespace gl {
+class GLContext;
+class GLLibraryEGL;
+
+class SharedSurface_Gralloc
+    : public SharedSurface_GL
+{
+public:
+    static SharedSurface_Gralloc* Create(GLContext* prodGL,
+                                         const GLFormats& formats,
+                                         const gfxIntSize& size,
+                                         bool hasAlpha,
+                                         layers::ISurfaceAllocator* allocator);
+
+    static SharedSurface_Gralloc* Cast(SharedSurface* surf) {
+        MOZ_ASSERT(surf->Type() == SharedSurfaceType::Gralloc);
+
+        return (SharedSurface_Gralloc*)surf;
+    }
+
+protected:
+    GLLibraryEGL* const mEGL;
+    layers::ISurfaceAllocator* const mAllocator;
+    // We keep the SurfaceDescriptor around, because we'll end up
+    // using it often and it's handy to do so.  The actual
+    // GraphicBuffer is kept alive by the sp<GraphicBuffer> in
+    // GrallocBufferActor; the actor will stay alive until we
+    // explicitly destroy this descriptor (and thus deallocate the
+    // actor) it in the destructor of this class.  This is okay to do
+    // on the client, but is very bad to do on the server (because on
+    // the client, the actor has no chance of going away unless the
+    // whole app died).
+    layers::SurfaceDescriptorGralloc mDesc;
+    const GLuint mProdTex;
+
+    SharedSurface_Gralloc(GLContext* prodGL,
+                          const gfxIntSize& size,
+                          bool hasAlpha,
+                          GLLibraryEGL* egl,
+                          layers::ISurfaceAllocator* allocator,
+                          layers::SurfaceDescriptorGralloc& desc,
+                          GLuint prodTex)
+        : SharedSurface_GL(SharedSurfaceType::Gralloc,
+                           AttachmentType::GLTexture,
+                           prodGL,
+                           size,
+                           hasAlpha)
+        , mEGL(egl)
+        , mAllocator(allocator)
+        , mDesc(desc)
+        , mProdTex(prodTex)
+    {}
+
+    static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
+
+public:
+    virtual ~SharedSurface_Gralloc();
+
+    virtual void Fence();
+    virtual bool WaitSync();
+
+    virtual void LockProdImpl();
+    virtual void UnlockProdImpl();
+
+    virtual GLuint Texture() const {
+        return mProdTex;
+    }
+
+    layers::SurfaceDescriptorGralloc& GetDescriptor() {
+        return mDesc;
+    }
+};
+
+class SurfaceFactory_Gralloc
+    : public SurfaceFactory_GL
+{
+protected:
+    layers::ISurfaceAllocator* mAllocator;
+
+public:
+    SurfaceFactory_Gralloc(GLContext* prodGL,
+                           const SurfaceCaps& caps,
+                           layers::ISurfaceAllocator* allocator = nullptr);
+
+    virtual SharedSurface* CreateShared(const gfxIntSize& size) {
+        bool hasAlpha = mReadCaps.alpha;
+        return SharedSurface_Gralloc::Create(mGL, mFormats, size, hasAlpha, mAllocator);
+    }
+};
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#endif /* SHARED_SURFACE_GRALLOC_H_ */
--- a/gfx/gl/SurfaceTypes.h
+++ b/gfx/gl/SurfaceTypes.h
@@ -7,29 +7,37 @@
 #define SURFACE_TYPES_H_
 
 #include "mozilla/TypedEnum.h"
 #include "mozilla/StandardInteger.h"
 
 #include <cstring>
 
 namespace mozilla {
+namespace layers {
+class ISurfaceAllocator;
+}
+
 namespace gfx {
 
 typedef uintptr_t SurfaceStreamHandle;
 
 struct SurfaceCaps
 {
     bool any;
     bool color, alpha;
     bool bpp16;
     bool depth, stencil;
     bool antialias;
     bool preserve;
 
+    // The surface allocator that we want to create this
+    // for.  May be null.
+    layers::ISurfaceAllocator* surfaceAllocator;
+
     SurfaceCaps() {
         Clear();
     }
 
     void Clear() {
         std::memset(this, 0, sizeof(SurfaceCaps));
     }
 
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -70,16 +70,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
         'SharedSurfaceANGLE.cpp',
     ]
 if CONFIG['MOZ_ENABLE_SKIA_GPU']:
     EXPORTS += ['GLContextSkia.h']
     CPP_SOURCES += [
         'GLContextSkia.cpp',
     ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+    CPP_SOURCES += ['SharedSurfaceGralloc.cpp']
+    EXPORTS += ['SharedSurfaceGralloc.h']
+
 if gl_provider == 'CGL':
     # TODO: CMMSRCS
     pass
 else:
     CPP_SOURCES += [
         'GLContextProvider%s.cpp' % gl_provider,
     ]
 
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -31,16 +31,19 @@ const TextureFlags ForceSingleTile    = 
 // Allow using 'repeat' mode for wrapping.
 const TextureFlags AllowRepeat        = 0x8;
 // The texture represents a tile which is newly created.
 const TextureFlags NewTile            = 0x10;
 // The host is responsible for tidying up any shared resources.
 const TextureFlags HostRelease        = 0x20;
 // The texture is part of a component-alpha pair
 const TextureFlags ComponentAlpha     = 0x40;
+// The shared resources are owned by client
+const TextureFlags OwnByClient        = 0x80;
+
 
 /**
  * The kind of memory held by the texture client/host pair. This will
  * determine how the texture client is drawn into and how the memory
  * is shared between client and host.
  */
 enum TextureClientType
 {
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -6,16 +6,20 @@
 #include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/TextureClient.h"
 #include "ClientCanvasLayer.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "SharedTextureImage.h"
 #include "nsXULAppAPI.h"
 #include "GLContext.h"
 #include "SurfaceStream.h"
+#include "SharedSurface.h"
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#endif
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 /* static */ TemporaryRef<CanvasClient>
 CanvasClient::CreateCanvasClient(CompositableType aCompositableHostType,
@@ -90,17 +94,41 @@ CanvasClientWebGL::Update(gfx::IntSize a
   }
 
   NS_ASSERTION(aLayer->mGLContext, "CanvasClientWebGL should only be used with GL canvases");
 
   // the content type won't be used
   mTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR);
 
   GLScreenBuffer* screen = aLayer->mGLContext->Screen();
-  SurfaceStreamHandle handle = screen->Stream()->GetShareHandle();
+  SurfaceStream* stream = screen->Stream();
+
+  bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
+  if (isCrossProcess) {
+    // swap staging -> consumer so we can send it to the compositor
+    SharedSurface* surf = stream->SwapConsumer();
+    if (!surf) {
+      printf_stderr("surf is null post-SwapConsumer!\n");
+      return;
+    }
 
-  mTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
+#ifdef MOZ_WIDGET_GONK
+    if (surf->Type() != SharedSurfaceType::Gralloc) {
+      printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
+      return;
+    }
+
+    SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
+    mTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
+#else
+    printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
+    MOZ_ASSERT(false);
+#endif
+  } else {
+    SurfaceStreamHandle handle = stream->GetShareHandle();
+    mTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
+  }
 
   aLayer->Painted();
 }
 
 }
 }
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -3,16 +3,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ClientCanvasLayer.h"
 #include "gfxPlatform.h"
 #include "SurfaceStream.h"
 #include "SharedSurfaceGL.h"
 #include "SharedSurfaceEGL.h"
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#endif
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 void
 ClientCanvasLayer::Initialize(const Data& aData)
@@ -32,17 +35,22 @@ ClientCanvasLayer::Initialize(const Data
         if (mGLContext->GetEGLContext()) {
           bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
 
           if (!isCrossProcess) {
             // [Basic/OGL Layers, OMTC] WebGL layer init.
             factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps());
           } else {
             // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
-            // Fall back to readback.
+#ifdef MOZ_WIDGET_GONK
+            factory = new SurfaceFactory_Gralloc(mGLContext, screen->Caps(), ClientManager());
+#else
+            // we could do readback here maybe
+            NS_NOTREACHED("isCrossProcess but not on native B2G!");
+#endif
           }
         } else {
           // [Basic Layers, OMTC] WebGL layer init.
           // Well, this *should* work...
           factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, screen->Caps());
         }
       }
     }
@@ -65,16 +73,25 @@ ClientCanvasLayer::RenderLayer()
     ToClientLayer(GetMaskLayer())->RenderLayer();
   }
   
   if (!mCanvasClient) {
     TextureFlags flags = 0;
     if (mNeedsYFlip) {
       flags |= NeedsYFlip;
     }
+
+    bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
+    //Append OwnByClient flag for streaming buffer under OOPC case
+    if (isCrossProcess && mGLContext) {
+      GLScreenBuffer* screen = mGLContext->Screen();
+      if (screen && screen->Stream()) {
+        flags |= OwnByClient;
+      }
+    }
     mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
                                                      ClientManager(), flags);
     if (!mCanvasClient) {
       return;
     }
     if (HasShadow()) {
       mCanvasClient->Connect();
       ClientManager()->Attach(mCanvasClient, this);
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -68,17 +68,17 @@ public:
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
   
   CompositableType GetCompositableClientType()
   {
-    if (mGLContext && XRE_GetProcessType() == GeckoProcessType_Default) {
+    if (mGLContext) {
       return BUFFER_IMAGE_BUFFERED;
     }
     return BUFFER_IMAGE_SINGLE;
   }
 
   RefPtr<CanvasClient> mCanvasClient;
 
   friend class CanvasClient2D;
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -72,20 +72,22 @@ TextureHost::TextureHost()
   , mDeAllocator(nullptr)
 {
   MOZ_COUNT_CTOR(TextureHost);
 }
 
 TextureHost::~TextureHost()
 {
   if (mBuffer) {
-    if (mDeAllocator) {
-      mDeAllocator->DestroySharedSurface(mBuffer);
-    } else {
-      MOZ_ASSERT(mBuffer->type() == SurfaceDescriptor::Tnull_t);
+    if (!(mFlags & OwnByClient)) {
+      if (mDeAllocator) {
+        mDeAllocator->DestroySharedSurface(mBuffer);
+      } else {
+        MOZ_ASSERT(mBuffer->type() == SurfaceDescriptor::Tnull_t);
+      }
     }
     delete mBuffer;
   }
   MOZ_COUNT_DTOR(TextureHost);
 }
 
 void
 TextureHost::Update(const SurfaceDescriptor& aImage,
--- a/gfx/layers/ipc/ISurfaceAllocator.h
+++ b/gfx/layers/ipc/ISurfaceAllocator.h
@@ -39,17 +39,21 @@ class PGrallocBufferChild;
 class MaybeMagicGrallocBufferHandle;
 
 enum BufferCapabilities {
   DEFAULT_BUFFER_CAPS = 0,
   /**
    * The allocated buffer must be efficiently mappable as a
    * gfxImageSurface.
    */
-  MAP_AS_IMAGE_SURFACE = 1 << 0
+  MAP_AS_IMAGE_SURFACE = 1 << 0,
+  /**
+   * The allocated buffer will be used for GL rendering only
+   */
+  USING_GL_RENDERING_ONLY = 1 << 1
 };
 
 class SurfaceDescriptor;
 
 
 ipc::SharedMemory::SharedMemoryType OptimalShmemType();
 bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface);
 bool IsSurfaceDescriptorOwned(const SurfaceDescriptor& aDescriptor);
@@ -109,18 +113,21 @@ protected:
   // this method is needed for a temporary fix, will be removed after
   // TextureClient/Host rework.
   virtual bool IsOnCompositorSide() const = 0;
   static bool PlatformDestroySharedSurface(SurfaceDescriptor* aSurface);
   virtual bool PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
                                               gfxASurface::gfxContentType aContent,
                                               uint32_t aCaps,
                                               SurfaceDescriptor* aBuffer);
+
+  // method that does the actual allocation work
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
-                                                  gfxASurface::gfxContentType aContent,
+                                                  uint32_t aFormat,
+                                                  uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle)
   {
     return nullptr;
   }
 
   ~ISurfaceAllocator() {}
 };
 
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -576,17 +576,17 @@ ImageBridgeChild::AllocSurfaceDescriptor
   if (handle.Tnull_t == handle.type()) {
     PGrallocBufferChild::Send__delete__(gc);
     return false;
   }
 
   GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
   gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
 
-  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false);
+  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false, /* swapRB */ false);
   return true;
 #else
   NS_RUNTIMEABORT("No gralloc buffers for you");
   return false;
 #endif
 }
 
 bool
@@ -743,23 +743,24 @@ ImageBridgeChild::DeallocShmem(ipc::Shme
     while (!done) {
       barrier.Wait();
     }
   }
 }
 
 PGrallocBufferChild*
 ImageBridgeChild::AllocGrallocBuffer(const gfxIntSize& aSize,
-                                     gfxASurface::gfxContentType aContent,
+                                     uint32_t aFormat,
+                                     uint32_t aUsage,
                                      MaybeMagicGrallocBufferHandle* aHandle)
 {
 #ifdef MOZ_WIDGET_GONK
   return SendPGrallocBufferConstructor(aSize,
-                                       aContent,
-                                       GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       aFormat,
+                                       aUsage,
                                        aHandle);
 #else
   NS_RUNTIMEABORT("not implemented");
   return nullptr;
 #endif
 }
 
 } // layers
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -194,17 +194,17 @@ public:
    * Part of the allocation of gralloc SurfaceDescriptor that is
    * executed on the ImageBridgeChild thread after invoking
    * AllocSurfaceDescriptorGralloc.
    *
    * Must be called from the ImageBridgeChild thread.
    */
   bool
   AllocSurfaceDescriptorGrallocNow(const gfxIntSize& aSize,
-                                   const uint32_t& aContent,
+                                   const uint32_t& aFormat,
                                    const uint32_t& aUsage,
                                    SurfaceDescriptor* aBuffer);
 
   /**
    * Deallocate a remotely allocated gralloc buffer.
    */
   bool
   DeallocSurfaceDescriptorGralloc(const SurfaceDescriptor& aBuffer);
@@ -332,17 +332,18 @@ protected:
   ImageBridgeChild();
   bool DispatchAllocShmemInternal(size_t aSize,
                                   SharedMemory::SharedMemoryType aType,
                                   Shmem* aShmem,
                                   bool aUnsafe);
 
   CompositableTransaction* mTxn;
 
+  // ISurfaceAllocator
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
-                                                  gfxASurface::gfxContentType aContent,
+                                                  uint32_t aFormat, uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
 };
 
 } // layers
 } // mozilla
 
 #endif
--- a/gfx/layers/ipc/LayerTransactionChild.cpp
+++ b/gfx/layers/ipc/LayerTransactionChild.cpp
@@ -19,18 +19,19 @@ LayerTransactionChild::Destroy()
   NS_ABORT_IF_FALSE(0 == ManagedPLayerChild().Length(),
                     "layers should have been cleaned up by now");
   PLayerTransactionChild::Send__delete__(this);
   // WARNING: |this| has gone to the great heap in the sky
 }
 
 PGrallocBufferChild*
 LayerTransactionChild::AllocPGrallocBuffer(const gfxIntSize&,
-                                       const gfxContentType&,
-                                       MaybeMagicGrallocBufferHandle*)
+                                           const uint32_t&,
+                                           const uint32_t&,
+                                           MaybeMagicGrallocBufferHandle*)
 {
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   return GrallocBufferActor::Create();
 #else
   NS_RUNTIMEABORT("No gralloc buffers for you");
   return nullptr;
 #endif
 }
--- a/gfx/layers/ipc/LayerTransactionChild.h
+++ b/gfx/layers/ipc/LayerTransactionChild.h
@@ -25,17 +25,18 @@ public:
    * It is expected (checked with an assert) that all shadow layers
    * created by this have already been destroyed and
    * Send__delete__()d by the time this method is called.
    */
   void Destroy();
 
 protected:
   virtual PGrallocBufferChild*
-  AllocPGrallocBuffer(const gfxIntSize&, const gfxContentType&,
+  AllocPGrallocBuffer(const gfxIntSize&,
+                      const uint32_t&, const uint32_t&,
                       MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
   virtual bool
   DeallocPGrallocBuffer(PGrallocBufferChild* actor) MOZ_OVERRIDE;
 
   virtual PLayerChild* AllocPLayer() MOZ_OVERRIDE;
   virtual bool DeallocPLayer(PLayerChild* actor) MOZ_OVERRIDE;
 
   virtual PCompositableChild* AllocPCompositable(const TextureInfo& aInfo) MOZ_OVERRIDE;
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -511,21 +511,22 @@ LayerTransactionParent::RecvClearCachedR
     // of resources to exactly that subtree, so we specify it here.
     mLayerManager->ClearCachedResources(mRoot);
   }
   return true;
 }
 
 PGrallocBufferParent*
 LayerTransactionParent::AllocPGrallocBuffer(const gfxIntSize& aSize,
-                                            const gfxContentType& aContent,
+                                            const uint32_t& aFormat,
+                                            const uint32_t& aUsage,
                                             MaybeMagicGrallocBufferHandle* aOutHandle)
 {
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
-  return GrallocBufferActor::Create(aSize, aContent, aOutHandle);
+  return GrallocBufferActor::Create(aSize, aFormat, aUsage, aOutHandle);
 #else
   NS_RUNTIMEABORT("No gralloc buffers for you");
   return nullptr;
 #endif
 }
 
 bool
 LayerTransactionParent::DeallocPGrallocBuffer(PGrallocBufferParent* actor)
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -77,17 +77,18 @@ protected:
 
   virtual bool RecvClearCachedResources() MOZ_OVERRIDE;
   virtual bool RecvGetOpacity(PLayerParent* aParent,
                               float* aOpacity) MOZ_OVERRIDE;
   virtual bool RecvGetTransform(PLayerParent* aParent,
                                 gfx3DMatrix* aTransform) MOZ_OVERRIDE;
 
   virtual PGrallocBufferParent*
-  AllocPGrallocBuffer(const gfxIntSize& aSize, const gfxContentType& aContent,
+  AllocPGrallocBuffer(const gfxIntSize& aSize,
+                      const uint32_t& aFormat, const uint32_t& aUsage,
                       MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
   virtual bool
   DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE;
 
   virtual PLayerParent* AllocPLayer() MOZ_OVERRIDE;
   virtual bool DeallocPLayer(PLayerParent* actor) MOZ_OVERRIDE;
 
   virtual PCompositableParent* AllocPCompositable(const TextureInfo& aInfo) MOZ_OVERRIDE;
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -57,16 +57,27 @@ struct SurfaceDescriptorGralloc {
   /**
    * We can have one source producing gralloc buffers and sharing them
    * with another source that may also produce its own gralloc buffers.
    * This happens for camera preview buffers sent to video code.  When
    * that happens, the producer can mark the buffer as "external" to
    * prevent its consumer from mistakenly freeing the buffer.
    */
   bool external;
+
+  /**
+   * This gralloc buffer will be treated as if the RB bytes are swapped.
+   * This is useful for rendering using Cairo/Thebes, because there is no
+   * BGRX Android pixel format, and so we have to do byte swapping.
+   *
+   * For example, if the GraphicBuffer has an Android pixel format of
+   * PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
+   * (for example, with GL), a BGRA shader should be used.
+   */
+  bool isRBSwapped;
 };
 
 struct SurfaceStreamDescriptor {
   SurfaceStreamHandle handle;
   bool yflip;
 };
 
 struct YCbCrImage {
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -38,18 +38,40 @@ sync protocol PLayerTransaction {
   manages PCompositable;
   manages PGrallocBuffer;
 
 parent:
   /**
    * Only the parent side has privileges to allocate the buffer.
    * Allocation may fail (pmem is a scarce resource), and if so null_t
    * is returned.
+   *
+   * |format| is an Android PixelFormat (see PixelFormat.h)
+   *
+   * commonly used PixelFormats are:
+   *   PIXEL_FORMAT_RGBA_8888
+   *   PIXEL_FORMAT_RGBX_8888
+   *   PIXEL_FORMAT_BGRA_8888
+   *
+   * Note that SurfaceDescriptorGralloc has a "isRBSwapped" boolean
+   * that can treat the R/B bytes as swapped when they are rendered
+   * to the screen, to help with matching the native pixel format
+   * of other rendering engines.
+   *
+   * |usage| is a USAGE_* mask (see GraphicBuffer.h)
+   *
+   * commonly used USAGE flags are:
+   *   USAGE_SW_READ_OFTEN | USAGE_SW_WRITE_OFTEN | USAGE_HW_TEXTURE
+   *     - used for software rendering to a buffer which the compositor
+   *       treats as a texture
+   *   USAGE_HW_RENDER | USAGE_HW_TEXTURE
+   *     - used for GL rendering to a buffer which the compositor
+   *       treats as a texture
    */
-  sync PGrallocBuffer(gfxIntSize size, gfxContentType content)
+  sync PGrallocBuffer(gfxIntSize size, uint32_t format, uint32_t usage)
     returns (MaybeMagicGrallocBufferHandle handle);
   async PLayer();
   async PCompositable(TextureInfo aTextureInfo);
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint)
     returns (EditReply[] reply);
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -141,16 +141,41 @@ PixelFormatForImageFormat(gfxASurface::g
   case gfxASurface::ImageFormatA8:
     return android::PIXEL_FORMAT_A_8;
   default:
     MOZ_NOT_REACHED("Unknown gralloc pixel format");
   }
   return gfxASurface::ImageFormatARGB32;
 }
 
+static size_t
+BytesPerPixelForPixelFormat(android::PixelFormat aFormat)
+{
+  switch (aFormat) {
+  case PIXEL_FORMAT_RGBA_8888:
+  case PIXEL_FORMAT_RGBX_8888:
+  case PIXEL_FORMAT_BGRA_8888:
+    return 4;
+  case PIXEL_FORMAT_RGB_888:
+    return 3;
+  case PIXEL_FORMAT_RGB_565:
+  case PIXEL_FORMAT_RGBA_5551:
+  case PIXEL_FORMAT_RGBA_4444:
+  case PIXEL_FORMAT_LA_88:
+    return 2;
+  case PIXEL_FORMAT_L_8:
+  case PIXEL_FORMAT_A_8:
+  case PIXEL_FORMAT_RGB_332:
+    return 1;
+  default:
+    MOZ_NOT_REACHED("Unknown gralloc pixel format");
+  }
+  return gfxASurface::ImageFormatARGB32;
+}
+
 static android::PixelFormat
 PixelFormatForContentType(gfxASurface::gfxContentType aContentType)
 {
   return PixelFormatForImageFormat(
     gfxPlatform::GetPlatform()->OptimalFormatForContent(aContentType));
 }
 
 static gfxASurface::gfxContentType
@@ -192,38 +217,42 @@ GrallocBufferActor::~GrallocBufferActor(
 {
   if (mAllocBytes > 0) {
     sCurrentAlloc -= mAllocBytes;
   }
 }
 
 /*static*/ PGrallocBufferParent*
 GrallocBufferActor::Create(const gfxIntSize& aSize,
-                           const gfxContentType& aContent,
+                           const uint32_t& aFormat,
+                           const uint32_t& aUsage,
                            MaybeMagicGrallocBufferHandle* aOutHandle)
 {
   PROFILER_LABEL("GrallocBufferActor", "Create");
   GrallocBufferActor* actor = new GrallocBufferActor();
   *aOutHandle = null_t();
-  android::PixelFormat format = PixelFormatForContentType(aContent);
-  sp<GraphicBuffer> buffer(
-    new GraphicBuffer(aSize.width, aSize.height, format,
-                      GraphicBuffer::USAGE_SW_READ_OFTEN |
-                      GraphicBuffer::USAGE_SW_WRITE_OFTEN |
-                      GraphicBuffer::USAGE_HW_TEXTURE));
+  uint32_t format = aFormat;
+  uint32_t usage = aUsage;
+
+  if (format == 0 || usage == 0) {
+    printf_stderr("GrallocBufferActor::Create -- format and usage must be non-zero");
+    return actor;
+  }
+
+  sp<GraphicBuffer> buffer(new GraphicBuffer(aSize.width, aSize.height, format, usage));
   if (buffer->initCheck() != OK)
     return actor;
 
-  size_t bpp = gfxASurface::BytePerPixelFromFormat(
-      gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent));
+  size_t bpp = BytesPerPixelForPixelFormat(format);
   actor->mAllocBytes = aSize.width * aSize.height * bpp;
   sCurrentAlloc += actor->mAllocBytes;
 
   actor->mGraphicBuffer = buffer;
   *aOutHandle = MagicGrallocBufferHandle(buffer);
+
   return actor;
 }
 
 // used only for hacky fix in gecko 23 for bug 862324
 void GrallocBufferActor::ActorDestroy(ActorDestroyReason)
 {
   if (mTextureHost) {
     mTextureHost->ForgetBuffer();
@@ -256,34 +285,16 @@ LayerManagerComposite::SupportsDirectTex
 }
 
 /*static*/ void
 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
 {
   // Nothing to be done for gralloc.
 }
 
-/*static*/ PGrallocBufferParent*
-GrallocBufferActor::Create(const gfxIntSize& aSize,
-                           const uint32_t& aFormat,
-                           const uint32_t& aUsage,
-                           MaybeMagicGrallocBufferHandle* aOutHandle)
-{
-  GrallocBufferActor* actor = new GrallocBufferActor();
-  *aOutHandle = null_t();
-  sp<GraphicBuffer> buffer(
-    new GraphicBuffer(aSize.width, aSize.height, aFormat, aUsage));
-  if (buffer->initCheck() != OK)
-    return actor;
-
-  actor->mGraphicBuffer = buffer;
-  *aOutHandle = MagicGrallocBufferHandle(buffer);
-  return actor;
-}
-
 bool
 ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
 {
   if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aSurface->type()) {
     return false;
   }
 
   // we should have either a bufferParent or bufferChild
@@ -317,20 +328,21 @@ GrallocBufferActor::InitFromHandle(const
   MOZ_ASSERT(!mGraphicBuffer.get());
   MOZ_ASSERT(aHandle.mGraphicBuffer.get());
 
   mGraphicBuffer = aHandle.mGraphicBuffer;
 }
 
 PGrallocBufferChild*
 ShadowLayerForwarder::AllocGrallocBuffer(const gfxIntSize& aSize,
-                                         gfxASurface::gfxContentType aContent,
+                                         uint32_t aFormat,
+                                         uint32_t aUsage,
                                          MaybeMagicGrallocBufferHandle* aHandle)
 {
-  return mShadowManager->SendPGrallocBufferConstructor(aSize, aContent, aHandle);
+  return mShadowManager->SendPGrallocBufferConstructor(aSize, aFormat, aUsage, aHandle);
 }
 
 bool
 ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
                                                   gfxASurface::gfxContentType aContent,
                                                   uint32_t aCaps,
                                                   SurfaceDescriptor* aBuffer)
 {
@@ -340,30 +352,56 @@ ISurfaceAllocator::PlatformAllocSurfaceD
   // upload.
   if (aSize.width < 64) {
     return false;
   }
   PROFILER_LABEL("ShadowLayerForwarder", "PlatformAllocSurfaceDescriptor");
   // Gralloc buffers are efficiently mappable as gfxImageSurface, so
   // no need to check |aCaps & MAP_AS_IMAGE_SURFACE|.
   MaybeMagicGrallocBufferHandle handle;
-  PGrallocBufferChild* gc = AllocGrallocBuffer(aSize, aContent, &handle);
+  PGrallocBufferChild* gc;
+  bool defaultRBSwap;
+
+  if (aCaps & USING_GL_RENDERING_ONLY) {
+    gc = AllocGrallocBuffer(aSize,
+                            PixelFormatForContentType(aContent),
+                            GraphicBuffer::USAGE_HW_RENDER |
+                            GraphicBuffer::USAGE_HW_TEXTURE,
+                            &handle);
+    // If you're allocating for USING_GL_RENDERING_ONLY, then we don't flag
+    // this for RB swap.
+    defaultRBSwap = false;
+  } else {
+    gc = AllocGrallocBuffer(aSize,
+                            PixelFormatForContentType(aContent),
+                            GraphicBuffer::USAGE_SW_READ_OFTEN |
+                            GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                            GraphicBuffer::USAGE_HW_TEXTURE,
+                            &handle);
+    // But if you're allocating for non-GL-only rendering, we flag for
+    // RB swap to preserve old behaviour and proper interaction with
+    // cairo.
+    defaultRBSwap = true;
+  }
+
   if (!gc) {
     NS_ERROR("GrallocBufferConstructor failed by returned null");
     return false;
   } else if (handle.Tnull_t == handle.type()) {
     NS_ERROR("GrallocBufferConstructor failed by returning handle with type Tnull_t");
     PGrallocBufferChild::Send__delete__(gc);
     return false;
   }
 
   GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
   gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
 
-  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false);
+  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize,
+                                      /* external */ false,
+                                      defaultRBSwap);
   return true;
 }
 
 //-----------------------------------------------------------------------------
 // Both processes
 
 /*static*/ sp<GraphicBuffer>
 GrallocBufferActor::GetFrom(const SurfaceDescriptorGralloc& aDescriptor)
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
@@ -67,20 +67,16 @@ class GrallocBufferActor : public PGrall
   friend class LayerManagerComposite;
   friend class ImageBridgeChild;
   typedef android::GraphicBuffer GraphicBuffer;
 
 public:
   virtual ~GrallocBufferActor();
 
   static PGrallocBufferParent*
-  Create(const gfxIntSize& aSize, const gfxContentType& aContent,
-         MaybeMagicGrallocBufferHandle* aOutHandle);
-
-  static PGrallocBufferParent*
   Create(const gfxIntSize& aSize, const uint32_t& aFormat, const uint32_t& aUsage,
          MaybeMagicGrallocBufferHandle* aOutHandle);
 
   static PGrallocBufferChild*
   Create();
 
   static android::sp<GraphicBuffer>
   GetFrom(const SurfaceDescriptorGralloc& aDescriptor);
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -24,16 +24,18 @@
 #include "RenderTrace.h"
 #include "GeckoProfiler.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/layers/ImageClient.h"
 #include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/ContentClient.h"
 #include "ISurfaceAllocator.h"
 
+#include "nsTraceRefcntImpl.h"
+
 using namespace mozilla::ipc;
 using namespace mozilla::gl;
 using namespace mozilla::dom;
 
 namespace mozilla {
 namespace layers {
 
 typedef nsTArray<SurfaceDescriptor> BufferArray;
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -383,18 +383,20 @@ public:
   OpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface);
 
 protected:
   ShadowLayerForwarder();
 
   PLayerTransactionChild* mShadowManager;
 
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
+  // from ISurfaceAllocator
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
-                                                  gfxASurface::gfxContentType aContent,
+                                                  uint32_t aFormat,
+                                                  uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
 #endif
 
 private:
   /**
    * Try to query the content type efficiently, but at worst map the
    * surface and return it in *aSurface.
    */
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -635,23 +635,26 @@ TiledTextureHostOGL::Lock()
   mGL->MakeCurrent();
   mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
 
   return true;
 }
 
 #ifdef MOZ_WIDGET_GONK
 static gfx::SurfaceFormat
-SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat)
+SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
+                                   bool swapRB = false)
 {
   switch (aFormat) {
+  case android::PIXEL_FORMAT_BGRA_8888:
+    return swapRB ? FORMAT_R8G8B8A8 : FORMAT_B8G8R8A8;
   case android::PIXEL_FORMAT_RGBA_8888:
-    return FORMAT_B8G8R8A8;
+    return swapRB ? FORMAT_B8G8R8A8 : FORMAT_R8G8B8A8;
   case android::PIXEL_FORMAT_RGBX_8888:
-    return FORMAT_B8G8R8X8;
+    return swapRB ? FORMAT_B8G8R8X8 : FORMAT_R8G8B8X8;
   case android::PIXEL_FORMAT_RGB_565:
     return FORMAT_R5G6B5;
   case android::PIXEL_FORMAT_A_8:
     return FORMAT_A8;
   case HAL_PIXEL_FORMAT_YCbCr_422_SP:
   case HAL_PIXEL_FORMAT_YCrCb_420_SP:
   case HAL_PIXEL_FORMAT_YCbCr_422_I:
   case HAL_PIXEL_FORMAT_YV12:
@@ -754,17 +757,18 @@ GrallocTextureHostOGL::SwapTexturesImpl(
 
   if (mBuffer) {
     // only done for hacky fix in gecko 23 for bug 862324.
     RegisterTextureHostAtGrallocBufferActor(nullptr, *mBuffer);
   }
 
   const SurfaceDescriptorGralloc& desc = aImage.get_SurfaceDescriptorGralloc();
   mGraphicBuffer = GrallocBufferActor::GetFrom(desc);
-  mFormat = SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
+  mFormat = SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat(),
+                                               desc.isRBSwapped());
   mTextureTarget = TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
 
   DeleteTextures();
 
   // only done for hacky fix in gecko 23 for bug 862324.
   // Doing this in SetBuffer is not enough, as ImageHostBuffered::SwapTextures can
   // change the value of *mBuffer without calling SetBuffer again.
   RegisterTextureHostAtGrallocBufferActor(this, aImage);
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -398,50 +398,75 @@ gfxSVGGlyphsDocument::InsertGlyphId(Elem
 
     if (NS_FAILED(rv)) {
         return;
     }
 
     mGlyphIdMap.Put(glyphId, aGlyphElement);
 }
 
+// Get the Unicode character at index aPos in the string, and update aPos to
+// point to the next char (i.e. advance by one or two, depending whether we
+// found a surrogate pair).
+// This will assert (and return junk) if the string is not well-formed UTF16.
+// However, this is only used to process an attribute that comes from the
+// SVG-glyph XML document, and is not exposed to modification via the DOM,
+// so it must be well-formed UTF16 data (no unpaired surrogate codepoints)
+// unless our Unicode handling is seriously broken.
+static uint32_t
+NextUSV(const nsAString& aString, uint32_t& aPos)
+{
+    mozilla::DebugOnly<uint32_t> len = aString.Length();
+    NS_ASSERTION(aPos < len, "already at end of string");
+
+    uint32_t c1 = aString[aPos++];
+    if (NS_IS_HIGH_SURROGATE(c1)) {
+        NS_ASSERTION(aPos < len, "trailing high surrogate");
+        uint32_t c2 = aString[aPos++];
+        NS_ASSERTION(NS_IS_LOW_SURROGATE(c2), "isolated high surrogate");
+        return SURROGATE_TO_UCS4(c1, c2);
+    }
+
+    NS_ASSERTION(!NS_IS_LOW_SURROGATE(c1), "isolated low surrogate");
+    return c1;
+}
+
 void
-gfxSVGGlyphsDocument::InsertGlyphChar(Element *aGlyphElement, hb_blob_t *aCmapTable)
+gfxSVGGlyphsDocument::InsertGlyphChar(Element *aGlyphElement,
+                                      hb_blob_t *aCmapTable)
 {
     nsAutoString glyphChar;
-    if (!aGlyphElement->GetAttr(kNameSpaceID_None, nsGkAtoms::glyphchar, glyphChar)) {
+    if (!aGlyphElement->GetAttr(kNameSpaceID_None, nsGkAtoms::glyphchar,
+                                glyphChar)) {
         return;
     }
 
-    uint32_t varSelector;
+    uint32_t charCode, varSelector = 0, len = glyphChar.Length(), index = 0;
+    if (!len) {
+        NS_WARNING("glyphchar is empty");
+        return;
+    }
 
-    // XXX jfkthame
-    // This will not handle surrogate pairs properly!
-    switch (glyphChar.Length()) {
-        case 0:
-            NS_WARNING("glyphchar is empty");
-            return;
-        case 1:
-            varSelector = 0;
-            break;
-        case 2:
-            if (gfxFontUtils::IsVarSelector(glyphChar.CharAt(1))) {
-                varSelector = glyphChar.CharAt(1);
-                break;
-            }
-        default:
+    charCode = NextUSV(glyphChar, index);
+    if (index < len) {
+        varSelector = NextUSV(glyphChar, index);
+        if (!gfxFontUtils::IsVarSelector(varSelector)) {
             NS_WARNING("glyphchar contains more than one character");
             return;
+        }
     }
 
-    uint32_t len;
+    if (index < len) {
+        NS_WARNING("glyphchar contains more than one character");
+        return;
+    }
+
     const uint8_t *data = (const uint8_t*)hb_blob_get_data(aCmapTable, &len);
-    uint32_t glyphId = gfxFontUtils::MapCharToGlyph(data, len,
-                                                    glyphChar.CharAt(0),
-                                                    varSelector);
+    uint32_t glyphId =
+        gfxFontUtils::MapCharToGlyph(data, len, charCode, varSelector);
 
     if (glyphId) {
         mGlyphIdMap.Put(glyphId, aGlyphElement);
     }
 }
 
 void
 gfxTextObjectPaint::InitStrokeGeometry(gfxContext *aContext,
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -199,154 +199,122 @@ unsigned char _BitScanReverse(unsigned l
 {
     unsigned long idx;
 
     _BitScanReverse(&idx, (unsigned long)val);
     return (int)(31-idx);
 }
 # define js_bitscan_ctz32(val)  __BitScanForward32(val)
 # define js_bitscan_clz32(val)  __BitScanReverse32(val)
-# define JS_HAS_BUILTIN_BITSCAN32
 
 #if defined(_M_AMD64) || defined(_M_X64)
 unsigned char _BitScanForward64(unsigned long * Index, unsigned __int64 Mask);
 unsigned char _BitScanReverse64(unsigned long * Index, unsigned __int64 Mask);
 # pragma intrinsic(_BitScanForward64,_BitScanReverse64)
+#endif
 
 __forceinline static int
 __BitScanForward64(unsigned __int64 val)
 {
+#if defined(_M_AMD64) || defined(_M_X64)
     unsigned long idx;
 
     _BitScanForward64(&idx, val);
     return (int)idx;
+#else
+    uint32_t lo = (uint32_t)val;
+    uint32_t hi = (uint32_t)(val >> 32);
+    return lo != 0 ?
+           js_bitscan_ctz32(lo) :
+           32 + js_bitscan_ctz32(hi);
+#endif
 }
 __forceinline static int
 __BitScanReverse64(unsigned __int64 val)
 {
+#if defined(_M_AMD64) || defined(_M_X64)
     unsigned long idx;
 
     _BitScanReverse64(&idx, val);
     return (int)(63-idx);
+#else
+    uint32_t lo = (uint32_t)val;
+    uint32_t hi = (uint32_t)(val >> 32);
+    return hi != 0 ?
+           js_bitscan_clz32(hi) :
+           32 + js_bitscan_clz32(lo);
+#endif
 }
 # define js_bitscan_ctz64(val)  __BitScanForward64(val)
 # define js_bitscan_clz64(val)  __BitScanReverse64(val)
-# define JS_HAS_BUILTIN_BITSCAN64
-#endif
 #elif MOZ_IS_GCC
 
 #if MOZ_GCC_VERSION_AT_LEAST(3, 4, 0)
 # define USE_BUILTIN_CTZ
 #endif
 
 #elif defined(__clang__)
 
 #if __has_builtin(__builtin_ctz)
 # define USE_BUILTIN_CTZ
 #endif
 
 #endif
 
 #if defined(USE_BUILTIN_CTZ)
+
+JS_STATIC_ASSERT(sizeof(unsigned int) == sizeof(uint32_t));
 # define js_bitscan_ctz32(val)  __builtin_ctz(val)
 # define js_bitscan_clz32(val)  __builtin_clz(val)
-# define JS_HAS_BUILTIN_BITSCAN32
-# if (JS_BYTES_PER_WORD == 8)
-#  define js_bitscan_ctz64(val)  __builtin_ctzll(val)
-#  define js_bitscan_clz64(val)  __builtin_clzll(val)
-#  define JS_HAS_BUILTIN_BITSCAN64
-# endif
+
+JS_STATIC_ASSERT(sizeof(unsigned long long) == sizeof(uint64_t));
+# define js_bitscan_ctz64(val)  __builtin_ctzll(val)
+# define js_bitscan_clz64(val)  __builtin_clzll(val)
 
 # undef USE_BUILTIN_CTZ
 
 #endif
 
 /*
 ** Macro version of JS_CeilingLog2: Compute the log of the least power of
 ** 2 greater than or equal to _n. The result is returned in _log2.
 */
-#ifdef JS_HAS_BUILTIN_BITSCAN32
 /*
  * Use intrinsic function or count-leading-zeros to calculate ceil(log2(_n)).
  * The macro checks for "n <= 1" and not "n != 0" as js_bitscan_clz32(0) is
  * undefined.
  */
 # define JS_CEILING_LOG2(_log2,_n)                                            \
     JS_BEGIN_MACRO                                                            \
         unsigned int j_ = (unsigned int)(_n);                                 \
         (_log2) = (j_ <= 1 ? 0 : 32 - js_bitscan_clz32(j_ - 1));              \
     JS_END_MACRO
-#else
-# define JS_CEILING_LOG2(_log2,_n)                                            \
-    JS_BEGIN_MACRO                                                            \
-        uint32_t j_ = (uint32_t)(_n);                                         \
-        (_log2) = 0;                                                          \
-        if ((j_) & ((j_)-1))                                                  \
-            (_log2) += 1;                                                     \
-        if ((j_) >> 16)                                                       \
-            (_log2) += 16, (j_) >>= 16;                                       \
-        if ((j_) >> 8)                                                        \
-            (_log2) += 8, (j_) >>= 8;                                         \
-        if ((j_) >> 4)                                                        \
-            (_log2) += 4, (j_) >>= 4;                                         \
-        if ((j_) >> 2)                                                        \
-            (_log2) += 2, (j_) >>= 2;                                         \
-        if ((j_) >> 1)                                                        \
-            (_log2) += 1;                                                     \
-    JS_END_MACRO
-#endif
 
 /*
 ** Macro version of JS_FloorLog2: Compute the log of the greatest power of
 ** 2 less than or equal to _n. The result is returned in _log2.
 **
 ** This is equivalent to finding the highest set bit in the word.
 */
-#ifdef JS_HAS_BUILTIN_BITSCAN32
 /*
  * Use js_bitscan_clz32 or count-leading-zeros to calculate floor(log2(_n)).
  * Since js_bitscan_clz32(0) is undefined, the macro set the loweset bit to 1
  * to ensure 0 result when _n == 0.
  */
 # define JS_FLOOR_LOG2(_log2,_n)                                              \
     JS_BEGIN_MACRO                                                            \
         (_log2) = 31 - js_bitscan_clz32(((unsigned int)(_n)) | 1);            \
     JS_END_MACRO
-#else
-# define JS_FLOOR_LOG2(_log2,_n)                                              \
-    JS_BEGIN_MACRO                                                            \
-        uint32_t j_ = (uint32_t)(_n);                                         \
-        (_log2) = 0;                                                          \
-        if ((j_) >> 16)                                                       \
-            (_log2) += 16, (j_) >>= 16;                                       \
-        if ((j_) >> 8)                                                        \
-            (_log2) += 8, (j_) >>= 8;                                         \
-        if ((j_) >> 4)                                                        \
-            (_log2) += 4, (j_) >>= 4;                                         \
-        if ((j_) >> 2)                                                        \
-            (_log2) += 2, (j_) >>= 2;                                         \
-        if ((j_) >> 1)                                                        \
-            (_log2) += 1;                                                     \
-    JS_END_MACRO
-#endif
 
 #if JS_BYTES_PER_WORD == 4
-# ifdef JS_HAS_BUILTIN_BITSCAN32
 #  define js_FloorLog2wImpl(n)                                                \
     ((size_t)(JS_BITS_PER_WORD - 1 - js_bitscan_clz32(n)))
-# else
-JS_PUBLIC_API(size_t) js_FloorLog2wImpl(size_t n);
-# endif
 #elif JS_BYTES_PER_WORD == 8
-# ifdef JS_HAS_BUILTIN_BITSCAN64
 #  define js_FloorLog2wImpl(n)                                                \
     ((size_t)(JS_BITS_PER_WORD - 1 - js_bitscan_clz64(n)))
-# else
-JS_PUBLIC_API(size_t) js_FloorLog2wImpl(size_t n);
-# endif
 #else
 # error "NOT SUPPORTED"
 #endif
 
 JS_END_EXTERN_C
 
 /*
  * Internal function.
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -3070,16 +3070,42 @@ MOZ_ARG_ENABLE_STRING([update-channel],
     MOZ_UPDATE_CHANNEL=`echo $enableval | tr A-Z a-z`)
 
 if test -z "$MOZ_UPDATE_CHANNEL"; then
     MOZ_UPDATE_CHANNEL=default
 fi
 AC_DEFINE_UNQUOTED(MOZ_UPDATE_CHANNEL, $MOZ_UPDATE_CHANNEL)
 AC_SUBST(MOZ_UPDATE_CHANNEL)
 
+
+dnl set GRE_MILESTONE
+dnl ========================================================
+GRE_MILESTONE=`tail -n 1 "$_topsrcdir"/config/milestone.txt 2>/dev/null || tail -1 "$_topsrcdir"/config/milestone.txt`
+AC_SUBST(GRE_MILESTONE)
+
+dnl set RELEASE_BUILD and NIGHTLY_BUILD variables depending on the cycle we're in
+dnl The logic works like this:
+dnl - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD)
+dnl - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora
+dnl - otherwise, we're building Release/Beta (define RELEASE_BUILD)
+case "$GRE_MILESTONE" in
+  *a1*)
+      NIGHTLY_BUILD=1
+      AC_DEFINE(NIGHTLY_BUILD)
+      ;;
+  *a*)
+      ;;
+  *)
+      RELEASE_BUILD=1
+      AC_DEFINE(RELEASE_BUILD)
+      ;;
+esac
+AC_SUBST(NIGHTLY_BUILD)
+AC_SUBST(RELEASE_BUILD)
+
 dnl ========================================================
 dnl =
 dnl = Check for external package dependencies
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(External Packages)
 
 dnl ========================================================
--- a/js/src/ion/shared/MacroAssembler-x86-shared.h
+++ b/js/src/ion/shared/MacroAssembler-x86-shared.h
@@ -378,53 +378,37 @@ class MacroAssemblerX86Shared : public A
         bind(&inRange);
         if (src != dest)
             movl(src, dest);
         bind(&done);
     }
 
     bool maybeInlineDouble(uint64_t u, const FloatRegister &dest) {
         // This implements parts of "13.4 Generating constants" of
-        // "2. Optimizing subroutines in assembly language" by Agner Fog.
-        switch (u) {
-          case 0x0000000000000000ULL: // 0.0
+        // "2. Optimizing subroutines in assembly language" by Agner Fog,
+        // generalized to handle any case that can use a pcmpeqw and
+        // up to two shifts.
+
+        if (u == 0) {
             xorpd(dest, dest);
-            break;
-          case 0x8000000000000000ULL: // -0.0
-            pcmpeqw(dest, dest);
-            psllq(Imm32(63), dest);
-            break;
-          case 0x3fe0000000000000ULL: // 0.5
-            pcmpeqw(dest, dest);
-            psllq(Imm32(55), dest);
-            psrlq(Imm32(2), dest);
-            break;
-          case 0x3ff0000000000000ULL: // 1.0
+            return true;
+        }
+
+        int tz = js_bitscan_ctz64(u);
+        int lz = js_bitscan_clz64(u);
+        if (u == (~uint64_t(0) << (lz + tz) >> lz)) {
             pcmpeqw(dest, dest);
-            psllq(Imm32(54), dest);
-            psrlq(Imm32(2), dest);
-            break;
-          case 0x3ff8000000000000ULL: // 1.5
-            pcmpeqw(dest, dest);
-            psllq(Imm32(53), dest);
-            psrlq(Imm32(2), dest);
-            break;
-          case 0x4000000000000000ULL: // 2.0
-            pcmpeqw(dest, dest);
-            psllq(Imm32(63), dest);
-            psrlq(Imm32(1), dest);
-            break;
-          case 0xc000000000000000ULL: // -2.0
-            pcmpeqw(dest, dest);
-            psllq(Imm32(62), dest);
-            break;
-          default:
-            return false;
+            if (tz != 0)
+                psllq(Imm32(lz + tz), dest);
+            if (lz != 0)
+                psrlq(Imm32(lz), dest);
+            return true;
         }
-        return true;
+
+        return false;
     }
 
     void emitSet(Assembler::Condition cond, const Register &dest,
                  Assembler::NaNCond ifNaN = Assembler::NaN_HandledByCond) {
         if (GeneralRegisterSet(Registers::SingleByteRegs).has(dest)) {
             // If the register we're defining is a single byte register,
             // take advantage of the setCC instruction
             setCC(cond, dest);
deleted file mode 100644
--- a/js/src/jslog2.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "jsutil.h"
-
-/*
- * Check that we can use js_bitscan_clz32 to implement JS_FLOOR_LOG2 and
- * JS_FLOOR_LOG2W and js_bitscan_clz64 to implement JS_FLOOR_LOG2W on 64-bit
- * systems.
- */
-#ifdef JS_HAS_BUILTIN_BITSCAN32
-JS_STATIC_ASSERT(sizeof(unsigned int) == sizeof(uint32_t));
-JS_STATIC_ASSERT_IF(JS_BYTES_PER_WORD == 4,
-                    sizeof(unsigned int) == sizeof(uintptr_t));
-#endif
-#ifdef JS_HAS_BUILTIN_BITSCAN64
-JS_STATIC_ASSERT_IF(JS_BYTES_PER_WORD == 8,
-                    sizeof(unsigned long long) == sizeof(uintptr_t));
-#endif
-
-#if !defined(JS_HAS_BUILTIN_BITSCAN32) && JS_BYTES_PER_WORD == 4
-
-size_t
-js_FloorLog2wImpl(size_t n)
-{
-    size_t log2;
-
-    JS_FLOOR_LOG2(log2, n);
-    return log2;
-}
-#endif
-/*
- * js_FloorLog2wImpl has to be defined only for 64-bit non-GCC case.
- */
-#if !defined(JS_HAS_BUILTIN_BITSCAN64) && JS_BYTES_PER_WORD == 8
-
-size_t
-js_FloorLog2wImpl(size_t n)
-{
-    size_t log2, m;
-
-    JS_ASSERT(n != 0);
-
-    log2 = 0;
-    m = n >> 32;
-    if (m != 0) { n = m; log2 = 32; }
-    m = n >> 16;
-    if (m != 0) { n = m; log2 |= 16; }
-    m = n >> 8;
-    if (m != 0) { n = m; log2 |= 8; }
-    m = n >> 4;
-    if (m != 0) { n = m; log2 |= 4; }
-    m = n >> 2;
-    if (m != 0) { n = m; log2 |= 2; }
-    log2 |= (n >> 1);
-
-    return log2;
-}
-
-#endif
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -227,17 +227,17 @@ js::ecmaAtan2(double x, double y)
         if (y < 0)
             z *= 3;
         return z;
     }
 #endif
 
 #if defined(SOLARIS) && defined(__GNUC__)
     if (x == 0) {
-        if (MOZ_DOUBLE_IS_NEGZERO(y))
+        if (IsNegativeZero(y))
             return js_copysign(M_PI, x);
         if (y == 0)
             return x;
     }
 #endif
     return atan2(x, y);
 }
 
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -151,17 +151,16 @@ CPP_SOURCES += [
     'jsdhash.cpp',
     'jsdtoa.cpp',
     'jsexn.cpp',
     'jsfriendapi.cpp',
     'jsfun.cpp',
     'jsgc.cpp',
     'jsinfer.cpp',
     'jsiter.cpp',
-    'jslog2.cpp',
     'jsmath.cpp',
     'jsmemorymetrics.cpp',
     'jsnativestack.cpp',
     'jsnum.cpp',
     'jsobj.cpp',
     'json.cpp',
     'jsonparser.cpp',
     'jsopcode.cpp',
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-svgglyphs/cat_face-bmp.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style type="text/css">
+/* font with the SVG glyph for the cat face U+1f431 remapped to
+   the BMP smiling-face character U+263a */
+@font-face { font-family: foo; src: url("resources/cat_face-bmp.ttf"); }
+body { font-family: foo, sans-serif; font-size: 24px; }
+td { padding: 2px 10px }
+</style>
+</head>
+<body>
+<table>
+<tr><td>&#x263a;</td><td>ネコ</td><td>cat face</td></tr>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-svgglyphs/cat_face-notref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style type="text/css">
+/* no SVG cat-face glyph, so this should NOT match the testcases */
+body { font-family: sans-serif; font-size: 24px; }
+td { padding: 2px 10px }
+</style>
+</head>
+<body>
+<table>
+<tr><td>&#x263a;</td><td>ネコ</td><td>cat face</td></tr>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-svgglyphs/cat_face.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style type="text/css">
+/* font with an SVG glyph for the cat face U+1f431 */
+@font-face { font-family: foo; src: url("resources/cat_face.ttf"); }
+body { font-family: foo, sans-serif; font-size: 24px; }
+td { padding: 2px 10px }
+</style>
+</head>
+<body>
+<table>
+<tr><td>&#x1f431;</td><td>ネコ</td><td>cat face</td></tr>
+</table>
+</body>
+</html>
--- a/layout/reftests/text-svgglyphs/reftest.list
+++ b/layout/reftests/text-svgglyphs/reftest.list
@@ -12,8 +12,14 @@ pref(gfx.font_rendering.opentype_svg.ena
 pref(gfx.font_rendering.opentype_svg.enabled,true)    == svg-glyph-objectpattern.svg svg-glyph-objectpattern-ref.svg
 pref(gfx.font_rendering.opentype_svg.enabled,true)    == clip.html clip-ref.html
 pref(gfx.font_rendering.opentype_svg.enabled,true)    fuzzy(5,12) == svg-glyph-objectopacity.svg svg-glyph-objectopacity-ref.svg # see bug 871961#c5
 pref(gfx.font_rendering.opentype_svg.enabled,true)    == svg-glyph-objectopacity2.svg svg-glyph-objectopacity2-ref.svg
 pref(gfx.font_rendering.opentype_svg.enabled,true)    random-if(winWidget) == svg-glyph-paintnone.svg svg-glyph-paintnone-ref.svg # bug 872491
 pref(gfx.font_rendering.opentype_svg.enabled,true)    == svg-glyph-cachedopacity.svg svg-glyph-cachedopacity-ref.svg
 pref(gfx.font_rendering.opentype_svg.enabled,true)    == svg-glyph-objectvalue.svg svg-glyph-objectvalue-ref.svg
 pref(gfx.font_rendering.opentype_svg.enabled,true)    fails == svg-glyph-mask.svg svg-glyph-mask-ref.svg # bug 872483
+
+# test for a non-BMP character in the glyphchar attribute (bug 875629)
+pref(gfx.font_rendering.opentype_svg.enabled,true)  != cat_face-bmp.html cat_face-notref.html
+pref(gfx.font_rendering.opentype_svg.enabled,true)  == cat_face.html cat_face-bmp.html
+# test for a variation sequence involving a Plane-1 char and Plane-14 variation selector (bug 875629)
+pref(gfx.font_rendering.opentype_svg.enabled,true)  == two_cats-var.html two_cats-ref.html
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f5c080ba66d395fee53906b1d2516042cecb2f13
GIT binary patch
literal 9544
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e21617e15b5a86fda54f4b2be689a5f5b2256450
GIT binary patch
literal 9592
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..583185a271c2d8ee69593f26137f91ddc9aad79d
GIT binary patch
literal 38248
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
Xt*d{ntADMlf32&3t?T`Bt&8~o1cg%P
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-svgglyphs/two_cats-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style type="text/css">
+@font-face { font-family: foo; src: url("resources/two_cats.ttf"); }
+body { font-family: foo, sans-serif; font-size: 24px; }
+td { padding: 2px 10px }
+</style>
+</head>
+<body>
+<table>
+<tr><td>&#x1f431;</td><td>ネコ</td><td>cat face</td></tr>
+<tr><td>&#x1f63b;</td><td>目がハート(ネコ)</td><td>smiling cat face with heart shaped eyes</td></tr>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-svgglyphs/two_cats-var.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style type="text/css">
+@font-face { font-family: foo; src: url("resources/two_cats.ttf"); }
+body { font-family: foo, sans-serif; font-size: 24px; }
+td { padding: 2px 10px }
+</style>
+</head>
+<body>
+<table>
+<!-- the Plane-14 variation selector U+E0100 should change U+1F431 to the "heart shaped eyes" cat face -->
+<tr><td>&#x1f431;</td><td>ネコ</td><td>cat face</td></tr>
+<tr><td>&#x1f431;&#xe0100;</td><td>目がハート(ネコ)</td><td>smiling cat face with heart shaped eyes</td></tr>
+</table>
+</body>
+</html>
--- a/mobile/android/base/gfx/GLController.java
+++ b/mobile/android/base/gfx/GLController.java
@@ -230,17 +230,17 @@ public class GLController {
     }
 
     /* This function is invoked by JNI on the compositor thread */
     private EGLSurface provideEGLSurface() {
         return mEGLSurface;
     }
 
     private String getEGLError() {
-        return "Error " + mEGL.eglGetError();
+        return "Error " + (mEGL == null ? "(no mEGL)" : mEGL.eglGetError());
     }
 
     void resumeCompositor(int width, int height) {
         // Asking Gecko to resume the compositor takes too long (see
         // https://bugzilla.mozilla.org/show_bug.cgi?id=735230#c23), so we
         // resume the compositor directly. We still need to inform Gecko about
         // the compositor resuming, so that Gecko knows that it can now draw.
         // It is important to not notify Gecko until after the compositor has
--- a/mobile/android/base/tests/BaseTest.java.in
+++ b/mobile/android/base/tests/BaseTest.java.in
@@ -13,17 +13,19 @@ import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.res.AssetManager;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Build;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.DisplayMetrics;
+import android.view.inputmethod.InputMethodManager;
 import android.view.View;
+import android.widget.Button;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 import java.io.File;
 import java.io.InputStream;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -467,16 +469,37 @@ abstract class BaseTest extends Activity
     public final void verifyTabCount(int expectedTabCount) {
         Activity activity = getActivity();
         Element tabCount = mDriver.findElement(activity, "tabs_counter");
         String tabCountText = tabCount.getText();
         int tabCountInt = Integer.parseInt(tabCountText);
         mAsserter.is(tabCountInt, expectedTabCount, "The correct number of tabs are opened");
     }
 
+    // Used to perform clicks on pop-up buttons without having to close the virtual keyboard
+    public void clickOnButton(String label) {
+        final Button button = mSolo.getButton(label);
+        try {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    button.performClick();
+                }
+            });
+       } catch (Throwable throwable) {
+           mAsserter.ok(false, "Unable to click the button","Was unable to click button ");
+       }
+    }
+
+    // Used to hide/show the virtual keyboard
+    public void toggleVKB() {
+        InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
+        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
+    }
+
     protected boolean isBookmark(String[] bookmarks, String aValue) {
         for (int i = 0; i < bookmarks.length; i++) {
             if (bookmarks[i].equals(aValue))
                 return true;
         }
         return false;
     }
 
@@ -668,48 +691,42 @@ abstract class BaseTest extends Activity
         // Clear the Field
         mSolo.clearEditText(fieldIndex);
 
         // Enter the new text
         mSolo.clickOnEditText(fieldIndex);
         mActions.sendKeys(addedText);
         mSolo.clickOnText("OK");
         waitForText("Bookmark updated");
-        mActions.sendSpecialKey(Actions.SpecialKey.BACK); // close the VKB
+        toggleVKB(); // close the VKB
     }
 
     public boolean checkBookmarkEdit(int bookmarkIndex, String addedText, ListView list) {
         Device mDevice = new Device();
         // Open the Edit Bookmark context menu
         View child;
         mSolo.clickOnText("Bookmarks");
         child = list.getChildAt(bookmarkIndex);
         mAsserter.ok(child != null, "check item can be retrieved", child != null ? child.toString() : "null!");
         waitForText("Switch to tab");
         mSolo.clickLongOnView(child);
         waitForText("Share");
         mSolo.clickOnText("Edit");
         waitForText("Edit Bookmark");
 
-        // If the OS is not Gingerbread the vkb will be opened so we need to close it in order to press the "Cancel" button
-        // XXX: This is not true on all devices, but is true on our current automation test machines...
-        if (!(mDevice.version.equals("2.x"))) {
-            mActions.sendSpecialKey(Actions.SpecialKey.BACK); // close the VKB
-        }
-
         // Check if the new text was added
         if (mSolo.searchText(addedText)) {
-            mSolo.clickOnText("Cancel");
+            clickOnButton("Cancel");
             waitForText("about:home");
-            mActions.sendSpecialKey(Actions.SpecialKey.BACK); // close the VKB
+            toggleVKB(); // close the VKB
             return true;
         } else {
-            mSolo.clickOnText("Cancel");
+            clickOnButton("Cancel");
             waitForText("about:home");
-            mActions.sendSpecialKey(Actions.SpecialKey.BACK); // close the VKB
+            toggleVKB(); // close the VKB
             return false;
         }
     }
 
     class Device {
         public final String version; // 2.x or 3.x or 4.x
         public String type; // "tablet" or "phone"
         public final int width;
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -22,17 +22,17 @@
 [testFormHistory]
 [testBrowserProvider]
 [testSearchSuggestions]
 [testSharedPreferences]
 # [testThumbnails] # see bug 813107
 [testAddonManager]
 [testHistory]
 [testVkbOverlap]
-# [testDoorHanger] # see bug 862493
+[testDoorHanger]
 [testTabHistory]
 [testShareLink]
 [testClearPrivateData]
 # [testSettingsMenuItems] # see bug 843947
 # [testSystemPages] # see bug 869030
 # [testPermissions] # see bug 757475
 # [testJarReader] # see bug 738890
 [testDistribution]
--- a/mobile/android/base/tests/testAddSearchEngine.java.in
+++ b/mobile/android/base/tests/testAddSearchEngine.java.in
@@ -46,22 +46,17 @@ public class testAddSearchEngine extends
             mAsserter.dumpLog("Something went wrong and the context menu was not opened. Trying again");
             mSolo.clickLongOnScreen(width,height);
         }
         mAsserter.ok(waitForText("Add Search Engine"), "Waiting for the context menu to be opened", "The context menu was opened");
 
         // Add the search engine
         mSolo.clickOnText("Add Search Engine");
         waitForText("Cancel");
-        if (mDevice.type.equals("tablet")) {
-            // On tablets, the vkb is opened when the popup is triggered so we need to close it in order to click the OK button
-            mActions.sendSpecialKey(Actions.SpecialKey.BACK);
-            waitForText("OK"); // Make sure the OK button is visible
-        }
-        mSolo.clickOnButton("OK");
+        clickOnButton("OK");
         mAsserter.ok(!mSolo.searchText("Add Search Engine"), "Adding the search engine", "The add search engine pop-up has been closed");
 
         // Check that the number of search results has increased
         mAsserter.is(getNumSearchEngines("Robocop Search Engine"), initialNumSearchEngines + 1 , "The number of search results has increased");
     }
 
     public int getNumSearchEngines(String waitText) {
         ArrayList<ListView> views;
--- a/mobile/android/base/tests/testMasterPassword.java.in
+++ b/mobile/android/base/tests/testMasterPassword.java.in
@@ -113,17 +113,17 @@ public class testMasterPassword extends 
         closeTabletKeyboard();
         editPasswordField(0, password);
         mSolo.clickOnButton("OK");
 
         // Verify that the Master Password was disabled
         mSolo.waitForText("^Use master password$");
         mSolo.clickOnText("^Use master password$");
         mAsserter.ok(mSolo.waitForText("^Create Master Password$"), "Checking if the password is disabled", "The password is disabled");
-        mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Close the VKB
+        toggleVKB(); // Close the VKB
         mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Close the Master Password menu
     }
 
     public void editPasswordField(int i, String password) {
         mSolo.clickOnEditText(i);
         mActions.sendKeys(password);
         mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Close the VKB
     }
@@ -139,17 +139,17 @@ public class testMasterPassword extends 
         loadUrl(LOGIN_URL);
         mAsserter.is(mSolo.waitForText("Save password for"), true, "Doorhanger notification is displayed");
     }
 
     // Checks to see if the device is a Tablet, because for those devices we need an extra back action to close the keyboard
     public void closeTabletKeyboard() {
         if (dev.type.equals("tablet")) {
             mSolo.sleep(1500);
-            mActions.sendSpecialKey(Actions.SpecialKey.BACK);// Close the keyboard for tablets
+            toggleVKB();// Close the keyboard for tablets
         }
     }
 
     public void clearPrivateData() {
 
         // Look for the 'Settings' menu if this device/OS uses it
         selectMenuItem("Settings");
         if (dev.type.equals("tablet")) {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1884,20 +1884,18 @@ var NativeWindow = {
           getValue: function(aElt) {
             if (item.hasAttribute("hidden"))
               return null;
 
             return {
               icon: item.icon,
               label: item.label,
               id: id,
-              isGroup: false,
-              inGroup: false,
               disabled: item.disabled,
-              isParent: item instanceof Ci.nsIDOMHTMLMenuElement
+              parent: item instanceof Ci.nsIDOMHTMLMenuElement
             }
           }
         };
 
         this.menuitems.splice(this._nativeItemsSeparator, 0, menuitem);
         this._nativeItemsSeparator++;
       }
     },
@@ -2012,46 +2010,46 @@ var NativeWindow = {
         // hidden menu items will return null from getValue
         if (val)
           itemArray.push(val);
       }
 
       if (itemArray.length == 0)
         return;
 
-      let msg = {
-        type: "Prompt:Show",
-        title: title,
-        listitems: itemArray
-      };
-      let data = JSON.parse(sendMessageToJava(msg));
-      if (data.button == -1) {
-        // prompt was cancelled
-        return;
-      }
-
-      let selectedId = itemArray[data.button].id;
-      let selectedItem = this._getMenuItemForId(selectedId);
-
-      this.menuitems = null;
-      if (selectedItem && selectedItem.callback) {
-        if (selectedItem.matches) {
-          // for menuitems added using the native UI, pass the dom element that matched that item to the callback
-          while (aTarget) {
-            if (selectedItem.matches(aTarget, aX, aY)) {
-              selectedItem.callback.call(selectedItem, aTarget, aX, aY);
-              break;
+      let prompt = new Prompt({
+        window: aTarget.ownerDocument.defaultView,
+        title: title
+      }).setSingleChoiceItems(itemArray)
+      .show((function(data) {
+        if (data.button == -1) {
+          // prompt was cancelled
+          return;
+        }
+
+        let selectedId = itemArray[data.button].id;
+        let selectedItem = this._getMenuItemForId(selectedId);
+
+        this.menuitems = null;
+        if (selectedItem && selectedItem.callback) {
+          if (selectedItem.matches) {
+            // for menuitems added using the native UI, pass the dom element that matched that item to the callback
+            while (aTarget) {
+              if (selectedItem.matches(aTarget, aX, aY)) {
+                selectedItem.callback.call(selectedItem, aTarget, aX, aY);
+                break;
+              }
+              aTarget = aTarget.parentNode;
             }
-            aTarget = aTarget.parentNode;
+          } else {
+            // if this was added using the html5 context menu api, just click on the context menu item
+            selectedItem.callback.call(selectedItem, aTarget, aX, aY);
           }
-        } else {
-          // if this was added using the html5 context menu api, just click on the context menu item
-          selectedItem.callback.call(selectedItem, aTarget, aX, aY);
         }
-      }
+      }).bind(this));
     },
 
     handleEvent: function(aEvent) {
       BrowserEventHandler._cancelTapHighlight();
       aEvent.target.ownerDocument.defaultView.removeEventListener("contextmenu", this, false);
       this._show(aEvent);
     },
 
@@ -3901,18 +3899,16 @@ var BrowserEventHandler = {
     Services.obs.addObserver(this, "Gesture:DoubleTap", false);
     Services.obs.addObserver(this, "Gesture:Scroll", false);
     Services.obs.addObserver(this, "dom-touch-listener-added", false);
 
     BrowserApp.deck.addEventListener("DOMUpdatePageReport", PopupBlockerObserver.onUpdatePageReport, false);
     BrowserApp.deck.addEventListener("touchstart", this, true);
     BrowserApp.deck.addEventListener("click", InputWidgetHelper, true);
     BrowserApp.deck.addEventListener("click", SelectHelper, true);
-    document.addEventListener("MozMagnifyGestureStart", this, true);
-    document.addEventListener("MozMagnifyGestureUpdate", this, true);
     document.addEventListener("MozMagnifyGesture", this, true);
 
     Services.prefs.addObserver("browser.zoom.reflowOnZoom", this, false);
     this.updateReflozPref();
   },
 
   resetMaxLineBoxWidth: function() {
     BrowserApp.selectedTab.probablyNeedRefloz = false;
@@ -3931,19 +3927,19 @@ var BrowserEventHandler = {
   },
 
   handleEvent: function(aEvent) {
     switch (aEvent.type) {
       case 'touchstart':
         this._handleTouchStart(aEvent);
         break;
       case 'MozMagnifyGesture':
-      case 'MozMagnifyGestureUpdate':
-      case 'MozMagnifyGestureStart':
-        this.observe(this, aEvent.type, JSON.stringify({x: aEvent.screenX, y: aEvent.screenY}));
+        this.observe(this, aEvent.type,
+                     JSON.stringify({x: aEvent.screenX, y: aEvent.screenY,
+                                     zoomDelta: aEvent.delta}));
         break;
     }
   },
 
   _handleTouchStart: function(aEvent) {
     if (!BrowserApp.isBrowserContentDocumentDisplayed() || aEvent.touches.length > 1 || aEvent.defaultPrevented)
       return;
 
@@ -4100,19 +4096,18 @@ var BrowserEventHandler = {
         break;
       }
 
       case"Gesture:DoubleTap":
         this._cancelTapHighlight();
         this.onDoubleTap(aData);
         break;
 
-      case "MozMagnifyGestureStart":
-      case "MozMagnifyGestureUpdate":
-        this.onPinch(aData);
+      case "MozMagnifyGesture":
+        this.onPinchFinish(aData);
         break;
 
       default:
         dump('BrowserEventHandler.handleUserEvent: unexpected topic "' + aTopic + '"');
         break;
     }
   },
 
@@ -4275,27 +4270,28 @@ var BrowserEventHandler = {
     rect.y = Math.max(topPos, viewport.cssPageTop);
     rect.w = viewport.cssWidth;
     rect.h = viewport.cssHeight;
 
     sendMessageToJava(rect);
     BrowserApp.selectedTab._mReflozPoint = null;
    },
 
-   onPinch: function(aData) {
-     // We only want to do this if reflow-on-zoom is enabled.
+   onPinchFinish: function(aData) {
+     let data = {};
+     try {
+       data = JSON.parse(aData);
+     } catch(ex) {
+       console.log(ex);
+       return;
+     }
+
      if (BrowserEventHandler.mReflozPref &&
-         !BrowserApp.selectedTab._mReflozPoint) {
-       let data = JSON.parse(aData);
-       let zoomPointX = data.x;
-       let zoomPointY = data.y;
-
-       BrowserApp.selectedTab._mReflozPoint = { x: zoomPointX, y: zoomPointY,
-         range: BrowserApp.selectedBrowser.contentDocument.caretPositionFromPoint(zoomPointX, zoomPointY) };
-         BrowserApp.selectedTab.probablyNeedRefloz = true;
+         data.zoomDelta < 0.0) {
+       BrowserEventHandler.resetMaxLineBoxWidth();
      }
    },
 
   _shouldZoomToElement: function(aElement) {
     let win = aElement.ownerDocument.defaultView;
     if (win.getComputedStyle(aElement, null).display == "inline")
       return false;
     if (aElement instanceof Ci.nsIDOMHTMLLIElement)
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3961,16 +3961,20 @@ pref("webgl.min_capability_mode", false)
 pref("webgl.disable-extensions", false);
 pref("webgl.msaa-force", false);
 pref("webgl.prefer-16bpp", false);
 pref("webgl.default-no-alpha", false);
 pref("webgl.force-layers-readback", false);
 pref("webgl.lose-context-on-heap-minimize", false);
 pref("webgl.can-lose-context-in-foreground", true);
 pref("webgl.max-warnings-per-context", 32);
+#ifdef MOZ_WIDGET_GONK
+pref("gfx.gralloc.fence-with-readpixels", false);
+#endif
+
 
 // Stagefright prefs
 pref("stagefright.force-enabled", false);
 pref("stagefright.disabled", false);
 
 #ifdef XP_WIN
 // The default TCP send window on Windows is too small, and autotuning only occurs on receive
 pref("network.tcp.sendbuffer", 131072);
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -267,23 +267,17 @@ class MozbuildObject(ProcessExecutionMix
         if substs['OS_ARCH'] == 'Darwin':
             stem = os.path.join(stem, substs['MOZ_MACBUNDLE_NAME'], 'Contents',
                 'MacOS')
         elif where == 'default':
             stem = os.path.join(stem, 'bin')
 
         leaf = None
 
-        if what == 'app':
-            leaf = substs['MOZ_APP_NAME'] + substs['BIN_SUFFIX']
-        elif what == 'xpcshell':
-            leaf = 'xpcshell'
-        else:
-            raise Exception("Don't know how to locate binary: %s" % what)
-
+        leaf = (substs['MOZ_APP_NAME'] if what == 'app' else what) + substs['BIN_SUFFIX']
         path = os.path.join(stem, leaf)
 
         if validate_exists and not os.path.exists(path):
             raise Exception('Binary expected at %s does not exist.' % path)
 
         return path
 
     @property
--- a/python/mozbuild/mozbuild/test/test_base.py
+++ b/python/mozbuild/mozbuild/test/test_base.py
@@ -113,16 +113,22 @@ class TestMozbuildObject(unittest.TestCa
             self.assertTrue(p.endswith('awesomeapp/Nightly.app/Contents/MacOS/awesomeapp'))
         elif platform.startswith(('win32', 'cygwin')):
             self.assertTrue(p.endswith('awesomeapp/awesomeapp.exe'))
         else:
             self.assertTrue(p.endswith('awesomeapp/awesomeapp'))
 
         self.assertRaises(Exception, base.get_binary_path, where="somewhere")
 
+        p = base.get_binary_path('foobar', validate_exists=False)
+        if platform.startswith('win32'):
+            self.assertTrue(p.endswith('foobar.exe'))
+        else:
+            self.assertTrue(p.endswith('foobar'))
+
 class TestPathArgument(unittest.TestCase):
     def test_path_argument(self):
         # Absolute path
         p = PathArgument("/obj/foo", "/src", "/obj", "/src")
         self.assertEqual(p.relpath(), "foo")
         self.assertEqual(p.srcdir_path(), "/src/foo")
         self.assertEqual(p.objdir_path(), "/obj/foo")
 
--- a/testing/marionette/client/marionette/tests/unit/test_navigation.py
+++ b/testing/marionette/client/marionette/tests/unit/test_navigation.py
@@ -66,20 +66,46 @@ class TestNavigate(MarionetteTestCase):
         self.marionette.switch_to_frame(0)
         self.marionette.navigate(self.marionette.absolute_url("empty.html"))
         self.assertTrue('empty.html' in self.marionette.get_url())
         self.marionette.switch_to_frame()
         self.assertTrue('test_iframe.html' in self.marionette.get_url())
 
     def test_shouldnt_error_if_nonexistent_url_used(self):
         try:
-            self.marionette.navigate("http://localhost:12345")
+            self.marionette.navigate("thisprotocoldoesnotexist://")
             self.fail("Should have thrown a MarionetteException")
         except TimeoutException: 
             self.fail("The socket shouldn't have timed out when navigating to a non-existent URL")
-        except MarionetteException:
-            pass
+        except MarionetteException as e:
+            self.assertEqual(str(e), 'Error loading page')
         except Exception as inst:
             import traceback
             print traceback.format_exc()
             self.fail("Should have thrown a MarionetteException instead of %s" % type(inst))
 
+    def test_find_element_state_complete(self):
+        test_html = self.marionette.absolute_url("test.html")
+        self.marionette.navigate(test_html)
+        state = self.marionette.execute_script("return window.document.readyState;")
+        self.assertEqual("complete", state)
+        self.assertTrue(self.marionette.find_element("id", "mozLink"))
 
+    def test_should_throw_a_timeoutexception_when_loading_page(self):
+        try:
+            self.marionette.timeouts("page load", 0)
+            test_html = self.marionette.absolute_url("test.html")
+            self.marionette.navigate(test_html)
+            self.assertTrue(self.marionette.find_element("id", "mozLink"))
+            self.fail("Should have thrown a MarionetteException")
+        except MarionetteException as e:
+            self.assertEqual(str(e), "Error loading page, timed out")
+        except Exception as inst:
+            import traceback
+            print traceback.format_exc()
+            self.fail("Should have thrown a MarionetteException instead of %s" % type(inst))
+
+    def test_navigate_iframe(self):
+        test_iframe = self.marionette.absolute_url("test_iframe.html")
+        self.marionette.navigate(test_iframe)
+        self.assertTrue('test_iframe.html' in self.marionette.get_url())
+        self.assertTrue(self.marionette.find_element("id", "test_iframe"))
+
--- a/testing/marionette/marionette-listener.js
+++ b/testing/marionette/marionette-listener.js
@@ -1052,36 +1052,53 @@ function multiAction(msg) {
 }
 
 /**
  * Navigate to URI. Handles the case where we navigate within an iframe.
  * All other navigation is handled by the server (in chrome space).
  */
 function goUrl(msg) {
   let command_id = msg.json.command_id;
+
+  let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+  let start = new Date().getTime();
+  let end = null;
+  function checkLoad(){
+    end = new Date().getTime();
+    let errorRegex = /about:.+(error)|(blocked)\?/;
+    let elapse = end - start;
+    if (msg.json.pageTimeout == null || elapse <= msg.json.pageTimeout){
+      if (curWindow.document.readyState == "complete"){
+        sendOk(command_id);
+        checkTimer.cancel();
+      }
+      else if (curWindow.document.readyState == "interactive" && errorRegex.exec(curWindow.document.baseURI)){
+        sendError("Error loading page", 13, null, command_id);
+      }
+      else{
+        checkTimer.cancel();
+        checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT);
+      }
+    }
+    else{
+      sendError("Error loading page, timed out", 21, null, command_id);
+    }
+  }
   // Prevent DOMContentLoaded events from frames from invoking this code,
   // unless the event is coming from the frame associated with the current
   // window (i.e., someone has used switch_to_frame).
   let onDOMContentLoaded = function onDOMContentLoaded(event){
-    if (msg.json.pageTimeout != null){
-      checkTimer.cancel();
-    }
     if (!event.originalTarget.defaultView.frameElement ||
       event.originalTarget.defaultView.frameElement == curWindow.frameElement) {
-      removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
-      let errorRegex = /about:.+(error)|(blocked)\?/;
-      if (curWindow.document.readyState == "interactive" && errorRegex.exec(curWindow.document.baseURI)) {
-        sendError("Error loading page", 13, null, command_id);
-        return;
-      }
-      sendOk(command_id);
+      checkLoad();
     }
   };
+
   function timerFunc(){
-    sendError("Error loading page", 13, null, command_id);
+    sendError("Error loading page, timed out", 21, null, command_id);
     removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
   }
   if (msg.json.pageTimeout != null){
     checkTimer.initWithCallback(timerFunc, msg.json.pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
   }
   addEventListener("DOMContentLoaded", onDOMContentLoaded, false);
   curWindow.location = msg.json.value;
 }
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -375,17 +375,17 @@ jetpack-tests:
 	$(PYTHON) $(topsrcdir)/addon-sdk/source/bin/cfx -b $(browser_path) --parseable testpkgs
 
 # -- -register
 # -- --trace-malloc malloc.log --shutdown-leaks=sdleak.log
 leaktest:
 	$(PYTHON) _leaktest/leaktest.py $(LEAKTEST_ARGS)
 
 pgo-profile-run:
-	$(PYTHON) $(DEPTH)/_profile/pgo/profileserver.py $(EXTRA_TEST_ARGS)
+	$(PYTHON) $(topsrcdir)/build/pgo/profileserver.py $(EXTRA_TEST_ARGS)
 
 # Package up the tests and test harnesses
 include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
 
 ifndef UNIVERSAL_BINARY
 PKG_STAGE = $(DIST)/test-package-stage
 package-tests: \
   stage-config \
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/DevToolsUtils.js
@@ -0,0 +1,70 @@
+/* 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";
+
+/* General utilities used throughout devtools. */
+
+/* Turn the error e into a string, without fail. */
+function safeErrorString(aError) {
+  try {
+    var s = aError.toString();
+    if (typeof s === "string")
+      return s;
+  } catch (ee) { }
+
+  return "<failed trying to find error description>";
+}
+
+/**
+ * Report that |aWho| threw an exception, |aException|.
+ */
+function reportException(aWho, aException) {
+  let msg = aWho + " threw an exception: " + safeErrorString(aException);
+  if (aException.stack) {
+    msg += "\nCall stack:\n" + aException.stack;
+  }
+
+  dump(msg + "\n");
+
+  if (Components.utils.reportError) {
+    /*
+     * Note that the xpcshell test harness registers an observer for
+     * console messages, so when we're running tests, this will cause
+     * the test to quit.
+     */
+    Components.utils.reportError(msg);
+  }
+}
+
+/**
+ * Given a handler function that may throw, return an infallible handler
+ * function that calls the fallible handler, and logs any exceptions it
+ * throws.
+ *
+ * @param aHandler function
+ *      A handler function, which may throw.
+ * @param aName string
+ *      A name for aHandler, for use in error messages. If omitted, we use
+ *      aHandler.name.
+ *
+ * (SpiderMonkey does generate good names for anonymous functions, but we
+ * don't have a way to get at them from JavaScript at the moment.)
+ */
+function makeInfallible(aHandler, aName) {
+  if (!aName)
+    aName = aHandler.name;
+
+  return function (/* arguments */) {
+    try {
+      return aHandler.apply(this, arguments);
+    } catch (ex) {
+      let who = "Handler function";
+      if (aName) {
+        who += " " + aName;
+      }
+      reportException(who, ex);
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/DevToolsUtils.jsm
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/*
+ * General utilities used throughout devtools.
+ *
+ * To support chrome debugging, the debugger server needs to have all its
+ * code in one global, so it must use loadSubScript directly. Everyone else,
+ * though, prefers a JSM.
+ */
+
+this.EXPORTED_SYMBOLS = [ "DevToolsUtils" ];
+
+Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+  .getService(Components.interfaces.mozIJSSubScriptLoader)
+  .loadSubScript("resource://gre/modules/devtools/DevToolsUtils.js", this);
+
+this.DevToolsUtils = {
+  safeErrorString: safeErrorString,
+  reportException: reportException,
+  makeInfallible: makeInfallible
+};
--- a/toolkit/devtools/Makefile.in
+++ b/toolkit/devtools/Makefile.in
@@ -8,8 +8,9 @@ srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(topsrcdir)/config/config.mk
 
 include $(topsrcdir)/config/rules.mk
 
 libs::
 	$(NSINSTALL) $(IFLAGS1) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
+	$(NSINSTALL) $(IFLAGS1) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools
--- a/toolkit/devtools/client/dbg-client.jsm
+++ b/toolkit/devtools/client/dbg-client.jsm
@@ -24,16 +24,19 @@ const { defer, resolve, reject } = Promi
 
 XPCOMUtils.defineLazyServiceGetter(this, "socketTransportService",
                                    "@mozilla.org/network/socket-transport-service;1",
                                    "nsISocketTransportService");
 
 XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleClient",
                                   "resource://gre/modules/devtools/WebConsoleClient.jsm");
 
+Components.utils.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
+var { makeInfallible } = DevToolsUtils;
+
 let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
 
 function dumpn(str)
 {
   if (wantLogging) {
     dump("DBG-CLIENT: " + str + "\n");
   }
 }
--- a/toolkit/devtools/server/main.js
+++ b/toolkit/devtools/server/main.js
@@ -24,16 +24,18 @@ let wantLogging = Services.prefs.getBool
 Cu.import("resource://gre/modules/jsdebugger.jsm");
 addDebuggerToGlobal(this);
 
 Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
 const { defer, resolve, reject, all } = Promise;
 
 Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
 
+loadSubScript.call(this, "resource://gre/modules/devtools/DevToolsUtils.js");
+
 function dumpn(str) {
   if (wantLogging) {
     dump("DBG-SERVER: " + str + "\n");
   }
 }
 
 function dbg_assert(cond, e) {
   if (!cond) {
--- a/toolkit/devtools/server/tests/unit/test_dbgsocket.js
+++ b/toolkit/devtools/server/tests/unit/test_dbgsocket.js
@@ -1,13 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
+Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
+
+var { safeErrorString } = DevToolsUtils;
 
 let port = 2929;
 
 function run_test()
 {
   do_print("Starting test at " + new Date().toTimeString());
   initTestDebuggerServer();
 
--- a/toolkit/devtools/server/transport.js
+++ b/toolkit/devtools/server/transport.js
@@ -2,72 +2,16 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 
-/* Turn the error e into a string, without fail. */
-function safeErrorString(aError) {
-  try {
-    var s = aError.toString();
-    if (typeof s === "string")
-      return s;
-  } catch (ee) { }
-
-  return "<failed trying to find error description>";
-}
-
-/**
- * Given a handler function that may throw, return an infallible handler
- * function that calls the fallible handler, and logs any exceptions it
- * throws.
- *
- * @param aHandler function
- *      A handler function, which may throw.
- * @param aName string
- *      A name for aHandler, for use in error messages. If omitted, we use
- *      aHandler.name.
- *
- * (SpiderMonkey does generate good names for anonymous functions, but we
- * don't have a way to get at them from JavaScript at the moment.)
- */
-function makeInfallible(aHandler, aName) {
-  if (!aName)
-    aName = aHandler.name;
-
-  return function (/* arguments */) {
-    try {
-      return aHandler.apply(this, arguments);
-    } catch (ex) {
-      let msg = "Handler function ";
-      if (aName) {
-        msg += aName + " ";
-      }
-      msg += "threw an exception: " + safeErrorString(ex);
-      if (ex.stack) {
-        msg += "\nCall stack:\n" + ex.stack;
-      }
-
-      dump(msg + "\n");
-
-      if (Cu.reportError) {
-        /*
-         * Note that the xpcshell test harness registers an observer for
-         * console messages, so when we're running tests, this will cause
-         * the test to quit.
-         */
-        Cu.reportError(msg);
-      }
-    }
-  }
-}
-
 /**
  * An adapter that handles data transfers between the debugger client and
  * server. It can work with both nsIPipe and nsIServerSocket transports so
  * long as the properly created input and output streams are specified.
  *
  * @param aInput nsIInputStream
  *        The input stream.
  * @param aOutput nsIAsyncOutputStream
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -138,17 +138,17 @@ INNER_MAKE_PACKAGE	= $(ZIP) -r9D $(PACKA
   -x \*/.mkdir.done
 INNER_UNMAKE_PACKAGE	= $(UNZIP) $(UNPACKAGE)
 MAKE_SDK = $(ZIP) -r9D $(SDK) $(MOZ_APP_NAME)-sdk
 endif
 ifeq ($(MOZ_PKG_FORMAT),SFX7Z)
 PKG_SUFFIX	= .exe
 INNER_MAKE_PACKAGE	= rm -f app.7z && \
   mv $(MOZ_PKG_DIR) core && \
-  $(CYGWIN_WRAPPER) 7z a -r -t7z app.7z -mx -m0=BCJ2 -m1=LZMA:d24 \
+  $(CYGWIN_WRAPPER) 7z a -r -t7z app.7z -mx -m0=BCJ2 -m1=LZMA:d25 \
     -m2=LZMA:d19 -m3=LZMA:d19 -mb0:1 -mb0s1:2 -mb0s2:3 && \
   mv core $(MOZ_PKG_DIR) && \
   cat $(SFX_HEADER) app.7z > $(PACKAGE) && \
   chmod 0755 $(PACKAGE)
 INNER_UNMAKE_PACKAGE	= $(CYGWIN_WRAPPER) 7z x $(UNPACKAGE) core && \
   mv core $(MOZ_PKG_DIR)
 endif
 
--- a/toolkit/mozapps/installer/windows/nsis/makensis.mk
+++ b/toolkit/mozapps/installer/windows/nsis/makensis.mk
@@ -41,33 +41,39 @@ CUSTOM_UI = \
 $(CONFIG_DIR)/setup.exe::
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/toolkit/mozapps/installer/windows/nsis/,$(TOOLKIT_NSIS_FILES)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/other-licenses/nsis/Plugins/,$(CUSTOM_NSIS_PLUGINS)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/other-licenses/nsis/,$(CUSTOM_UI)) $(CONFIG_DIR)
 	cd $(CONFIG_DIR) && $(MAKENSISU) installer.nsi
 ifdef MOZ_STUB_INSTALLER
 	cd $(CONFIG_DIR) && $(MAKENSISU) stub.nsi
 ifdef MOZ_EXTERNAL_SIGNING_FORMAT
+	$(MOZ_SIGN_CMD) $(foreach f,$(MOZ_EXTERNAL_SIGNING_FORMAT),-f $(f)) $(CONFIG_DIR)/setup-stub.exe
+endif
+	$(MAKE) $(CONFIG_DIR)/7zSD.sfx
+	cd $(CONFIG_DIR) &&  $(CYGWIN_WRAPPER) 7z a -t7z $(ABS_CONFIG_DIR)/stub.7z setup-stub.exe -mx -m0=BCJ2 -m1=LZMA:d21 -m2=LZMA:d17 -m3=LZMA:d17 -mb0:1 -mb0s1:2 -mb0s2:3
+	cat $(CONFIG_DIR)/7zSD.sfx $(CONFIG_DIR)/stub.tag $(CONFIG_DIR)/stub.7z > "$(CONFIG_DIR)/stub.exe"
+ifdef MOZ_EXTERNAL_SIGNING_FORMAT
 	$(MOZ_SIGN_CMD) $(foreach f,$(MOZ_EXTERNAL_SIGNING_FORMAT),-f $(f)) $(CONFIG_DIR)/stub.exe
 endif
 endif
 # Support for building the uninstaller when repackaging locales
 ifeq ($(CONFIG_DIR),l10ngen)
 	cd $(CONFIG_DIR) && $(MAKENSISU) uninstaller.nsi
 endif
 ifdef MOZ_EXTERNAL_SIGNING_FORMAT
 	$(MOZ_SIGN_CMD) $(foreach f,$(MOZ_EXTERNAL_SIGNING_FORMAT),-f $(f)) "$@"
 endif
 
 $(CONFIG_DIR)/7zSD.sfx:
 	$(CYGWIN_WRAPPER) upx --best -o $(CONFIG_DIR)/7zSD.sfx $(SFX_MODULE)
 
 installer::
 	$(INSTALL) $(CONFIG_DIR)/setup.exe $(DEPTH)/installer-stage
-	cd $(DEPTH)/installer-stage && $(CYGWIN_WRAPPER) 7z a -r -t7z $(ABS_CONFIG_DIR)/app.7z -mx -m0=BCJ2 -m1=LZMA:d24 -m2=LZMA:d19 -m3=LZMA:d19  -mb0:1 -mb0s1:2 -mb0s2:3
+	cd $(DEPTH)/installer-stage && $(CYGWIN_WRAPPER) 7z a -r -t7z $(ABS_CONFIG_DIR)/app.7z -mx -m0=BCJ2 -m1=LZMA:d25 -m2=LZMA:d19 -m3=LZMA:d19 -mb0:1 -mb0s1:2 -mb0s2:3
 	$(MAKE) $(CONFIG_DIR)/7zSD.sfx
 	$(NSINSTALL) -D $(DIST)/$(PKG_INST_PATH)
 	cat $(CONFIG_DIR)/7zSD.sfx $(CONFIG_DIR)/app.tag $(CONFIG_DIR)/app.7z > "$(DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe"
 	chmod 0755 "$(DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe"
 ifdef MOZ_STUB_INSTALLER
 	cp $(CONFIG_DIR)/stub.exe "$(DIST)/$(PKG_INST_PATH)$(PKG_STUB_BASENAME).exe"
 	chmod 0755 "$(DIST)/$(PKG_INST_PATH)$(PKG_STUB_BASENAME).exe"
 endif
--- a/tools/update-packaging/make_incremental_updates.py
+++ b/tools/update-packaging/make_incremental_updates.py
@@ -37,17 +37,17 @@ class PatchInfo:
         
     def append_add_instruction(self, filename):
         """ Appends an add instruction for this patch.   
             if the filename starts with distribution/extensions/ adds an add-if
             instruction to test the existence of the subdirectory.  This was
             ported from mozilla/tools/update-packaging/common.sh's
             make_add_instruction.
         """
-        m = re.match("((?:|.*/)distribution/extensions)/", filename):
+        m = re.match("((?:|.*/)distribution/extensions)/", filename)
         if m:
             # Directory immediately following extensions is used for the test
             testdir = m.group(1)
             self.manifestv1.append('add-if "'+testdir+'" "'+filename+'"')
             self.manifestv2.append('add-if "'+testdir+'" "'+filename+'"')
         else:
             self.manifestv1.append('add "'+filename+'"')
             self.manifestv2.append('add "'+filename+'"')
@@ -58,17 +58,17 @@ class PatchInfo:
             filename = file to patch
             patchname = patchfile to apply to file
             
             if the filename starts with distribution/extensions/ adds a
             patch-if instruction to test the existence of the subdirectory.  
             This was ported from
             mozilla/tools/update-packaging/common.sh's make_patch_instruction.
         """
-        m = re.match("((?:|.*/)distribution/extensions)/", filename):
+        m = re.match("((?:|.*/)distribution/extensions)/", filename)
         if m:
             testdir = m.group(1)
             self.manifestv1.append('patch-if "'+testdir+'" "'+patchname+'" "'+filename+'"')
             self.manifestv2.append('patch-if "'+testdir+'" "'+patchname+'" "'+filename+'"')
         else:
             self.manifestv1.append('patch "'+patchname+'" "'+filename+'"')
             self.manifestv2.append('patch "'+patchname+'" "'+filename+'"')
                 
--- a/widget/nsGUIEvent.h
+++ b/widget/nsGUIEvent.h
@@ -1547,30 +1547,16 @@ public:
   // values of mComputedScrollAction
   enum {
     SCROLL_ACTION_NONE,
     SCROLL_ACTION_LINE,
     SCROLL_ACTION_PAGE
   };
 };
 
-class nsFocusEvent : public nsEvent
-{
-public:
-  nsFocusEvent(bool isTrusted, uint32_t msg)
-    : nsEvent(isTrusted, msg, NS_FOCUS_EVENT),
-      fromRaise(false),
-      isRefocus(false)
-  {
-  }
-
-  bool fromRaise;
-  bool isRefocus;
-};
-
 class nsSelectionEvent : public nsGUIEvent
 {
 private:
   friend class mozilla::dom::PBrowserParent;
   friend class mozilla::dom::PBrowserChild;
 
   nsSelectionEvent()
   {
@@ -1713,28 +1699,46 @@ public:
   }
 
   nsCOMPtr<nsIDOMDataTransfer> clipboardData;
 };
 
 /**
  * DOM UIEvent
  */
-class nsUIEvent : public nsEvent
+class nsUIEvent : public nsGUIEvent
 {
 public:
   nsUIEvent(bool isTrusted, uint32_t msg, int32_t d)
-    : nsEvent(isTrusted, msg, NS_UI_EVENT),
+    : nsGUIEvent(isTrusted, msg, nullptr, NS_UI_EVENT),
       detail(d)
   {
   }
 
   int32_t detail;
 };
 
+class nsFocusEvent : public nsUIEvent
+{
+public:
+  nsFocusEvent(bool isTrusted, uint32_t msg)
+    : nsUIEvent(isTrusted, msg, 0),
+      fromRaise(false),
+      isRefocus(false)
+  {
+    eventStructType = NS_FOCUS_EVENT;
+  }
+
+  /// The possible related target
+  nsCOMPtr<mozilla::dom::EventTarget> relatedTarget;
+
+  bool fromRaise;
+  bool isRefocus;
+};
+
 /**
  * Simple gesture event
  */
 class nsSimpleGestureEvent : public nsMouseEvent_base
 {
 public:
   nsSimpleGestureEvent(bool isTrusted, uint32_t msg, nsIWidget* w,
                          uint32_t directionArg, double deltaArg)