Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 20 Sep 2012 21:23:35 -0400
changeset 107777 488beb32bca5a1b017f2175c83d5e06d8f12b59d
parent 107705 f731fa718465e7cfc252c0acf1aeec35913d7123 (current diff)
parent 107776 3f5309a5b66eaae754ff9c6422d03a295ae72a42 (diff)
child 107778 9ae014a115b2dd3cd0864052e0e18a7f03df6677
child 107809 494304d495d82cf1929ca8d56a96ae4aef50d5d4
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
milestone18.0a1
Merge the last PGO-green inbound changeset to m-c.
docshell/base/nsDocShell.cpp
mobile/android/base/resources/menu-v11/gecko_app_menu.xml.in
mobile/android/base/resources/menu-v11/titlebar_contextmenu.xml.in
testing/mochitest/MockFilePicker.jsm
testing/mochitest/specialpowers/Makefile.in
testing/mochitest/specialpowers/chrome.manifest
testing/mochitest/specialpowers/components/SpecialPowersObserver.js
testing/mochitest/specialpowers/content/specialpowers.js
testing/mochitest/specialpowers/install.rdf
testing/mochitest/specialpowers/jar.mn
testing/mochitest/tests/SimpleTest/MozillaLogger.js
testing/mochitest/tests/SimpleTest/SpecialPowersObserverAPI.js
testing/mochitest/tests/SimpleTest/specialpowersAPI.js
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.sln
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.vcproj
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/precompile.cc
toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/precompile.h
toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h
toolkit/crashreporter/google-breakpad/src/common/linux/memory_unittest.cc
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3555,43 +3555,40 @@
 
       <handler event="dragstart"><![CDATA[
         var tab = this._getDragTargetTab(event);
         if (!tab)
           return;
 
         let dt = event.dataTransfer;
         dt.mozSetDataAt(TAB_DROP_TYPE, tab, 0);
-        let uri = this.tabbrowser.getBrowserForTab(tab).currentURI;
-        let spec = uri ? uri.spec : "about:blank";
+        let browser = tab.linkedBrowser;
 
         // We must not set text/x-moz-url or text/plain data here,
         // otherwise trying to deatch the tab by dropping it on the desktop
         // may result in an "internet shortcut"
-        dt.mozSetDataAt("text/x-moz-text-internal", spec, 0);
+        dt.mozSetDataAt("text/x-moz-text-internal", browser.currentURI.spec, 0);
 
         // Set the cursor to an arrow during tab drags.
         dt.mozCursor = "default";
 
         // Create a canvas to which we capture the current tab.
         let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
-        let browser = tab.linkedBrowser;
         canvas.mozOpaque = true;
         canvas.width = 160;
         canvas.height = 90;
         PageThumbs.captureToCanvas(browser.contentWindow, canvas);
         dt.setDragImage(canvas, -16, -16);
 
         // _dragData.offsetX/Y give the coordinates that the mouse should be
         // positioned relative to the corner of the new window created upon
         // dragend such that the mouse appears to have the same position
         // relative to the corner of the dragged tab.
         function clientX(ele) ele.getBoundingClientRect().left;
-        let tabOffsetX = clientX(tab) -
-                         clientX(this.children[0].pinned ? this.children[0] : this);
+        let tabOffsetX = clientX(tab) - clientX(this);
         tab._dragData = {
           offsetX: event.screenX - window.screenX - tabOffsetX,
           offsetY: event.screenY - window.screenY,
           scrollX: this.mTabstrip.scrollPosition,
           screenX: event.screenX
         };
 
         event.stopPropagation();
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -195,17 +195,17 @@ langpack: langpack-$(AB_CD)
 # tinderbox scripts. Alter it with caution.
 
 installers-%: clobber-% langpack-% repackage-win32-installer-% repackage-zip-%
 	@echo "repackaging done"
 
 ifdef MOZ_UPDATER
 # Note that we want updater.ini to be in the top directory, not the browser/
 # subdirectory, because that's where the updater is installed and runs.
-libs:: $(call MERGE_FILE,updater/updater.ini)
+libs:: $(call MERGE_FILE,updater/updater.ini) $(call mkdir_deps,$(DIST)/bin)
 ifeq ($(OS_ARCH),WINNT)
 	cat $< $(srcdir)/../installer/windows/nsis/updater_append.ini | \
 	  sed -e "s/^InfoText=/Info=/" -e "s/^TitleText=/Title=/" | \
 	  sed -e "s/%MOZ_APP_DISPLAYNAME%/$(MOZ_APP_DISPLAYNAME)/" > \
 	  $(DIST)/bin/updater.ini
 else
 	cat $< | \
 	  sed -e "s/^InfoText=/Info=/" -e "s/^TitleText=/Title=/" | \
@@ -231,13 +231,16 @@ merge-%:
 ifdef LOCALE_MERGEDIR
 	$(RM) -rf $(LOCALE_MERGEDIR)
 	MACOSX_DEPLOYMENT_TARGET= compare-locales -m $(LOCALE_MERGEDIR) $(srcdir)/l10n.ini $(L10NBASEDIR) $*
 endif
 	@echo
 
 # test target, depends on make package
 # try to repack x-test, with just toolkit/defines.inc being there
+l10n-check:: INNER_UNMAKE_PACKAGE=true
 l10n-check::
 	$(RM) -rf x-test
 	$(NSINSTALL) -D x-test/toolkit
 	echo "#define MOZ_LANG_TITLE Just testing" > x-test/toolkit/defines.inc
 	$(MAKE) installers-x-test L10NBASEDIR="$(PWD)" LOCALE_MERGEDIR="$(PWD)/mergedir"
+	cd $(DIST)/l10n-stage && $(UNMAKE_PACKAGE)
+	cd $(DIST)/l10n-stage && test $$(cat $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/update.locale) = x-test
new file mode 100644
--- /dev/null
+++ b/build/buildconfig.py
@@ -0,0 +1,27 @@
+# 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 imp
+import os
+import sys
+
+path = os.path.dirname(__file__)
+while not os.path.exists(os.path.join(path, 'config.status')):
+    parent = os.path.normpath(os.path.join(path, os.pardir))
+    if parent == path:
+        raise Exception("Can't find config.status")
+    path = parent
+
+path = os.path.join(path, 'config.status')
+config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE))
+
+for var in os.environ:
+    if var in config.substs:
+        config.substs[var] = os.environ[var]
+
+for var in config.__all__:
+    value = getattr(config, var)
+    if isinstance(value, list) and isinstance(value[0], tuple):
+        value = dict(value)
+    setattr(sys.modules[__name__], var, value)
--- a/build/macosx/universal/flight.mk
+++ b/build/macosx/universal/flight.mk
@@ -88,17 +88,21 @@ ifdef ENABLE_TESTS
 	$(MAKE) -C $(OBJDIR_ARCH_2) UNIVERSAL_BINARY= CHROME_JAR= package-tests
 	rm -rf $(DIST_UNI)/test-package-stage
 # automation.py differs because it hardcodes a path to
 # dist/bin. It doesn't matter which one we use.
 	if test -d $(DIST_ARCH_1)/test-package-stage -a                 \
                 -d $(DIST_ARCH_2)/test-package-stage; then              \
            cp $(DIST_ARCH_1)/test-package-stage/mochitest/automation.py \
              $(DIST_ARCH_2)/test-package-stage/mochitest/;              \
+           cp -RL $(DIST_ARCH_1)/test-package-stage/mochitest/extensions/specialpowers \
+             $(DIST_ARCH_2)/test-package-stage/mochitest/extensions/;              \
            cp $(DIST_ARCH_1)/test-package-stage/reftest/automation.py   \
              $(DIST_ARCH_2)/test-package-stage/reftest/;                \
+           cp -RL $(DIST_ARCH_1)/test-package-stage/reftest/specialpowers \
+             $(DIST_ARCH_2)/test-package-stage/reftest/;              \
            $(TOPSRCDIR)/build/macosx/universal/unify                 \
              --unify-with-sort "\.manifest$$" \
              --unify-with-sort "all-test-dirs\.list$$"               \
              $(DIST_ARCH_1)/test-package-stage                          \
              $(DIST_ARCH_2)/test-package-stage                          \
              $(DIST_UNI)/test-package-stage; fi
 endif
--- a/build/virtualenv/packages.txt
+++ b/build/virtualenv/packages.txt
@@ -7,8 +7,9 @@ mozprocess.pth:testing/mozbase/mozproces
 mozprofile.pth:testing/mozbase/mozprofile
 mozrunner.pth:testing/mozbase/mozrunner
 blessings.pth:python/blessings
 mozbuild.pth:python/mozbuild
 optional:setup.py:python/psutil:build_ext:--inplace
 optional:psutil.pth:python/psutil
 mozilla.pth:build
 mozilla.pth:config
+copy:build/buildconfig.py
--- a/build/virtualenv/populate_virtualenv.py
+++ b/build/virtualenv/populate_virtualenv.py
@@ -2,61 +2,76 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # This file contains code for populating the virtualenv environment for
 # Mozilla's build system. It is typically called as part of configure.
 
 from __future__ import with_statement
 import os
+import shutil
 import subprocess
 import sys
 import distutils.sysconfig
 
 def populate_virtualenv(top_source_directory, manifest_filename, log_handle):
     """Populate the virtualenv from the contents of a manifest.
 
     The manifest file consists of colon-delimited fields. The first field
     specifies the action. The remaining fields are arguments to that action.
     The following actions are supported:
 
       setup.py -- Invoke setup.py for a package. Expects the arguments:
         1. relative path directory containing setup.py.
         2. argument(s) to setup.py. e.g. "develop". Each program argument is
            delimited by a colon. Arguments with colons are not yet supported.
 
+      filename.pth -- Adds the path given as argument to filename.pth under
+          the virtualenv site packages directory.
+
       optional -- This denotes the action as optional. The requested action
           is attempted. If it fails, we issue a warning and go on. The initial
           "optional" field is stripped then the remaining line is processed
           like normal. e.g. "optional:setup.py:python/foo:built_ext:-i"
 
+      copy -- Copies the given file in the virtualenv site packages directory.
+
     Note that the Python interpreter running this function should be the one
     from the virtualenv. If it is the system Python or if the environment is
     not configured properly, packages could be installed into the wrong place.
     This is how virtualenv's work.
     """
     packages = []
     fh = open(manifest_filename, 'rU')
     for line in fh:
         packages.append(line.rstrip().split(':'))
     fh.close()
 
     def handle_package(package):
+        python_lib = distutils.sysconfig.get_python_lib()
         if package[0] == 'setup.py':
             assert len(package) >= 2
 
             call_setup(os.path.join(top_source_directory, package[1]),
                 package[2:])
 
             return True
 
+        if package[0] == 'copy':
+            assert len(package) == 2
+
+            shutil.copy(os.path.join(top_source_directory, package[1]),
+                        os.path.join(python_lib, os.path.basename(package[1])))
+
+            return True
+
         if package[0].endswith('.pth'):
             assert len(package) == 2
 
-            with open(os.path.join(distutils.sysconfig.get_python_lib(), package[0]), 'a') as f:
+            with open(os.path.join(python_lib, package[0]), 'a') as f:
                 f.write("%s\n" % os.path.join(top_source_directory, package[1]))
 
             return True
 
         if package[0] == 'optional':
             try:
                 handle_package(package[1:])
                 return True
--- a/config/makefiles/target_libs.mk
+++ b/config/makefiles/target_libs.mk
@@ -39,67 +39,96 @@ else
 EXPORT_LIBRARY = $(DEPTH)/staticlib
 endif
 else
 # If EXPORT_LIBRARY has a value, we'll be installing there. We also need to cleanup there
 GARBAGE += $(foreach lib,$(LIBRARY),$(EXPORT_LIBRARY)/$(lib))
 endif
 endif # EXPORT_LIBRARY
 
-libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
+libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
 ifndef NO_DIST_INSTALL
-ifdef LIBRARY
-ifdef EXPORT_LIBRARY # Stage libs that will be linked into a static build
-	$(INSTALL) $(IFLAGS1) $(LIBRARY) $(EXPORT_LIBRARY)
-endif # EXPORT_LIBRARY
-ifdef DIST_INSTALL
-ifdef IS_COMPONENT
-	$(error Shipping static component libs makes no sense.)
-else
-	$(INSTALL) $(IFLAGS1) $(LIBRARY) $(DIST)/lib
-endif
-endif # DIST_INSTALL
-endif # LIBRARY
 ifdef SHARED_LIBRARY
 ifdef IS_COMPONENT
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
 	$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
 ifndef NO_COMPONENTS_MANIFEST
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
 endif
-else # ! IS_COMPONENT
-ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
-ifndef NO_INSTALL_IMPORT_LIBRARY
-	$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
-endif
-else
-	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
-endif
-	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
 endif # IS_COMPONENT
 endif # SHARED_LIBRARY
-ifdef PROGRAM
-	$(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
-endif
-ifdef SIMPLE_PROGRAMS
-	$(INSTALL) $(IFLAGS2) $(SIMPLE_PROGRAMS) $(FINAL_TARGET)
-endif
-ifdef HOST_PROGRAM
-	$(INSTALL) $(IFLAGS2) $(HOST_PROGRAM) $(DIST)/host/bin
-endif
-ifdef HOST_SIMPLE_PROGRAMS
-	$(INSTALL) $(IFLAGS2) $(HOST_SIMPLE_PROGRAMS) $(DIST)/host/bin
-endif
-ifdef HOST_LIBRARY
-	$(INSTALL) $(IFLAGS1) $(HOST_LIBRARY) $(DIST)/host/lib
-endif
-ifdef JAVA_LIBRARY
-ifdef IS_COMPONENT
-	$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)/components
-else
-	$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)
-endif
-endif # JAVA_LIBRARY
 endif # !NO_DIST_INSTALL
 	$(LOOP_OVER_DIRS)
 
+ifndef NO_DIST_INSTALL
+
+ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
+PROGRAMS_EXECUTABLES = $(SIMPLE_PROGRAMS) $(PROGRAM)
+PROGRAMS_DEST ?= $(FINAL_TARGET)
+INSTALL_TARGETS += PROGRAMS
+endif
+
+ifdef LIBRARY
+ifdef EXPORT_LIBRARY
+LIBRARY_FILES = $(LIBRARY)
+LIBRARY_DEST ?= $(EXPORT_LIBRARY)
+INSTALL_TARGETS += LIBRARY
+endif
+ifdef DIST_INSTALL
+ifdef IS_COMPONENT
+$(error Shipping static component libs makes no sense.)
+else
+DIST_LIBRARY_FILES = $(LIBRARY)
+DIST_LIBRARY_DEST ?= $(DIST)/lib
+INSTALL_TARGETS += DIST_LIBRARY
+endif
+endif # DIST_INSTALL
+endif # LIBRARY
+
+
+ifdef SHARED_LIBRARY
+ifndef IS_COMPONENT
+SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
+SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
+INSTALL_TARGETS += SHARED_LIBRARY
+
+ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
+ifndef NO_INSTALL_IMPORT_LIBRARY
+IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
+endif # NO_INSTALL_IMPORT_LIBRARY
+else
+IMPORT_LIB_FILES = $(SHARED_LIBRARY)
+endif
+
+IMPORT_LIB_DEST ?= $(DIST)/lib
+ifdef IMPORT_LIB_FILES
+INSTALL_TARGETS += IMPORT_LIB
+endif
+
+endif # ! IS_COMPONENT
+endif # SHARED_LIBRARY
+
+ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)$(HOST_PROGRAM)))
+HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_PROGRAM)
+HOST_PROGRAMS_DEST ?= $(DIST)/host/bin
+INSTALL_TARGETS += HOST_PROGRAMS
+endif
+
+ifdef HOST_LIBRARY
+HOST_LIBRARY_FILES = $(HOST_LIBRARY)
+HOST_LIBRARY_DEST ?= $(DIST)/host/lib
+INSTALL_TARGETS += HOST_LIBRARY
+endif
+
+ifdef JAVA_LIBRARY
+JAVA_LIBRARY_FILES = $(JAVA_LIBRARY)
+ifdef IS_COMPONENT
+JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)/components
+else
+JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)
+endif
+INSTALL_TARGETS += JAVA_LIBRARY
+endif
+
+endif # !NO_DIST_INSTALL
+
 # EOF
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -57,22 +57,16 @@ else
   ELOG :=
 endif # -s
 else
   ELOG :=
 endif # ifndef .PYMAKE
 
 _VPATH_SRCS = $(abspath $<)
 
-# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
-VPATH += $(DIST)/lib
-ifdef LIBXUL_SDK
-VPATH += $(LIBXUL_SDK)/lib
-endif
-
 ifdef EXTRA_DSO_LIBS
 EXTRA_DSO_LIBS	:= $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
 endif
 
 ################################################################################
 # Testing frameworks support
 ################################################################################
 
@@ -1604,19 +1598,16 @@ endif
 .PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE
 
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
-# Properly set LIBPATTERNS for the platform
-.LIBPATTERNS = $(if $(IMPORT_LIB_SUFFIX),$(LIB_PREFIX)%.$(IMPORT_LIB_SUFFIX)) $(LIB_PREFIX)%.$(LIB_SUFFIX) $(DLL_PREFIX)%$(DLL_SUFFIX)
-
 tags: TAGS
 
 TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	-etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 
 ifndef INCLUDED_DEBUGMAKE_MK #{
--- a/config/version_win.pl
+++ b/config/version_win.pl
@@ -229,17 +229,17 @@ for ($j = 1; $j < 4; $j++)
         $appver[$j] = "0";
     }
     else {
         $appver[$j] =~s/\D.*$//;
     }
 }
 my $winappversion = "$appver[0],$appver[1],$appver[2],$appver[3]";
 
-my $copyright = "License: MPL 1.1/GPL 2.0/LGPL 2.1";
+my $copyright = "License: MPL 2";
 my $company = "Mozilla Foundation";
 my $trademarks = "Mozilla";
 my $productname = $displayname;
 
 
 if (defined($override_comment)){$override_comment =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $comment=$override_comment;}
 if (defined($override_description)){$override_description =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $description=$override_description;}
 if (defined($override_fileversion)){$override_fileversion =~ s/\@MOZ_APP_WINVERSION\@/$winappversion/g; $fileversion=$override_fileversion;}
--- a/content/base/src/nsDataDocumentContentPolicy.cpp
+++ b/content/base/src/nsDataDocumentContentPolicy.cpp
@@ -57,18 +57,21 @@ nsDataDocumentContentPolicy::ShouldLoad(
 
   // DTDs are always OK to load
   if (!doc || aContentType == nsIContentPolicy::TYPE_DTD) {
     return NS_OK;
   }
 
   // Nothing else is OK to load for data documents
   if (doc->IsLoadedAsData()) {
-    *aDecision = nsIContentPolicy::REJECT_TYPE;
-    return NS_OK;
+    // ...but let static (print/print preview) documents to load fonts.
+    if (!doc->IsStaticDocument() || aContentType != nsIContentPolicy::TYPE_FONT) {
+      *aDecision = nsIContentPolicy::REJECT_TYPE;
+      return NS_OK;
+    }
   }
 
   if (doc->IsBeingUsedAsImage()) {
     // We only allow SVG images to load content from URIs that are local and
     // also satisfy one of the following conditions:
     //  - URI inherits security context, e.g. data URIs
     //   OR
     //  - URI loadable by subsumers, e.g. blob URIs
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -122,16 +122,17 @@
 #include "nsIJSContextStack.h"
 #include "nsIXPConnect.h"
 #include "nsCycleCollector.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsICategoryManager.h"
 #include "nsIDocumentLoaderFactory.h"
+#include "nsIDocumentLoader.h"
 #include "nsIContentViewer.h"
 #include "nsIXMLContentSink.h"
 #include "nsIXULDocument.h"
 #include "nsIPrompt.h"
 #include "nsIPropertyBag2.h"
 #include "nsIDOMPageTransitionEvent.h"
 #include "nsFrameLoader.h"
 #include "nsEscape.h"
@@ -7623,18 +7624,25 @@ nsDocument::CloneDocHelper(nsDocument* c
 
   // Set URI/principal
   clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
   // Must set the principal first, since SetBaseURI checks it.
   clone->SetPrincipal(NodePrincipal());
   clone->mDocumentBaseURI = mDocumentBaseURI;
 
   if (mCreatingStaticClone) {
+    nsCOMPtr<nsILoadGroup> loadGroup;
+    
+    // |mDocumentContainer| is the container of the document that is being
+    // created and not the original container. See CreateStaticClone function().
+    nsCOMPtr<nsIDocumentLoader> docLoader = do_QueryReferent(mDocumentContainer);
+    if (docLoader) {
+      docLoader->GetLoadGroup(getter_AddRefs(loadGroup));
+    }
     nsCOMPtr<nsIChannel> channel = GetChannel();
-    nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
     if (channel && loadGroup) {
       clone->Reset(channel, loadGroup);
     } else {
       nsIURI* uri = static_cast<const nsIDocument*>(this)->GetDocumentURI();
       if (uri) {
         clone->ResetToURI(uri, loadGroup, NodePrincipal());
       }
     }
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -8670,25 +8670,27 @@ nsDocShell::InternalLoad(nsIURI * aURI,
         // that history.go(0) and the like trigger full refreshes, rather than
         // short-circuited loads.
         bool doShortCircuitedLoad =
           (historyNavBetweenSameDoc && mOSHE != aSHEntry) ||
           (!aSHEntry && aPostData == nullptr &&
            sameExceptHashes && !newHash.IsEmpty());
 
         if (doShortCircuitedLoad) {
-            // Cancel any outstanding loads if this is a history load.
+            // Cancel an outstanding new-document load if this is a history
+            // load.
             //
-            // We can't cancel the oustanding load unconditionally, because if a page does
+            // We can't cancel the oustanding load unconditionally, because if a
+            // page does
             //   - load a.html
             //   - start loading b.html
             //   - load a.html#h
             // we break the web if we cancel the load of b.html.
-            if (aSHEntry) {
-                Stop(nsIWebNavigation::STOP_NETWORK);
+            if (aSHEntry && mDocumentRequest) {
+                mDocumentRequest->Cancel(NS_BINDING_ABORTED);
             }
 
             // Save the current URI; we need it if we fire a hashchange later.
             nsCOMPtr<nsIURI> oldURI = mCurrentURI;
 
             // Save the position of the scrollers.
             nscoord cx = 0, cy = 0;
             GetCurScrollPos(ScrollOrientation_X, &cx);
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -157,17 +157,17 @@ class BluetoothService::ToggleBtTask : p
 {
 public:
   ToggleBtTask(bool aEnabled)
     : mEnabled(aEnabled)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
-  NS_IMETHOD Run() 
+  NS_IMETHOD Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
     if (mEnabled) {
       if (NS_FAILED(gBluetoothService->StartInternal())) {
         NS_WARNING("Bluetooth service failed to start!");
         mEnabled = !mEnabled;
       }
@@ -729,18 +729,18 @@ void
 BluetoothService::Notify(const BluetoothSignal& aData)
 {
   InfallibleTArray<BluetoothNamedValue> arr = aData.value().get_ArrayOfBluetoothNamedValue();
   nsString type;
 
   JSContext* cx = nsContentUtils::GetSafeJSContext();
   NS_ASSERTION(!::JS_IsExceptionPending(cx),
                "Shouldn't get here when an exception is pending!");
-  
-  JSAutoRequest jsar(cx);  
+
+  JSAutoRequest jsar(cx);
   JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
   if (!obj) {
     NS_WARNING("Failed to new JSObject for system message!");
     return;
   }
 
   bool ok = SetJsObject(cx, obj, arr);
   if (!ok) {
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -247,16 +247,19 @@ public:
   virtual bool
   SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
                                  BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual bool
   SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
                            BluetoothReplyRunnable* aRunnable) = 0;
 
+  virtual nsresult
+  PrepareAdapterInternal(const nsAString& aPath) = 0;
+
   bool
   IsEnabled() const
   {
     return mEnabled;
   }
 
 protected:
   BluetoothService()
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -121,17 +121,17 @@ BluetoothServiceChildProcess::GetPairedD
 
   SendRequest(aRunnable, request);
   return NS_OK;
 }
 
 nsresult
 BluetoothServiceChildProcess::StopDiscoveryInternal(
                                               const nsAString& aAdapterPath,
-                                              BluetoothReplyRunnable* aRunnable) 
+                                              BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable, StopDiscoveryRequest(nsString(aAdapterPath)));
   return NS_OK;
 }
 
 nsresult
 BluetoothServiceChildProcess::StartDiscoveryInternal(
                                               const nsAString& aAdapterPath,
@@ -273,16 +273,23 @@ BluetoothServiceChildProcess::SetAuthori
   } else {
     SendRequest(aRunnable,
                 DenyAuthorizationRequest(nsString(aDeviceAddress)));
   }
   return NS_OK;
 }
 
 nsresult
+BluetoothServiceChildProcess::PrepareAdapterInternal(const nsAString& aPath)
+{
+  MOZ_NOT_REACHED("Should never be called from child");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
 BluetoothServiceChildProcess::HandleStartup()
 {
   // Don't need to do anything here for startup since our Create function takes
   // care of the actor machinery.
   return NS_OK;
 }
 
 nsresult
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -140,14 +140,16 @@ private:
   virtual nsresult
   StopInternal() MOZ_OVERRIDE;
 
   // Should never be called from the child
   virtual nsresult
   GetDevicePropertiesInternal(const nsAString& aDevicePath,
                               const nsAString& aSignalPath) MOZ_OVERRIDE;
 
-
+  // This method should never be called from the child.
+  virtual nsresult
+  PrepareAdapterInternal(const nsAString& aPath) MOZ_OVERRIDE;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif // mozilla_dom_bluetooth_ipc_bluetoothservicechildprocess_h__
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -135,17 +135,17 @@ static const char* sBluetoothDBusSignals
   "type='signal',interface='org.bluez.NetworkServer'",
   "type='signal',interface='org.bluez.HealthDevice'",
   "type='signal',interface='org.bluez.AudioSink'"
 };
 
 /**
  * DBus Connection held for the BluetoothCommandThread to use. Should never be
  * used by any other thread.
- * 
+ *
  */
 static nsAutoPtr<RawDBusConnection> gThreadConnection;
 static nsDataHashtable<nsStringHashKey, DBusMessage* > sPairingReqTable;
 static nsDataHashtable<nsStringHashKey, DBusMessage* > sAuthorizeReqTable;
 static nsString sDefaultAdapterPath;
 static nsTArray<uint32_t> sServiceHandles;
 
 typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
@@ -198,25 +198,58 @@ public:
       NS_WARNING("BluetoothService not available!");
       return NS_ERROR_FAILURE;
     }
     bs->DistributeSignal(mSignal);
     return NS_OK;
   }
 };
 
+class PrepareAdapterTask : public nsRunnable {
+public:
+  PrepareAdapterTask(const nsAString& aPath) :
+    mPath(aPath)
+  {
+  }
+
+  NS_IMETHOD
+  Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    BluetoothService* bs = BluetoothService::Get();
+    if (!bs) {
+      NS_WARNING("BluetoothService not available!");
+      return NS_ERROR_FAILURE;
+    }
+
+    // Due to the fact that we need to queue the dbus call to the command thread
+    // inside the bluetoothservice, we have to route the call down to the main
+    // thread and then back out to the command thread. There has to be a better
+    // way to do this.
+    if (NS_FAILED(bs->PrepareAdapterInternal(mPath))) {
+      NS_WARNING("prepare adapter failed");
+      return NS_ERROR_FAILURE;
+    }
+    return NS_OK;
+  }
+
+private:
+  nsString mPath;
+};
+
 static bool
 IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
 {
   if (aErr && dbus_error_is_set(aErr)) {
     aErrorStr = NS_ConvertUTF8toUTF16(aErr->message);
     LOG_AND_FREE_DBUS_ERROR(aErr);
     return true;
   }
-  
+
   DBusError err;
   dbus_error_init(&err);
   if (dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_ERROR) {
     const char* error_msg;
     if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_STRING,
                                &error_msg, DBUS_TYPE_INVALID) ||
         !error_msg) {
       if (dbus_error_is_set(&err)) {
@@ -243,17 +276,17 @@ DispatchBluetoothReply(BluetoothReplyRun
   BluetoothReply* reply;
   if (!aErrorStr.IsEmpty()) {
     nsString err(aErrorStr);
     reply = new BluetoothReply(BluetoothReplyError(err));
   } else {
     MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
     reply = new BluetoothReply(BluetoothReplySuccess(aValue));
   }
-  
+
   aRunnable->SetReply(reply);
   if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
     NS_WARNING("Failed to dispatch to main thread!");
   }
 }
 
 static void
 UnpackIntMessage(DBusMessage* aMsg, DBusError* aErr,
@@ -300,17 +333,17 @@ UnpackObjectPathMessage(DBusMessage* aMs
   }
 }
 
 static void
 KeepDBusPairingMessage(const nsString& aDeviceAddress, DBusMessage* aMsg)
 {
   sPairingReqTable.Put(aDeviceAddress, aMsg);
 
-  // Increase ref count here because we need this message later. 
+  // Increase ref count here because we need this message later.
   // It'll be unrefed when set*Internal() is called.
   dbus_message_ref(aMsg);
 }
 
 static DBusHandlerResult
 AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data)
 {
   if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
@@ -362,22 +395,22 @@ AgentEventFilter(DBusConnection *conn, D
       parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("deviceAddress"), deviceAddress));
       parameters.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("uuid"),
                                                    NS_ConvertUTF8toUTF16(uuid)));
 
       // Because we may have authorization request and pairing request from the
       // same remote device at the same time, we need two tables to keep these messages.
       sAuthorizeReqTable.Put(deviceAddress, msg);
 
-      // Increase ref count here because we need this message later. 
+      // Increase ref count here because we need this message later.
       // It'll be unrefed when setAuthorizationInternal() is called.
       dbus_message_ref(msg);
 
       v = parameters;
-    }  
+    }
   } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "RequestConfirmation")) {
     // This method gets called when the service daemon needs to confirm a passkey for
     // an authentication.
     char *objectPath;
     uint32_t passkey;
     if (!dbus_message_get_args(msg, NULL,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_UINT32, &passkey,
@@ -527,28 +560,28 @@ RegisterLocalAgent(const char* adapterPa
         LOG_AND_FREE_DBUS_ERROR(&err);
         LOG("%s: Can't register agent!", __FUNCTION__);
         return false;
       }
     }
   } else {
     dbus_message_unref(reply);
   }
-  
+
   dbus_connection_flush(gThreadConnection->GetConnection());
   return true;
 }
 
 static bool
 RegisterAgent(const nsAString& aAdapterPath)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
-  if (!RegisterLocalAgent(NS_ConvertUTF16toUTF8(aAdapterPath).get(), 
-                          LOCAL_AGENT_PATH, 
+  if (!RegisterLocalAgent(NS_ConvertUTF16toUTF8(aAdapterPath).get(),
+                          LOCAL_AGENT_PATH,
                           B2G_AGENT_CAPABILITIES)) {
     return false;
   }
 
   // There is no "RegisterAgent" function defined in device interface.
   // When we call "CreatePairedDevice", it will do device agent registration for us.
   // (See maemo.org/api_refs/5.0/beta/bluez/adapter.html)
   if (!dbus_connection_register_object_path(gThreadConnection->GetConnection(),
@@ -560,29 +593,103 @@ RegisterAgent(const nsAString& aAdapterP
 
     return false;
   }
 
   return true;
 }
 
 static void
-AddReservedServices(const nsAString& aAdapterPath)
+ExtractHandles(DBusMessage *aReply, nsTArray<uint32_t>& aOutHandles)
+{
+  uint32_t* handles = NULL;
+  int len;
+
+  DBusError err;
+  dbus_error_init(&err);
+
+  if (dbus_message_get_args(aReply, &err,
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len,
+                            DBUS_TYPE_INVALID)) {
+     if (!handles) {
+       LOG("Null array in extract_handles");
+     } else {
+        for (int i = 0; i < len; ++i) {
+        aOutHandles.AppendElement(handles[i]);
+      }
+    }
+  } else {
+    LOG_AND_FREE_DBUS_ERROR(&err);
+  }
+}
+
+// static
+bool
+BluetoothDBusService::AddReservedServicesInternal(const nsAString& aAdapterPath,
+                                                  const nsTArray<uint32_t>& aServices,
+                                                  nsTArray<uint32_t>& aServiceHandlesContainer)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
-  nsTArray<uint32_t> uuids;
+  int length = aServices.Length();
+  if (length == 0) return false;
 
-  uuids.AppendElement((uint32_t)(BluetoothServiceUuid::HandsfreeAG >> 32));
-  uuids.AppendElement((uint32_t)(BluetoothServiceUuid::HeadsetAG >> 32));
+  const uint32_t* services = aServices.Elements();
+  DBusMessage* reply =
+    dbus_func_args(gThreadConnection->GetConnection(),
+                   NS_ConvertUTF16toUTF8(aAdapterPath).get(),
+                   DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
+                   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
+                   &services, length, DBUS_TYPE_INVALID);
+
+  if (!reply) {
+    LOG("Null DBus message. Couldn't extract handles.");
+    return false;
+  }
+
+  ExtractHandles(reply, aServiceHandlesContainer);
+  return true;
+}
 
-  sServiceHandles.Clear();
-  BluetoothDBusService::AddReservedServicesInternal(aAdapterPath, uuids,
-                                                    sServiceHandles);
-}
+class PrepareAdapterRunnable : public nsRunnable
+{
+public:
+  PrepareAdapterRunnable(const nsAString& aPath) :
+    mPath(aPath)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  NS_IMETHOD
+  Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    nsTArray<uint32_t> uuids;
+
+    uuids.AppendElement((uint32_t)(BluetoothServiceUuid::HandsfreeAG >> 32));
+    uuids.AppendElement((uint32_t)(BluetoothServiceUuid::HeadsetAG >> 32));
+
+    sServiceHandles.Clear();
+    if (!BluetoothDBusService::AddReservedServicesInternal(mPath, uuids, sServiceHandles)) {
+      NS_WARNING("Failed to add reserved services");
+      return NS_ERROR_FAILURE;
+    }
+
+    if(!RegisterAgent(mPath)) {
+      NS_WARNING("Failed to register agent");
+      return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+  }
+
+private:
+  nsString mPath;
+};
 
 void
 RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
                 UnpackFunc aFunc)
 {
 #ifdef MOZ_WIDGET_GONK
   // Due to the fact that we're running two dbus loops on desktop implicitly by
   // being gtk based, sometimes we'll get signals/reply coming in on the main
@@ -593,17 +700,17 @@ RunDBusCallback(DBusMessage* aMsg, void*
   nsRefPtr<BluetoothReplyRunnable> replyRunnable =
     dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
 
   NS_ASSERTION(replyRunnable, "Callback reply runnable is null!");
 
   nsString replyError;
   BluetoothValue v;
   aFunc(aMsg, nullptr, v, replyError);
-  DispatchBluetoothReply(replyRunnable, v, replyError);  
+  DispatchBluetoothReply(replyRunnable, v, replyError);
 }
 
 void
 GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
 {
   RunDBusCallback(aMsg, aBluetoothReplyRunnable,
                   UnpackObjectPathMessage);
 }
@@ -647,29 +754,29 @@ GetProperty(DBusMessageIter aIter, Prope
             int aPropertyTypeLen, int* aPropIndex,
             InfallibleTArray<BluetoothNamedValue>& aProperties)
 {
   DBusMessageIter prop_val, array_val_iter;
   char* property = NULL;
   uint32_t array_type;
   int i, type;
 
-  if (dbus_message_iter_get_arg_type(&aIter) != DBUS_TYPE_STRING) {    
+  if (dbus_message_iter_get_arg_type(&aIter) != DBUS_TYPE_STRING) {
     return false;
   }
 
   dbus_message_iter_get_basic(&aIter, &property);
 
   if (!dbus_message_iter_next(&aIter) ||
       dbus_message_iter_get_arg_type(&aIter) != DBUS_TYPE_VARIANT) {
     return false;
   }
 
   for (i = 0; i < aPropertyTypeLen; i++) {
-    if (!strncmp(property, aPropertyTypes[i].name, strlen(property))) {      
+    if (!strncmp(property, aPropertyTypes[i].name, strlen(property))) {
       break;
     }
   }
 
   if (i == aPropertyTypeLen) {
     return false;
   }
 
@@ -687,17 +794,17 @@ GetProperty(DBusMessageIter aIter, Prope
     str += NS_ConvertUTF16toUTF8(propertyName);
     str += " Property Type Expected: ;";
     str += type;
     str += " Property Type Received: ";
     str += dbus_message_iter_get_arg_type(&prop_val);
     NS_WARNING(str.get());
     return false;
   }
-  
+
   BluetoothValue propertyValue;
   switch (type) {
     case DBUS_TYPE_STRING:
     case DBUS_TYPE_OBJECT_PATH:
       const char* c;
       dbus_message_iter_get_basic(&prop_val, &c);
       propertyValue = NS_ConvertUTF8toUTF16(c);
       break;
@@ -745,17 +852,17 @@ GetProperty(DBusMessageIter aIter, Prope
       break;
     default:
       NS_NOTREACHED("Cannot find dbus message type!");
   }
   aProperties.AppendElement(BluetoothNamedValue(propertyName, propertyValue));
   return true;
 }
 
-void 
+void
 ParseProperties(DBusMessageIter* aIter,
                 BluetoothValue& aValue,
                 nsAString& aErrorStr,
                 Properties* aPropertyTypes,
                 const int aPropertyTypeLen)
 {
   DBusMessageIter dict_entry, dict;
   int prop_index = -1;
@@ -864,23 +971,23 @@ void
 ParsePropertyChange(DBusMessage* aMsg, BluetoothValue& aValue,
                     nsAString& aErrorStr, Properties* aPropertyTypes,
                     const int aPropertyTypeLen)
 {
   DBusMessageIter iter;
   DBusError err;
   int prop_index = -1;
   InfallibleTArray<BluetoothNamedValue> props;
-  
+
   dbus_error_init(&err);
   if (!dbus_message_iter_init(aMsg, &iter)) {
     NS_WARNING("Can't create iterator!");
     return;
   }
-    
+
   if (!GetProperty(iter, aPropertyTypes, aPropertyTypeLen,
                    &prop_index, props)) {
     NS_WARNING("Can't get property!");
     aErrorStr.AssignLiteral("Can't get property!");
     return;
   }
   aValue = props;
 }
@@ -962,49 +1069,49 @@ private:
 
 // Called by dbus during WaitForAndDispatchEventNative()
 // This function is called on the IOThread
 static
 DBusHandlerResult
 EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Shouldn't be called from Main Thread!");
-  
+
   if (dbus_message_get_type(aMsg) != DBUS_MESSAGE_TYPE_SIGNAL) {
     LOG("%s: event handler not interested in %s (not a signal).\n",
         __FUNCTION__, dbus_message_get_member(aMsg));
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-  }  
+  }
 
   if (dbus_message_get_path(aMsg) == NULL) {
     LOG("DBusMessage %s has no bluetooth destination, ignoring\n",
         dbus_message_get_member(aMsg));
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
   DBusError err;
   nsString signalPath;
   nsString signalName;
   dbus_error_init(&err);
   signalPath = NS_ConvertUTF8toUTF16(dbus_message_get_path(aMsg));
   signalName = NS_ConvertUTF8toUTF16(dbus_message_get_member(aMsg));
   nsString errorStr;
   BluetoothValue v;
-  
+
   if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceFound")) {
     DBusMessageIter iter;
 
     if (!dbus_message_iter_init(aMsg, &iter)) {
       NS_WARNING("Can't create iterator!");
       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
 
     const char* addr;
     dbus_message_iter_get_basic(&iter, &addr);
-    
+
     if (dbus_message_iter_next(&iter)) {
       ParseProperties(&iter,
                       v,
                       errorStr,
                       sDeviceProperties,
                       ArrayLength(sDeviceProperties));
       if (v.type() == BluetoothValue::TArrayOfBluetoothNamedValue)
       {
@@ -1066,33 +1173,38 @@ EventFilter(DBusConnection* aConn, DBusM
                         ArrayLength(sAdapterProperties));
   } else if (dbus_message_is_signal(aMsg, DBUS_DEVICE_IFACE, "PropertyChanged")) {
     ParsePropertyChange(aMsg,
                         v,
                         errorStr,
                         sDeviceProperties,
                         ArrayLength(sDeviceProperties));
     if (v.get_ArrayOfBluetoothNamedValue()[0].name().EqualsLiteral("Paired")) {
-      // transfer signal to BluetoothService and 
+      // transfer signal to BluetoothService and
       // broadcast system message of bluetooth-pairingstatuschanged
-      signalName = NS_LITERAL_STRING("PairedStatusChagned");
+      signalName = NS_LITERAL_STRING("PairedStatusChanged");
       signalPath = NS_LITERAL_STRING(LOCAL_AGENT_PATH);
       v.get_ArrayOfBluetoothNamedValue()[0].name() = NS_LITERAL_STRING("paired");
     }
   } else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE, "AdapterAdded")) {
     const char* str;
     if (!dbus_message_get_args(aMsg, &err,
                                DBUS_TYPE_OBJECT_PATH, &str,
                                DBUS_TYPE_INVALID)) {
       LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
       errorStr.AssignLiteral("Cannot parse manager path!");
     } else {
       sDefaultAdapterPath = NS_ConvertUTF8toUTF16(str);
-      AddReservedServices(sDefaultAdapterPath);
       v = sDefaultAdapterPath;
+
+      nsRefPtr<PrepareAdapterTask> b =
+        new PrepareAdapterTask(sDefaultAdapterPath);
+      if (NS_FAILED(NS_DispatchToMainThread(b))) {
+        NS_WARNING("Failed to dispatch to main thread!");
+      }
     }
   } else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE, "PropertyChanged")) {
     ParsePropertyChange(aMsg,
                         v,
                         errorStr,
                         sManagerProperties,
                         ArrayLength(sManagerProperties));
   } else {
@@ -1106,49 +1218,49 @@ EventFilter(DBusConnection* aConn, DBusM
   }
 
   if (!errorStr.IsEmpty()) {
     NS_WARNING(NS_ConvertUTF16toUTF8(errorStr).get());
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
   BluetoothSignal signal(signalName, signalPath, v);
-  
+
   nsRefPtr<DistributeBluetoothSignalTask>
     t = new DistributeBluetoothSignalTask(signal);
   if (NS_FAILED(NS_DispatchToMainThread(t))) {
     NS_WARNING("Failed to dispatch to main thread!");
   }
 
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
 nsresult
 BluetoothDBusService::StartInternal()
 {
   // This could block. It should never be run on the main thread.
   MOZ_ASSERT(!NS_IsMainThread());
-  
+
   if (!StartDBus()) {
     NS_WARNING("Cannot start DBus thread!");
     return NS_ERROR_FAILURE;
   }
-  
+
   if (mConnection) {
     return NS_OK;
   }
 
   if (NS_FAILED(EstablishDBusConnection())) {
     NS_WARNING("Cannot start Main Thread DBus connection!");
     StopDBus();
     return NS_ERROR_FAILURE;
   }
 
   gThreadConnection = new RawDBusConnection();
-  
+
   if (NS_FAILED(gThreadConnection->EstablishDBusConnection())) {
     NS_WARNING("Cannot start Sync Thread DBus connection!");
     StopDBus();
     return NS_ERROR_FAILURE;
   }
 
   DBusError err;
   dbus_error_init(&err);
@@ -1187,17 +1299,17 @@ UnrefDBusMessages(const nsAString& key, 
   return PL_DHASH_NEXT;
 }
 
 nsresult
 BluetoothDBusService::StopInternal()
 {
   // This could block. It should never be run on the main thread.
   MOZ_ASSERT(!NS_IsMainThread());
-  
+
   if (!mConnection) {
     StopDBus();
     return NS_OK;
   }
 
   DBusError err;
   dbus_error_init(&err);
   for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
@@ -1205,17 +1317,29 @@ BluetoothDBusService::StopInternal()
                           sBluetoothDBusSignals[i],
                           &err);
     if (dbus_error_is_set(&err)) {
       LOG_AND_FREE_DBUS_ERROR(&err);
     }
   }
 
   dbus_connection_remove_filter(mConnection, EventFilter, nullptr);
-  
+
+  if (!dbus_connection_unregister_object_path(gThreadConnection->GetConnection(),
+                                              LOCAL_AGENT_PATH)) {
+    LOG("%s: Can't unregister object path %s for agent!",
+        __FUNCTION__, LOCAL_AGENT_PATH);
+  }
+
+  if (!dbus_connection_unregister_object_path(gThreadConnection->GetConnection(),
+                                              REMOTE_AGENT_PATH)) {
+    LOG("%s: Can't unregister object path %s for agent!",
+        __FUNCTION__, LOCAL_AGENT_PATH);
+  }
+
   mConnection = nullptr;
   gThreadConnection = nullptr;
   mBluetoothSignalObserverTable.Clear();
 
   // unref stored DBusMessages before clear the hashtable
   sPairingReqTable.EnumerateRead(UnrefDBusMessages, nullptr);
   sPairingReqTable.Clear();
 
@@ -1235,17 +1359,17 @@ public:
   }
 
   nsresult
   Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
     DBusError err;
     dbus_error_init(&err);
-   
+
     BluetoothValue v;
     nsString replyError;
 
     DBusMessage* msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
                                               1000,
                                               &err,
                                               "/",
                                               DBUS_MANAGER_IFACE,
@@ -1258,42 +1382,40 @@ public:
     if (!replyError.IsEmpty()) {
       DispatchBluetoothReply(mRunnable, v, replyError);
       return NS_ERROR_FAILURE;
     }
 
     nsString path = v.get_nsString();
     nsCString tmp_path = NS_ConvertUTF16toUTF8(path);
     const char* object_path = tmp_path.get();
-   
+
     v = InfallibleTArray<BluetoothNamedValue>();
     msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
                                  1000,
                                  &err,
                                  object_path,
                                  "org.bluez.Adapter",
                                  "GetProperties",
                                  DBUS_TYPE_INVALID);
     UnpackAdapterPropertiesMessage(msg, &err, v, replyError);
-   
+
     if (!replyError.IsEmpty()) {
       DispatchBluetoothReply(mRunnable, v, replyError);
       return NS_ERROR_FAILURE;
     }
     if (msg) {
       dbus_message_unref(msg);
     }
     // We have to manually attach the path to the rest of the elements
     v.get_ArrayOfBluetoothNamedValue().AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Path"),
                                                                          path));
 
-    RegisterAgent(path);
+    DispatchBluetoothReply(mRunnable, v, replyError);
 
-    DispatchBluetoothReply(mRunnable, v, replyError);
-   
     return NS_OK;
   }
 
 private:
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
 };
 
 nsresult
@@ -1348,17 +1470,17 @@ BluetoothDBusService::StopDiscoveryInter
                                             BluetoothReplyRunnable* aRunnable)
 {
   if (!mConnection) {
     NS_WARNING("Bluetooth service not started yet, no need to stop discovery.");
     return NS_OK;
   }
   return SendDiscoveryMessage(aAdapterPath, "StopDiscovery", aRunnable);
 }
- 
+
 nsresult
 BluetoothDBusService::StartDiscoveryInternal(const nsAString& aAdapterPath,
                                              BluetoothReplyRunnable* aRunnable)
 {
   if (!mConnection) {
     NS_WARNING("Bluetooth service not started yet, cannot start discovery!");
     return NS_ERROR_FAILURE;
   }
@@ -1476,20 +1598,20 @@ nsresult
 BluetoothDBusService::GetProperties(BluetoothObjectType aType,
                                     const nsAString& aPath,
                                     BluetoothReplyRunnable* aRunnable)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
 
   MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
   MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusPropCallbacks));
-  
+
   const char* interface = sBluetoothDBusIfaces[aType];
   DBusCallback callback = sBluetoothDBusPropCallbacks[aType];
-  
+
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
   if (!dbus_func_args_async(mConnection,
                             1000,
                             callback,
                             (void*)aRunnable,
                             NS_ConvertUTF16toUTF8(aPath).get(),
                             interface,
@@ -1564,17 +1686,17 @@ BluetoothDBusService::SetProperty(Blueto
     return NS_ERROR_FAILURE;
   }
 
   const char* propName = NS_ConvertUTF16toUTF8(aValue.name()).get();
   if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &propName, DBUS_TYPE_INVALID)) {
     NS_WARNING("Couldn't append arguments to dbus message!");
     return NS_ERROR_FAILURE;
   }
-  
+
   int type;
   int tmp_int;
   void* val;
   nsCString str;
   if (aValue.value().type() == BluetoothValue::Tuint32_t) {
     tmp_int = aValue.value().get_uint32_t();
     val = &tmp_int;
     type = DBUS_TYPE_UINT32;
@@ -1587,30 +1709,30 @@ BluetoothDBusService::SetProperty(Blueto
     tmp_int = aValue.value().get_bool() ? 1 : 0;
     val = &(tmp_int);
     type = DBUS_TYPE_BOOLEAN;
   } else {
     NS_WARNING("Property type not handled!");
     dbus_message_unref(msg);
     return NS_ERROR_FAILURE;
   }
-  
+
   DBusMessageIter value_iter, iter;
   dbus_message_iter_init_append(msg, &iter);
   char var_type[2] = {(char)type, '\0'};
   if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, var_type, &value_iter) ||
       !dbus_message_iter_append_basic(&value_iter, type, val) ||
       !dbus_message_iter_close_container(&iter, &value_iter)) {
     NS_WARNING("Could not append argument to method call!");
     dbus_message_unref(msg);
     return NS_ERROR_FAILURE;
   }
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
-  // msg is unref'd as part of dbus_func_send_async 
+  // msg is unref'd as part of dbus_func_send_async
   if (!dbus_func_send_async(mConnection,
                             msg,
                             1000,
                             GetVoidCallback,
                             (void*)aRunnable)) {
     NS_WARNING("Could not start async function!");
     return NS_ERROR_FAILURE;
   }
@@ -1644,68 +1766,16 @@ GetDeviceServiceChannel(const nsAString&
                    DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
                    DBUS_TYPE_STRING, &pattern,
                    DBUS_TYPE_UINT16, &aAttributeId,
                    DBUS_TYPE_INVALID);
 
   return reply ? dbus_returns_int32(reply) : -1;
 }
 
-static void
-ExtractHandles(DBusMessage *aReply, nsTArray<uint32_t>& aOutHandles)
-{
-  uint32_t* handles = NULL;
-  int len;
-
-  DBusError err;
-  dbus_error_init(&err);
-
-  if (dbus_message_get_args(aReply, &err,
-                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len,
-                            DBUS_TYPE_INVALID)) {
-     if (!handles) {
-       LOG("Null array in extract_handles");
-     } else {
-        for (int i = 0; i < len; ++i) {
-        aOutHandles.AppendElement(handles[i]);
-      }
-    }
-  } else {
-    LOG_AND_FREE_DBUS_ERROR(&err);
-  }
-}
-
-// static
-bool
-BluetoothDBusService::AddReservedServicesInternal(const nsAString& aAdapterPath,
-                                                  const nsTArray<uint32_t>& aServices, 
-                                                  nsTArray<uint32_t>& aServiceHandlesContainer)
-{
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  int length = aServices.Length();
-  if (length == 0) return false;
-
-  const uint32_t* services = aServices.Elements();
-  DBusMessage* reply =
-    dbus_func_args(gThreadConnection->GetConnection(),
-                   NS_ConvertUTF16toUTF8(aAdapterPath).get(),
-                   DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
-                   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
-                   &services, length, DBUS_TYPE_INVALID);
-
-  if (!reply) {
-    LOG("Null DBus message. Couldn't extract handles.");
-    return false;
-  }
-
-  ExtractHandles(reply, aServiceHandlesContainer);
-  return true;
-}
-
 // static
 bool
 BluetoothDBusService::RemoveReservedServicesInternal(const nsAString& aAdapterPath,
                                                      const nsTArray<uint32_t>& aServiceHandles)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
   int length = aServiceHandles.Length();
@@ -1769,17 +1839,17 @@ BluetoothDBusService::RemoveDeviceIntern
 {
   nsCString tempDeviceObjectPath =
     NS_ConvertUTF16toUTF8(GetObjectPathFromAddress(aAdapterPath, aDeviceAddress));
   const char* deviceObjectPath = tempDeviceObjectPath.get();
 
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
   // We don't really care about how long it would take on removing a device,
-  // just to make sure that the value of timeout is reasonable. So, we use 
+  // just to make sure that the value of timeout is reasonable. So, we use
   // -1 for the timeout, which means a reasonable default timeout will be used.
   bool ret = dbus_func_args_async(mConnection,
                                   -1,
                                   GetVoidCallback,
                                   (void*)runnable,
                                   NS_ConvertUTF16toUTF8(aAdapterPath).get(),
                                   DBUS_ADAPTER_IFACE,
                                   "RemoveDevice",
@@ -1901,17 +1971,17 @@ BluetoothDBusService::SetPairingConfirma
     errorStr.AssignLiteral("Couldn't get original request message.");
     DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   DBusMessage *reply;
 
   if (aConfirm) {
-    reply = dbus_message_new_method_return(msg);   
+    reply = dbus_message_new_method_return(msg);
   } else {
     reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected",
                                    "User rejected confirmation");
   }
 
   if (!reply) {
     LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
     dbus_message_unref(msg);
@@ -1935,28 +2005,28 @@ BluetoothDBusService::SetPairingConfirma
 bool
 BluetoothDBusService::SetAuthorizationInternal(const nsAString& aDeviceAddress,
                                                bool aAllow,
                                                BluetoothReplyRunnable* aRunnable)
 {
   nsString errorStr;
   BluetoothValue v = true;
   DBusMessage *msg;
-  
+
   if (!sAuthorizeReqTable.Get(aDeviceAddress, &msg)) {
     LOG("%s: Couldn't get original request message.", __FUNCTION__);
     errorStr.AssignLiteral("Couldn't get original request message.");
     DispatchBluetoothReply(aRunnable, v, errorStr);
     return false;
   }
 
   DBusMessage *reply;
 
   if (aAllow) {
-    reply = dbus_message_new_method_return(msg);   
+    reply = dbus_message_new_method_return(msg);
   } else {
     reply = dbus_message_new_error(msg, "org.bluez.Error.Rejected",
                                    "User rejected authorization");
   }
 
   if (!reply) {
     LOG("%s: Memory can't be allocated for the message.", __FUNCTION__);
     dbus_message_unref(msg);
@@ -1972,16 +2042,35 @@ BluetoothDBusService::SetAuthorizationIn
   dbus_message_unref(msg);
   dbus_message_unref(reply);
 
   sAuthorizeReqTable.Remove(aDeviceAddress);
   DispatchBluetoothReply(aRunnable, v, errorStr);
   return result;
 }
 
+nsresult
+BluetoothDBusService::PrepareAdapterInternal(const nsAString& aPath)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+
+  if (!mConnection || !gThreadConnection) {
+    NS_ERROR("Bluetooth service not started yet!");
+    return NS_ERROR_FAILURE;
+  }
+
+  nsRefPtr<nsRunnable> func(new PrepareAdapterRunnable(aPath));
+  if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Cannot dispatch task!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
 class CreateBluetoothSocketRunnable : public nsRunnable
 {
 public:
   CreateBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable,
                                 const nsAString& aObjectPath,
                                 const nsAString& aServiceUUID,
                                 int aType,
                                 bool aAuth,
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -84,24 +84,27 @@ public:
   virtual bool
   SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
                      BluetoothReplyRunnable* aRunnable);
 
   virtual bool
   SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
                      BluetoothReplyRunnable* aRunnable);
 
-  virtual bool 
+  virtual bool
   SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
                                  BluetoothReplyRunnable* aRunnable);
 
-  virtual bool 
+  virtual bool
   SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
                            BluetoothReplyRunnable* aRunnable);
 
+  virtual nsresult
+  PrepareAdapterInternal(const nsAString& aPath);
+
 private:
   nsresult SendGetPropertyMessage(const nsAString& aPath,
                                   const char* aInterface,
                                   void (*aCB)(DBusMessage *, void *),
                                   BluetoothReplyRunnable* aRunnable);
   nsresult SendDiscoveryMessage(const nsAString& aAdapterPath,
                                 const char* aMessageName,
                                 BluetoothReplyRunnable* aRunnable);
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -283,28 +283,30 @@ AsyncConnectionHelper::Run()
           NS_WARNING("Failed to make savepoint!");
         }
       }
     }
 
     mResultCode = DoDatabaseWork(connection);
 
     if (mDatabase) {
-      IndexedDatabaseManager::SetCurrentWindow(nullptr);
-
       // Release or roll back the savepoint depending on the error code.
       if (hasSavepoint) {
         NS_ASSERTION(mTransaction, "Huh?!");
         if (NS_SUCCEEDED(mResultCode)) {
           mTransaction->ReleaseSavepoint();
         }
         else {
           mTransaction->RollbackSavepoint();
         }
       }
+
+      // Don't unset this until we're sure that all SQLite activity has
+      // completed!
+      IndexedDatabaseManager::SetCurrentWindow(nullptr);
     }
   }
   else {
     // NS_ERROR_NOT_AVAILABLE is our special code for "database is invalidated"
     // and we should fail with RECOVERABLE_ERR.
     if (rv == NS_ERROR_NOT_AVAILABLE) {
       mResultCode = NS_ERROR_DOM_INDEXEDDB_RECOVERABLE_ERR;
     }
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -76,32 +76,32 @@ IDBRequest::Reset()
 
 nsresult
 IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!");
   NS_ASSERTION(JSVAL_IS_VOID(mResultVal), "Should be undefined!");
 
-  // See if our window is still valid. If not then we're going to pretend that
-  // we never completed.
-  if (NS_FAILED(CheckInnerWindowCorrectness())) {
-    return NS_OK;
-  }
-
   mHaveResultOrErrorCode = true;
 
   nsresult rv = aHelper->GetResultCode();
 
   // If the request failed then set the error code and return.
   if (NS_FAILED(rv)) {
     SetError(rv);
     return NS_OK;
   }
 
+  // See if our window is still valid. If not then we're going to pretend that
+  // we never completed.
+  if (NS_FAILED(CheckInnerWindowCorrectness())) {
+    return NS_OK;
+  }
+
   // Otherwise we need to get the result from the helper.
   JSContext* cx = GetJSContext();
   if (!cx) {
     NS_WARNING("Failed to get safe JSContext!");
     rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     SetError(rv);
     return rv;
   }
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -776,27 +776,27 @@ IndexedDatabaseManager::EnsureOriginIsIn
   // First figure out the filename pattern we'll use.
   nsCOMPtr<nsIFile> patternFile;
   rv = directory->Clone(getter_AddRefs(patternFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = patternFile->Append(NS_LITERAL_STRING("*"));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCString pattern;
-  rv = patternFile->GetNativePath(pattern);
+  nsString pattern;
+  rv = patternFile->GetPath(pattern);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now tell SQLite to start tracking this pattern for content.
   nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
 
   if (aPrivilege != Chrome) {
-    rv = ss->SetQuotaForFilenamePattern(pattern,
+    rv = ss->SetQuotaForFilenamePattern(NS_ConvertUTF16toUTF8(pattern),
                                         GetIndexedDBQuotaMB() * 1024 * 1024,
                                         mQuotaCallbackSingleton, nullptr);
     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 tell SQLite about all of them.
--- a/dom/interfaces/permission/nsIDOMPermissionSettings.idl
+++ b/dom/interfaces/permission/nsIDOMPermissionSettings.idl
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
 interface nsIDOMDOMRequest;
 
-[scriptable, uuid(36e73ef0-c6f4-11e1-9b21-0800200c9a66)]
+[scriptable, uuid(18390770-02ab-11e2-a21f-0800200c9a66)]
 interface nsIDOMPermissionSettings : nsISupports
 {
-  DOMString get(in DOMString permission, in DOMString access, in DOMString manifestURI, in DOMString origin, in bool browserFlag);
+  DOMString get(in DOMString permission, in DOMString manifestURI, in DOMString origin, in bool browserFlag);
 
-  void set(in DOMString permission, in DOMString access, in DOMString manifestURI, in DOMString origin, in DOMString value, in bool browserFlag);
+  void set(in DOMString permission, in DOMString value, in DOMString manifestURI, in DOMString origin, in bool browserFlag);
 };
--- a/dom/permission/PermissionSettings.js
+++ b/dom/permission/PermissionSettings.js
@@ -18,31 +18,31 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PermissionSettings.jsm");
 
 var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"].getService(Components.interfaces.nsISyncMessageSender);
 
 // PermissionSettings
 
 const PERMISSIONSETTINGS_CONTRACTID = "@mozilla.org/permissionSettings;1";
-const PERMISSIONSETTINGS_CID        = Components.ID("{36e73ef0-c6f4-11e1-9b21-0800200c9a66}");
+const PERMISSIONSETTINGS_CID        = Components.ID("{18390770-02ab-11e2-a21f-0800200c9a66}");
 const nsIDOMPermissionSettings      = Components.interfaces.nsIDOMPermissionSettings;
 
 function PermissionSettings()
 {
   debug("Constructor");
 }
 
 var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
 var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"].getService(Components.interfaces.nsIScriptSecurityManager);
 var appsService = Components.classes["@mozilla.org/AppsService;1"].getService(Components.interfaces.nsIAppsService);
 
 PermissionSettings.prototype = {
-  get: function get(aPermission, aAccess, aManifestURL, aOrigin, aBrowserFlag) {
-    debug("Get called with: " + aPermission + ", " + aAccess + ", " + aManifestURL + ", " + aOrigin + ", " + aBrowserFlag);
+  get: function get(aPermission, aManifestURL, aOrigin, aBrowserFlag) {
+    debug("Get called with: " + aPermission + ", " + aManifestURL + ", " + aOrigin + ", " + aBrowserFlag);
     let uri = Services.io.newURI(aOrigin, null, null);
     let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
     let principal = secMan.getAppCodebasePrincipal(uri, appID, aBrowserFlag);
     let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
 
     switch (result)
     {
       case Ci.nsIPermissionManager.UNKNOWN_ACTION:
@@ -54,35 +54,35 @@ PermissionSettings.prototype = {
       case Ci.nsIPermissionManager.PROMPT_ACTION:
         return "prompt";
       default:
         dump("Unsupported PermissionSettings Action!\n");
         return "unknown";
     }
   },
 
-  set: function set(aPermission, aAccess, aManifestURL, aOrigin, aValue, aBrowserFlag) {
-    debug("Set called with: " + aPermission + ", " + aAccess + ", " + aManifestURL + ", " + aOrigin + ",  " + aValue + ", " + aBrowserFlag);
+  set: function set(aPermission, aValue, aManifestURL, aOrigin, aBrowserFlag) {
+    debug("Set called with: " + aPermission + ", " + aManifestURL + ", " + aOrigin + ",  " + aValue + ", " + aBrowserFlag);
     let action;
     cpm.sendSyncMessage("PermissionSettings:AddPermission", {
       type: aPermission,
-      access: aAccess,
       origin: aOrigin,
       manifestURL: aManifestURL,
       value: aValue,
       browserFlag: aBrowserFlag
     });
   },
 
   init: function(aWindow) {
     debug("init");
+
     // Set navigator.mozPermissionSettings to null.
+    let perm = Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "permissions");
     if (!Services.prefs.getBoolPref("dom.mozPermissionSettings.enabled")
-        || Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "permissions")) {
-      debug("Permission to get/set permissions not granted!");
+        || perm != Ci.nsIPermissionManager.ALLOW_ACTION) {
       return null;
     }
 
     debug("Permission to get/set permissions granted!");
   },
 
   classID : PERMISSIONSETTINGS_CID,
   QueryInterface : XPCOMUtils.generateQI([nsIDOMPermissionSettings, Ci.nsIDOMGlobalPropertyInitializer]),
--- a/dom/permission/PermissionSettings.manifest
+++ b/dom/permission/PermissionSettings.manifest
@@ -1,3 +1,3 @@
-component {36e73ef0-c6f4-11e1-9b21-0800200c9a66} PermissionSettings.js
-contract @mozilla.org/permissionSettings;1 {36e73ef0-c6f4-11e1-9b21-0800200c9a66}
+component {18390770-02ab-11e2-a21f-0800200c9a66} PermissionSettings.js
+contract @mozilla.org/permissionSettings;1 {18390770-02ab-11e2-a21f-0800200c9a66}
 category JavaScript-navigator-property mozPermissionSettings @mozilla.org/permissionSettings;1
--- a/dom/permission/tests/test_permission_basics.html
+++ b/dom/permission/tests/test_permission_basics.html
@@ -16,38 +16,39 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 "use strict";
 
+SpecialPowers.addPermission("permissions", true, document);
 var comp = SpecialPowers.wrap(Components);
 SpecialPowers.pushPrefEnv({ "set": [["dom.mozPermissionSettings.enabled", true]] }, 
                           function() {
-                            SpecialPowers.addPermission("permissions", true, document);
+                            SpecialPowers.removePermission("permissions", document);
                           });
 
 comp.utils.import("resource://gre/modules/PermissionSettings.jsm");
 var mozPermissions = window.navigator.mozPermissionSettings;
 
 function permissionTest() {
   if (gPermissionssEnabled) {
-    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "unknown", true);
-    var result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    mozPermissions.set("a", "unknown", "http://examplemanifestURI.com", "http://origin.com", true);
+    var result = mozPermissions.get("a", "http://examplemanifestURI.com", "http://origin.com", true);
     is(result, "unknown", "same result");
-    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "allow", true);
-    result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    mozPermissions.set("a", "allow", "http://examplemanifestURI.com", "http://origin.com", true);
+    result = mozPermissions.get("a", "http://examplemanifestURI.com", "http://origin.com", true);
     is(result, "allow", "same result");
-    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "deny", true);
-    result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    mozPermissions.set("a", "deny", "http://examplemanifestURI.com", "http://origin.com", true);
+    result = mozPermissions.get("a", "http://examplemanifestURI.com", "http://origin.com", true);
     is(result, "deny", "same result");
-    mozPermissions.set("a", "read", "http://examplemanifestURI.com", "http://origin.com", "prompt", true);
-    result = mozPermissions.get("a","read", "http://examplemanifestURI.com", "http://origin.com", true);
+    mozPermissions.set("a", "prompt", "http://examplemanifestURI.com", "http://origin.com", true);
+    result = mozPermissions.get("a", "http://examplemanifestURI.com", "http://origin.com", true);
     is(result, "prompt", "same result");
     SimpleTest.finish();
   } else {
     is(mozPermissions, null, "mozPermissionSettings is null when not enabled.");
     SimpleTest.finish();
   }
 }
 
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -248,16 +248,31 @@ public:
   void SetMode(int32_t aMode)
   {
     if ((aMode == AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED) &&
         (mMode == AUTOMOUNTER_DISABLE)) {
       // If it's already disabled, then leave it as disabled.
       // AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED implies "enabled until unplugged"
       aMode = AUTOMOUNTER_DISABLE;
     }
+
+    if ((aMode == AUTOMOUNTER_DISABLE) &&
+        (mMode == AUTOMOUNTER_ENABLE) && IsUsbCablePluggedIn()) {
+      // On many devices (esp non-Samsung), we can't force the disable, so we
+      // need to defer until the USB cable is actually unplugged.
+      // See bug 777043.
+      //
+      // Otherwise our attempt to disable it will fail, and we'll wind up in a bad
+      // state where the AutoMounter thinks that Sharing has been turned off, but
+      // the files are actually still being Shared because the attempt to unshare
+      // failed.
+      LOG("Attempting to disable UMS. Deferring until USB cable is unplugged.");
+      aMode = AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED;
+    }
+
     if (aMode != mMode) {
       LOG("Changing mode from '%s' to '%s'", ModeStr(mMode), ModeStr(aMode));
       mMode = aMode;
       DBG("Calling UpdateState due to mode set to %d", mMode);
       UpdateState();
     }
   }
 
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -348,16 +348,17 @@ NetworkManager.prototype = {
       // Don't set default route and DNS on secondary APN
       if (oldActive &&
           (oldActive.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
           oldActive.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL)) {
         return;
       }
       this.setDefaultRouteAndDNS(oldActive);
     }
+    Services.io.offline = !this.active;
   },
 
   setDefaultRouteAndDNS: function setDefaultRouteAndDNS(oldInterface) {
     debug("Going to change route and DNS to " + this.active.name);
     let options = {
       cmd: this.active.dhcp ? "runDHCPAndSetDefaultRouteAndDNS" : "setDefaultRouteAndDNS",
       ifname: this.active.name,
       oldIfname: (oldInterface && oldInterface != this.active) ? oldInterface.name : null
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -522,29 +522,58 @@ RadioInterfaceLayer.prototype = {
       if (this.networkChanged(operatorMessage, voice.network)) {
         voice.network = operatorMessage;
       }
       if (this.networkChanged(operatorMessage, data.network)) {
         data.network = operatorMessage;
       }
     }
 
+    this.checkRoamingBetweenOperators(voice);
+    this.checkRoamingBetweenOperators(data);
+
     if (voiceMessage || operatorMessage) {
       ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voice);
     }
     if (dataMessage || operatorMessage) {
       ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data);
     }
 
     if (selectionMessage) {
       this.updateNetworkSelectionMode(selectionMessage);
     }
   },
 
   /**
+    * Fix the roaming. RIL can report roaming in some case it is not
+    * really the case. See bug 787967
+    *
+    * @param registration  The voiceMessage or dataMessage from which the
+    *                      roaming state will be changed (maybe, if needed).
+    */
+  checkRoamingBetweenOperators: function checkRoamingBetweenOperators(registration) {
+    let icc = this.rilContext.icc;
+    if (!icc || !registration.connected) {
+      return;
+    }
+
+    let spn = icc.spn;
+    let operator = registration.network;
+    let longName = operator.longName;
+    let shortName = operator.shortName;
+
+    let equalsLongName = longName && (spn == longName);
+    let equalsShortName = shortName && (spn == shortName);
+    let equalsMcc = icc.mcc == operator.mcc;
+
+    registration.roaming = registration.roaming &&
+                           !(equalsMcc && (equalsLongName || equalsShortName));
+  },
+
+  /**
    * Sends the RIL:VoiceInfoChanged message when the voice
    * connection's state has changed.
    *
    * @param newInfo The new voice connection information. When newInfo.batch is true,
    *                the RIL:VoiceInfoChanged message will not be sent.
    */
   updateVoiceConnection: function updateVoiceConnection(newInfo) {
     let voiceInfo = this.rilContext.voice;
@@ -1322,35 +1351,31 @@ RadioInterfaceLayer.prototype = {
 
   get microphoneMuted() {
     return gAudioManager.microphoneMuted;
   },
   set microphoneMuted(value) {
     if (value == this.microphoneMuted) {
       return;
     }
-    gAudioManager.phoneState = value ?
-      nsIAudioManager.PHONE_STATE_IN_COMMUNICATION :
-      nsIAudioManager.PHONE_STATE_IN_CALL;  //XXX why is this needed?
     gAudioManager.microphoneMuted = value;
 
     if (!this._activeCall) {
       gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
     }
   },
 
   get speakerEnabled() {
     return (gAudioManager.getForceForUse(nsIAudioManager.USE_COMMUNICATION) ==
             nsIAudioManager.FORCE_SPEAKER);
   },
   set speakerEnabled(value) {
     if (value == this.speakerEnabled) {
       return;
     }
-    gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL; // XXX why is this needed?
     let force = value ? nsIAudioManager.FORCE_SPEAKER :
                         nsIAudioManager.FORCE_NONE;
     gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
 
     if (!this._activeCall) {
       gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
     }
   },
--- a/dom/system/gonk/VolumeManager.cpp
+++ b/dom/system/gonk/VolumeManager.cpp
@@ -9,26 +9,27 @@
 #include "VolumeManagerLog.h"
 #include "VolumeServiceTest.h"
 
 #include "nsWhitespaceTokenizer.h"
 #include "nsXULAppAPI.h"
 
 #include "base/message_loop.h"
 #include "mozilla/Scoped.h"
+#include "mozilla/StaticPtr.h"
 
 #include <android/log.h>
 #include <cutils/sockets.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 
 namespace mozilla {
 namespace system {
 
-static RefPtr<VolumeManager> sVolumeManager;
+static StaticRefPtr<VolumeManager> sVolumeManager;
 
 VolumeManager::STATE VolumeManager::mState = VolumeManager::UNINITIALIZED;
 VolumeManager::StateObserverList VolumeManager::mStateObserverList;
 
 /***************************************************************************/
 
 VolumeManager::VolumeManager()
   : mSocket(-1),
--- a/dom/system/gonk/VolumeManager.h
+++ b/dom/system/gonk/VolumeManager.h
@@ -152,17 +152,16 @@ private:
 
   static const int    kRcvBufSize = 1024;
   ScopedClose         mSocket;
   VolumeArray         mVolumeArray;
   CommandQueue        mCommands;
   bool                mCommandPending;
   char                mRcvBuf[kRcvBufSize];
   size_t              mRcvIdx;
-  MessageLoopForIO                       *mIOLoop;
   MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
   MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
   RefPtr<VolumeResponseCallback>          mBroadcastCallback;
 };
 
 /***************************************************************************
 *
 *   The initialization/shutdown functions do not need to be called from
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1058,16 +1058,17 @@ let RIL = {
   /**
    * Fetch ICC records.
    */
   fetchICCRecords: function fetchICCRecords() {
     this.getICCID();
     this.getIMSI();
     this.getMSISDN();
     this.getAD();
+    this.getSPN();
     this.getSST();
     this.getMBDN();
   },
 
   /**
    * Update the ICC information to RadioInterfaceLayer.
    */
   _handleICCInfoChange: function _handleICCInfoChange() {
@@ -1190,16 +1191,49 @@ let RIL = {
       data:      null,
       pin2:      null,
       type:      EF_TYPE_TRANSPARENT,
       callback:  callback,
     });
   },
 
   /**
+   * Read the SPN (Service Provider Name) from the ICC.
+   */
+  getSPN: function getSPN() {
+    function callback() {
+      let length = Buf.readUint32();
+      // Each octet is encoded into two chars.
+      // Minus 1 because first is used to store display condition
+      let len = (length / 2) - 1;
+      let spnDisplayCondition = GsmPDUHelper.readHexOctet();
+      this.iccInfo.spn = GsmPDUHelper.readAlphaIdentifier(len);
+      Buf.readStringDelimiter(length);
+
+      if (DEBUG) {
+        debug("SPN: spn=" + this.iccInfo.spn + ", spnDisplayCondition=" + spnDisplayCondition);
+      }
+      this._handleICCInfoChange();
+    }
+
+    this.iccIO({
+      command:   ICC_COMMAND_GET_RESPONSE,
+      fileId:    ICC_EF_SPN,
+      pathId:    this._getPathIdForICCRecord(ICC_EF_SPN),
+      p1:        0, // For GET_RESPONSE, p1 = 0
+      p2:        0, // For GET_RESPONSE, p2 = 0
+      p3:        GET_RESPONSE_EF_SIZE_BYTES,
+      data:      null,
+      pin2:      null,
+      type:      EF_TYPE_TRANSPARENT,
+      callback:  callback,
+    });
+  },
+
+  /**
    * Get whether specificed (U)SIM service is available.
    *
    * @param geckoService
    *        Service name like "ADN", "BDN", etc.
    *
    * @return true if the service is enabled, false otherwise.
    */
   isICCServiceAvailable: function isICCServiceAvailable(geckoService) {
@@ -2234,44 +2268,51 @@ let RIL = {
 
   /**
    * Send STK Envelope(Menu Selection) command.
    *
    * @param itemIdentifier
    * @param helpRequested
    */
   sendStkMenuSelection: function sendStkMenuSelection(command) {
+    command.tag = BER_MENU_SELECTION_TAG;
+    command.deviceId = {
+      sourceId :STK_DEVICE_ID_KEYPAD,
+      destinationId: STK_DEVICE_ID_SIM
+    };
     this.sendICCEnvelopeCommand(command);
   },
 
   /**
    * Send REQUEST_STK_SEND_ENVELOPE_COMMAND to ICC.
    *
+   * @param tag
+   * @patam deviceId
    * @param [optioanl] itemIdentifier
    * @param [optional] helpRequested
    */
   sendICCEnvelopeCommand: function sendICCEnvelopeCommand(options) {
     let token = Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_COMMAND);
     let berLen = 4 + /* Size of Device Identifier TLV */
                  (options.itemIdentifier ? 3 : 0) +
                  (options.helpRequested ? 2 : 0);
     let size = (2 + berLen) * 2;
 
     Buf.writeUint32(size);
 
     // Write a BER-TLV
-    GsmPDUHelper.writeHexOctet(BER_MENU_SELECTION_TAG);
+    GsmPDUHelper.writeHexOctet(options.tag);
     GsmPDUHelper.writeHexOctet(berLen);
 
     // Device Identifies
     GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID |
                                COMPREHENSIONTLV_FLAG_CR);
     GsmPDUHelper.writeHexOctet(2);
-    GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_KEYPAD);
-    GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_SIM);
+    GsmPDUHelper.writeHexOctet(options.deviceId.sourceId);
+    GsmPDUHelper.writeHexOctet(options.deviceId.destinationId);
 
     // Item Identifier
     if (options.itemIdentifier) {
       GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ITEM_ID |
                                  COMPREHENSIONTLV_FLAG_CR);
       GsmPDUHelper.writeHexOctet(1);
       GsmPDUHelper.writeHexOctet(options.itemIdentifier);
     }
@@ -2419,26 +2460,28 @@ let RIL = {
       case CARD_APPTYPE_SIM:
         switch (fileId) {
           case ICC_EF_FDN:
           case ICC_EF_MSISDN:
             return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
 
           case ICC_EF_AD:
           case ICC_EF_MBDN:
+          case ICC_EF_SPN:
           case ICC_EF_SST:
             return EF_PATH_MF_SIM + EF_PATH_DF_GSM;
         }
       case CARD_APPTYPE_USIM:
         switch (fileId) {
           case ICC_EF_AD:
           case ICC_EF_FDN:
           case ICC_EF_MBDN:
           case ICC_EF_UST:
           case ICC_EF_MSISDN:
+          case ICC_EF_SPN:
             return EF_PATH_MF_SIM + EF_PATH_ADF_USIM;
 
           default:
             // The file ids in USIM phone book entries are decided by the
 	    // card manufacturer. So if we don't match any of the cases
 	    // above and if its a USIM return the phone book path.
             return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
         }
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -286,19 +286,25 @@ DrawTargetD2D::DrawSurface(SourceSurface
     break;
   case SURFACE_D2D1_DRAWTARGET:
     {
       SourceSurfaceD2DTarget *srcSurf = static_cast<SourceSurfaceD2DTarget*>(aSurface);
       bitmap = srcSurf->GetBitmap(mRT);
       AddDependencyOnSource(srcSurf);
     }
     break;
-  case SURFACE_DATA:
+  default:
     {
-      DataSourceSurface *srcSurf = static_cast<DataSourceSurface*>(aSurface);
+      RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
+
+      if (!srcSurf) {
+        gfxDebug() << "Not able to deal with non-data source surface.";
+        return;
+      }
+
       if (aSource.width > rt->GetMaximumBitmapSize() ||
           aSource.height > rt->GetMaximumBitmapSize()) {
         gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail.";
         // Don't know how to deal with this yet.
         return;
       }
 
       int stride = srcSurf->Stride();
@@ -310,18 +316,16 @@ DrawTargetD2D::DrawSurface(SourceSurface
       D2D1_BITMAP_PROPERTIES props =
         D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat())));
       mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap));
 
       srcRect.x -= (uint32_t)aSource.x;
       srcRect.y -= (uint32_t)aSource.y;
     }
     break;
-  default:
-    break;
   }
 
   rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect));
 
   FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest);
 }
 
 void
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -183,16 +183,18 @@ avoid-extend-none.patch: Avoid incorrect
 win32-ExtCreatePen-zero-size.patch: Don't pass zero width or dash lengths to ExtCreatePen (bug 768348)
 
 d2d-repeating-gradients.patch: Minimize number of gradient stops added to handle repeating with path fills (bug 768775)
 
 xlib-glyph-clip-region.patch: bug 709477, addressed upstream by be1ff2f45fdbc69537e513834fcffa0435e63073
 
 gdi-RGB24-ARGB32.patch: bug 788794
 
+dwrite-font-printing.patch: bug 468568; don't substitute a GDI font for a DWrite font if the name tables aren't equal
+
 ==== pixman patches ====
 
 pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
 
 pixman-rename-and-endian.patch: include cairo-platform.h for renaming of external symbols and endian macros
 
 NOTE: we previously supported ARM assembler on MSVC, this has been removed because of the maintenance burden
 
--- a/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
+++ b/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
@@ -37,16 +37,17 @@
 #include "cairoint.h"
 
 #include "cairo-win32-private.h"
 #include "cairo-surface-private.h"
 #include "cairo-clip-private.h"
 
 #include "cairo-d2d-private.h"
 #include "cairo-dwrite-private.h"
+#include "cairo-truetype-subset-private.h"
 #include <float.h>
 
 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
     D2D1_FACTORY_TYPE factoryType,
     REFIID iid,
     CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
     void **factory
 );
@@ -1036,17 +1037,17 @@ cairo_int_status_t
 {
     cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
     cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
 
     const void *data;
     UINT32 size;
     void *tableContext;
     BOOL exists;
-    face->dwriteface->TryGetFontTable(tag,
+    face->dwriteface->TryGetFontTable(be32_to_cpu (tag),
 				      &data,
 				      &size,
 				      &tableContext,
 				      &exists);
 
     if (!exists) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -1476,16 +1477,59 @@ DWriteFactory::CreateRenderingParams()
     Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
 	pixelGeometry, renderingMode,
 	&mCustomClearTypeRenderingParams);
     Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
         pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
         &mForceGDIClassicRenderingParams);
 }
 
+static cairo_bool_t
+_name_tables_match (cairo_scaled_font_t *font1,
+                    cairo_scaled_font_t *font2)
+{
+    unsigned long size1;
+    unsigned long size2;
+    cairo_int_status_t status1;
+    cairo_int_status_t status2;
+    unsigned char *buffer1;
+    unsigned char *buffer2;
+    cairo_bool_t result = false;
+
+    if (!font1->backend->load_truetype_table ||
+        !font2->backend->load_truetype_table)
+        return false;
+
+    status1 = font1->backend->load_truetype_table (font1,
+                                                   TT_TAG_name, 0, NULL, &size1);
+    status2 = font2->backend->load_truetype_table (font2,
+                                                   TT_TAG_name, 0, NULL, &size2);
+    if (status1 || status2)
+        return false;
+    if (size1 != size2)
+        return false;
+
+    buffer1 = (unsigned char*)malloc (size1);
+    buffer2 = (unsigned char*)malloc (size2);
+
+    if (buffer1 && buffer2) {
+        status1 = font1->backend->load_truetype_table (font1,
+                                                       TT_TAG_name, 0, buffer1, &size1);
+        status2 = font2->backend->load_truetype_table (font2,
+                                                       TT_TAG_name, 0, buffer2, &size2);
+        if (!status1 && !status2) {
+            result = memcmp (buffer1, buffer2, size1) == 0;
+        }
+    }
+
+    free (buffer1);
+    free (buffer2);
+    return result;
+}
+
 // Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
 // of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
 // paths or blitting glyph bitmaps.
 cairo_int_status_t
 _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font,
                                                     cairo_scaled_font_t **new_font)
 {
     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE) {
@@ -1528,19 +1572,18 @@ cairo_int_status_t
 			                                  &ctm,
 			                                  &options);
     cairo_font_face_destroy (win32_face);
 
     if (!font) {
         return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    if (_cairo_win32_scaled_font_is_type1 (font) || _cairo_win32_scaled_font_is_bitmap (font)) {
-        // If we somehow got a Type1 or bitmap font, it can't be the same physical font
-        // as directwrite was using, so glyph IDs will not match; best we can do is to
-        // throw it away and fall back on rendering paths or blitting bitmaps instead.
+    if (!_name_tables_match (font, scaled_font)) {
+        // If the font name tables aren't equal, then GDI may have failed to
+        // find the right font and substituted a different font.
         cairo_scaled_font_destroy (font);
         return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
     *new_font = font;
     return CAIRO_INT_STATUS_SUCCESS;
 }
--- a/gfx/cairo/cairo/src/cairo-truetype-subset-private.h
+++ b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h
@@ -34,16 +34,18 @@
  *	Adrian Johnson <ajohnson@redneon.com>
  */
 
 #ifndef CAIRO_TRUETYPE_SUBSET_PRIVATE_H
 #define CAIRO_TRUETYPE_SUBSET_PRIVATE_H
 
 #include "cairoint.h"
 
+CAIRO_BEGIN_DECLS
+
 #if CAIRO_HAS_FONT_SUBSET
 
 /* The structs defined here should strictly follow the TrueType
  * specification and not be padded.  We use only 16-bit integer
  * in their definition to guarantee that.  The fields of type
  * "FIXED" in the TT spec are broken into two *_1 and *_2 16-bit
  * parts, and 64-bit members are broken into four.
  *
@@ -191,9 +193,11 @@ typedef struct _tt_composite_glyph {
 typedef struct _tt_glyph_data {
     int16_t           num_contours;
     int8_t            data[8];
     tt_composite_glyph_t glyph;
 } tt_glyph_data_t;
 
 #endif /* CAIRO_HAS_FONT_SUBSET */
 
+CAIRO_END_DECLS
+
 #endif /* CAIRO_TRUETYPE_SUBSET_PRIVATE_H */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/dwrite-font-printing.patch
@@ -0,0 +1,157 @@
+diff --git a/gfx/cairo/cairo/src/cairo-dwrite-font.cpp b/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
+--- a/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
++++ b/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
+@@ -37,16 +37,17 @@
+ #include "cairoint.h"
+ 
+ #include "cairo-win32-private.h"
+ #include "cairo-surface-private.h"
+ #include "cairo-clip-private.h"
+ 
+ #include "cairo-d2d-private.h"
+ #include "cairo-dwrite-private.h"
++#include "cairo-truetype-subset-private.h"
+ #include <float.h>
+ 
+ typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
+     D2D1_FACTORY_TYPE factoryType,
+     REFIID iid,
+     CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
+     void **factory
+ );
+@@ -1036,17 +1037,17 @@ cairo_int_status_t
+ {
+     cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+     cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
+ 
+     const void *data;
+     UINT32 size;
+     void *tableContext;
+     BOOL exists;
+-    face->dwriteface->TryGetFontTable(tag,
++    face->dwriteface->TryGetFontTable(be32_to_cpu (tag),
+ 				      &data,
+ 				      &size,
+ 				      &tableContext,
+ 				      &exists);
+ 
+     if (!exists) {
+ 	return CAIRO_INT_STATUS_UNSUPPORTED;
+     }
+@@ -1476,16 +1477,59 @@ DWriteFactory::CreateRenderingParams()
+     Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
+ 	pixelGeometry, renderingMode,
+ 	&mCustomClearTypeRenderingParams);
+     Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
+         pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
+         &mForceGDIClassicRenderingParams);
+ }
+ 
++static cairo_bool_t
++_name_tables_match (cairo_scaled_font_t *font1,
++                    cairo_scaled_font_t *font2)
++{
++    unsigned long size1;
++    unsigned long size2;
++    cairo_int_status_t status1;
++    cairo_int_status_t status2;
++    unsigned char *buffer1;
++    unsigned char *buffer2;
++    cairo_bool_t result = false;
++
++    if (!font1->backend->load_truetype_table ||
++        !font2->backend->load_truetype_table)
++        return false;
++
++    status1 = font1->backend->load_truetype_table (font1,
++                                                   TT_TAG_name, 0, NULL, &size1);
++    status2 = font2->backend->load_truetype_table (font2,
++                                                   TT_TAG_name, 0, NULL, &size2);
++    if (status1 || status2)
++        return false;
++    if (size1 != size2)
++        return false;
++
++    buffer1 = (unsigned char*)malloc (size1);
++    buffer2 = (unsigned char*)malloc (size2);
++
++    if (buffer1 && buffer2) {
++        status1 = font1->backend->load_truetype_table (font1,
++                                                       TT_TAG_name, 0, buffer1, &size1);
++        status2 = font2->backend->load_truetype_table (font2,
++                                                       TT_TAG_name, 0, buffer2, &size2);
++        if (!status1 && !status2) {
++            result = memcmp (buffer1, buffer2, size1) == 0;
++        }
++    }
++
++    free (buffer1);
++    free (buffer2);
++    return result;
++}
++
+ // Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
+ // of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
+ // paths or blitting glyph bitmaps.
+ cairo_int_status_t
+ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font,
+                                                     cairo_scaled_font_t **new_font)
+ {
+     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE) {
+@@ -1528,19 +1572,18 @@ cairo_int_status_t
+ 			                                  &ctm,
+ 			                                  &options);
+     cairo_font_face_destroy (win32_face);
+ 
+     if (!font) {
+         return CAIRO_INT_STATUS_UNSUPPORTED;
+     }
+ 
+-    if (_cairo_win32_scaled_font_is_type1 (font) || _cairo_win32_scaled_font_is_bitmap (font)) {
+-        // If we somehow got a Type1 or bitmap font, it can't be the same physical font
+-        // as directwrite was using, so glyph IDs will not match; best we can do is to
+-        // throw it away and fall back on rendering paths or blitting bitmaps instead.
++    if (!_name_tables_match (font, scaled_font)) {
++        // If the font name tables aren't equal, then GDI may have failed to
++        // find the right font and substituted a different font.
+         cairo_scaled_font_destroy (font);
+         return CAIRO_INT_STATUS_UNSUPPORTED;
+     }
+ 
+     *new_font = font;
+     return CAIRO_INT_STATUS_SUCCESS;
+ }
+diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset-private.h b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h
+--- a/gfx/cairo/cairo/src/cairo-truetype-subset-private.h
++++ b/gfx/cairo/cairo/src/cairo-truetype-subset-private.h
+@@ -34,16 +34,18 @@
+  *	Adrian Johnson <ajohnson@redneon.com>
+  */
+ 
+ #ifndef CAIRO_TRUETYPE_SUBSET_PRIVATE_H
+ #define CAIRO_TRUETYPE_SUBSET_PRIVATE_H
+ 
+ #include "cairoint.h"
+ 
++CAIRO_BEGIN_DECLS
++
+ #if CAIRO_HAS_FONT_SUBSET
+ 
+ /* The structs defined here should strictly follow the TrueType
+  * specification and not be padded.  We use only 16-bit integer
+  * in their definition to guarantee that.  The fields of type
+  * "FIXED" in the TT spec are broken into two *_1 and *_2 16-bit
+  * parts, and 64-bit members are broken into four.
+  *
+@@ -191,9 +193,11 @@ typedef struct _tt_composite_glyph {
+ typedef struct _tt_glyph_data {
+     int16_t           num_contours;
+     int8_t            data[8];
+     tt_composite_glyph_t glyph;
+ } tt_glyph_data_t;
+ 
+ #endif /* CAIRO_HAS_FONT_SUBSET */
+ 
++CAIRO_END_DECLS
++
+ #endif /* CAIRO_TRUETYPE_SUBSET_PRIVATE_H */
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -164,16 +164,29 @@ WrapRotationAxis(int32_t* aRotationPoint
 {
   if (*aRotationPoint < 0) {
     *aRotationPoint += aSize;
   } else if (*aRotationPoint >= aSize) {
     *aRotationPoint -= aSize;
   }
 }
 
+static nsIntRect
+ComputeBufferRect(const nsIntRect& aRequestedRect)
+{
+  nsIntRect rect(aRequestedRect);
+  // Set a minimum width to guarantee a minimum size of buffers we
+  // allocate (and work around problems on some platforms with smaller
+  // dimensions).  64 is the magic number needed to work around the
+  // rendering glitch, and guarantees image rows can be SIMD'd for
+  // even r5g6b5 surfaces pretty much everywhere.
+  rect.width = NS_MAX(aRequestedRect.width, 64);
+  return rect;
+}
+
 ThebesLayerBuffer::PaintState
 ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
                               uint32_t aFlags)
 {
   PaintState result;
   // We need to disable rotation if we're going to be resampled when
   // drawing, because we might sample across the rotation boundary.
   bool canHaveRotation = !(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION));
@@ -197,17 +210,18 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
       } else if (neededRegion.GetBounds().Size() <= mBufferRect.Size()) {
         // The buffer's big enough but doesn't contain everything that's
         // going to be visible. We'll move it.
         destBufferRect = nsIntRect(neededRegion.GetBounds().TopLeft(), mBufferRect.Size());
       } else {
         destBufferRect = neededRegion.GetBounds();
       }
     } else {
-      destBufferRect = neededRegion.GetBounds();
+      // We won't be reusing the buffer.  Compute a new rect.
+      destBufferRect = ComputeBufferRect(neededRegion.GetBounds());
     }
 
     if ((aFlags & PAINT_WILL_RESAMPLE) &&
         (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) ||
          neededRegion.GetNumRects() > 1)) {
       // The area we add to neededRegion might not be painted opaquely
       contentType = gfxASurface::CONTENT_COLOR_ALPHA;
 
@@ -266,17 +280,17 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
           EnsureBuffer()->MovePixels(srcRect, dest);
           result.mDidSelfCopy = true;
           // Don't set destBuffer; we special-case self-copies, and
           // just did the necessary work above.
           mBufferRect = destBufferRect;
         } else {
           // We can't do a real self-copy because the buffer is rotated.
           // So allocate a new buffer for the destination.
-          destBufferRect = neededRegion.GetBounds();
+          destBufferRect = ComputeBufferRect(neededRegion.GetBounds());
           destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags);
           if (!destBuffer)
             return result;
         }
       } else {
         mBufferRect = destBufferRect;
         mBufferRotation = newRotation;
       }
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -97,90 +97,97 @@ namespace {
 class VibratorRunnable
   : public nsIRunnable
   , public nsIObserver
 {
 public:
   VibratorRunnable()
     : mMonitor("VibratorRunnable")
     , mIndex(0)
-    , mShuttingDown(false)
   {
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     if (!os) {
       NS_WARNING("Could not get observer service!");
       return;
     }
 
-    os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, /* weak ref */ true);
+    os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   }
+
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIOBSERVER
 
   // Run on the main thread, not the vibrator thread.
   void Vibrate(const nsTArray<uint32_t> &pattern);
   void CancelVibrate();
 
+  static bool ShuttingDown() { return sShuttingDown; }
+
 private:
   Monitor mMonitor;
 
   // The currently-playing pattern.
   nsTArray<uint32_t> mPattern;
 
   // The index we're at in the currently-playing pattern.  If mIndex >=
   // mPattern.Length(), then we're not currently playing anything.
   uint32_t mIndex;
 
   // Set to true in our shutdown observer.  When this is true, we kill the
   // vibrator thread.
-  bool mShuttingDown;
+  static bool sShuttingDown;
 };
 
-NS_IMPL_ISUPPORTS2(VibratorRunnable, nsIRunnable, nsIObserver);
+NS_IMPL_THREADSAFE_ISUPPORTS2(VibratorRunnable, nsIRunnable, nsIObserver);
+
+bool VibratorRunnable::sShuttingDown = false;
+
+static nsRefPtr<VibratorRunnable> sVibratorRunnable;
 
 NS_IMETHODIMP
 VibratorRunnable::Run()
 {
   MonitorAutoLock lock(mMonitor);
 
   // We currently assume that mMonitor.Wait(X) waits for X milliseconds.  But in
   // reality, the kernel might not switch to this thread for some time after the
   // wait expires.  So there's potential for some inaccuracy here.
   //
   // This doesn't worry me too much.  Note that we don't even start vibrating
   // immediately when VibratorRunnable::Vibrate is called -- we go through a
   // condvar onto another thread.  Better just to be chill about small errors in
   // the timing here.
 
-  while (!mShuttingDown) {
+  while (!sShuttingDown) {
     if (mIndex < mPattern.Length()) {
       uint32_t duration = mPattern[mIndex];
       if (mIndex % 2 == 0) {
         vibrator_on(duration);
       }
       mIndex++;
       mMonitor.Wait(PR_MillisecondsToInterval(duration));
     }
     else {
       mMonitor.Wait();
     }
   }
-
+  sVibratorRunnable = NULL;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 VibratorRunnable::Observe(nsISupports *subject, const char *topic,
                           const PRUnichar *data)
 {
   MOZ_ASSERT(strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
   MonitorAutoLock lock(mMonitor);
-  mShuttingDown = true;
+  sShuttingDown = true;
   mMonitor.Notify();
+
   return NS_OK;
 }
 
 void
 VibratorRunnable::Vibrate(const nsTArray<uint32_t> &pattern)
 {
   MonitorAutoLock lock(mMonitor);
   mPattern = pattern;
@@ -193,43 +200,48 @@ VibratorRunnable::CancelVibrate()
 {
   MonitorAutoLock lock(mMonitor);
   mPattern.Clear();
   mPattern.AppendElement(0);
   mIndex = 0;
   mMonitor.Notify();
 }
 
-VibratorRunnable *sVibratorRunnable = NULL;
-
 void
 EnsureVibratorThreadInitialized()
 {
   if (sVibratorRunnable) {
     return;
   }
 
-  nsRefPtr<VibratorRunnable> runnable = new VibratorRunnable();
-  sVibratorRunnable = runnable;
+  sVibratorRunnable = new VibratorRunnable();
   nsCOMPtr<nsIThread> thread;
   NS_NewThread(getter_AddRefs(thread), sVibratorRunnable);
 }
 
 } // anonymous namespace
 
 void
 Vibrate(const nsTArray<uint32_t> &pattern, const hal::WindowIdentifier &)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  if (VibratorRunnable::ShuttingDown()) {
+    return;
+  }
   EnsureVibratorThreadInitialized();
   sVibratorRunnable->Vibrate(pattern);
 }
 
 void
 CancelVibrate(const hal::WindowIdentifier &)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  if (VibratorRunnable::ShuttingDown()) {
+    return;
+  }
   EnsureVibratorThreadInitialized();
   sVibratorRunnable->CancelVibrate();
 }
 
 namespace {
 
 class BatteryUpdater : public nsRunnable {
 public:
--- a/ipc/glue/AsyncChannel.h
+++ b/ipc/glue/AsyncChannel.h
@@ -66,17 +66,20 @@ public:
     {
     public:
         virtual ~AsyncListener() { }
 
         virtual void OnChannelClose() = 0;
         virtual void OnChannelError() = 0;
         virtual Result OnMessageReceived(const Message& aMessage) = 0;
         virtual void OnProcessingError(Result aError) = 0;
-        virtual void OnChannelConnected(int32_t peer_pid) {};
+        // FIXME/bug 792652: this doesn't really belong here, but a
+        // large refactoring is needed to put it where it belongs.
+        virtual int32_t GetProtocolTypeId() = 0;
+        virtual void OnChannelConnected(int32_t peer_pid) {}
     };
 
     enum Side { Parent, Child, Unknown };
 
 public:
     //
     // These methods are called on the "worker" thread
     //
--- a/ipc/glue/RPCChannel.h
+++ b/ipc/glue/RPCChannel.h
@@ -41,22 +41,23 @@ public:
     {
     public:
         virtual ~RPCListener() { }
 
         virtual void OnChannelClose() = 0;
         virtual void OnChannelError() = 0;
         virtual Result OnMessageReceived(const Message& aMessage) = 0;
         virtual void OnProcessingError(Result aError) = 0;
+        virtual int32_t GetProtocolTypeId() = 0;
         virtual bool OnReplyTimeout() = 0;
         virtual Result OnMessageReceived(const Message& aMessage,
                                          Message*& aReply) = 0;
         virtual Result OnCallReceived(const Message& aMessage,
                                       Message*& aReply) = 0;
-        virtual void OnChannelConnected(int32_t peer_pid) {};
+        virtual void OnChannelConnected(int32_t peer_pid) {}
 
         virtual void OnEnteredCxxStack()
         {
             NS_RUNTIMEABORT("default impl shouldn't be invoked");
         }
 
         virtual void OnExitedCxxStack()
         {
--- a/ipc/glue/SyncChannel.h
+++ b/ipc/glue/SyncChannel.h
@@ -27,20 +27,21 @@ public:
     {
     public:
         virtual ~SyncListener() { }
 
         virtual void OnChannelClose() = 0;
         virtual void OnChannelError() = 0;
         virtual Result OnMessageReceived(const Message& aMessage) = 0;
         virtual void OnProcessingError(Result aError) = 0;
+        virtual int32_t GetProtocolTypeId() = 0;
         virtual bool OnReplyTimeout() = 0;
         virtual Result OnMessageReceived(const Message& aMessage,
                                          Message*& aReply) = 0;
-        virtual void OnChannelConnected(int32_t peer_pid) {};
+        virtual void OnChannelConnected(int32_t peer_pid) {}
     };
 
     SyncChannel(SyncListener* aListener);
     virtual ~SyncChannel();
 
     virtual bool Send(Message* msg) MOZ_OVERRIDE {
         return AsyncChannel::Send(msg);
     }
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -107,16 +107,19 @@ def _actorName(pname, side):
     """|pname| is the protocol name. |side| is 'Parent' or 'Child'."""
     tag = side
     if not tag[0].isupper():  tag = side.title()
     return pname + tag
 
 def _actorIdType():
     return Type.INT32
 
+def _actorTypeTagType():
+    return Type.INT32
+
 def _actorId(actor=None):
     if actor is not None:
         return ExprSelect(actor, '->', 'mId')
     return ExprVar('mId')
 
 def _actorHId(actorhandle):
     return ExprSelect(actorhandle, '.', 'mId')
 
@@ -3023,16 +3026,22 @@ class _GenerateProtocolActorCode(ipdl.as
         if ptype.isToplevel():
             onprocessingerror.addstmt(StmtReturn(
                 ExprCall(p.processingErrorVar(), args=[ codevar ])))
         else:
             onprocessingerror.addstmt(
                 _runtimeAbort("`OnProcessingError' called on non-toplevel actor"))
         self.cls.addstmts([ onprocessingerror, Whitespace.NL ])
 
+        # int32_t GetProtocolTypeId() { return PFoo; }
+        gettypetag = MethodDefn(
+            MethodDecl('GetProtocolTypeId', ret=_actorTypeTagType()))
+        gettypetag.addstmt(StmtReturn(_protocolId(ptype)))
+        self.cls.addstmts([ gettypetag, Whitespace.NL ])
+
         # OnReplyTimeout()
         if toplevel.talksSync() or toplevel.talksRpc():
             ontimeout = MethodDefn(
                 MethodDecl('OnReplyTimeout', ret=Type.BOOL))
 
             if ptype.isToplevel():
                 ontimeout.addstmt(StmtReturn(
                     ExprCall(p.shouldContinueFromTimeoutVar())))
@@ -4123,38 +4132,54 @@ class _GenerateProtocolActorCode(ipdl.as
         ifbadid.addifstmts([
                 _protocolErrorBreakpoint('bad ID for '+ self.protocol.name),
                 StmtReturn.FALSE
         ])
         read.addstmts([ ifbadid, Whitespace.NL ])
         
         # if (NULL_ID == id)
         #   *var = null
-        # else
-        #   *var = Lookup(id)
-        #   if (!*var)
-        #     return false
+        #   return true
         outactor = ExprDeref(var)
         ifnull = StmtIf(ExprBinary(_NULL_ACTOR_ID, '==', idvar))
-        ifnull.addifstmt(StmtExpr(ExprAssn(outactor, ExprLiteral.NULL)))
-
-        ifnull.addelsestmt(StmtExpr(ExprAssn(
-            outactor,
-            ExprCast(_lookupListener(idvar), cxxtype, static=1))))
-
-        ifnotfound = StmtIf(ExprNot(outactor))
+        ifnull.addifstmts([ StmtExpr(ExprAssn(outactor, ExprLiteral.NULL)),
+                            StmtReturn.TRUE ])
+        read.addstmts([ ifnull, Whitespace.NL ])
+
+        # Listener* listener = Lookup(id)
+        # if (!listener)
+        #   return false
+        listenervar = ExprVar('listener')
+        read.addstmt(StmtDecl(Decl(Type('ChannelListener', ptr=1),
+                                   listenervar.name),
+                              init=_lookupListener(idvar)))
+        ifnotfound = StmtIf(ExprNot(listenervar))
         ifnotfound.addifstmts([
-                _protocolErrorBreakpoint('could not look up '+ self.protocol.name),
+                _protocolErrorBreakpoint('could not look up '+ actortype.name()),
                 StmtReturn.FALSE
         ])
-        ifnull.addelsestmt(ifnotfound)
-
+        read.addstmts([ ifnotfound, Whitespace.NL ])
+
+        # if listener->GetProtocolTypeId() != [expected protocol type]
+        #   return false
+        ifbadtype = StmtIf(ExprBinary(
+                _protocolId(actortype), '!=',
+                ExprCall(ExprSelect(listenervar, '->', 'GetProtocolTypeId'))))
+        ifbadtype.addifstmts([
+                _protocolErrorBreakpoint('actor that should be of type '+ actortype.name() +' has different type'),
+                StmtReturn.FALSE
+        ])
+        read.addstmts([ ifbadtype, Whitespace.NL ])
+
+        # *outactor = static_cast<ExpectedType>(listener)
+        # return true
         read.addstmts([
-            ifnull,
-            StmtReturn.TRUE
+                StmtExpr(ExprAssn(outactor,
+                                  ExprCast(listenervar, cxxtype, static=1))),
+                StmtReturn.TRUE
         ])
 
         self.cls.addstmts([ write, Whitespace.NL, read, Whitespace.NL ])
 
 
     def implementSpecialArrayPickling(self, arraytype):
         var = self.var
         msgvar = self.msgvar
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/IPDLUnitTestUtils.h
@@ -0,0 +1,27 @@
+
+#ifndef mozilla__ipdltest_IPDLUnitTestUtils
+#define mozilla__ipdltest_IPDLUnitTestUtils 1
+
+namespace mozilla {
+namespace _ipdltest {
+
+struct Bad {};
+
+} // namespace _ipdltest
+} // namespace mozilla
+
+namespace IPC {
+
+template<>
+struct ParamTraits<mozilla::_ipdltest::Bad>
+{
+  typedef mozilla::_ipdltest::Bad paramType;
+
+  // Defined in TestActorPunning.cpp.
+  static void Write(Message* aMsg, const paramType& aParam);
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+};
+
+} // namespace IPC
+
+#endif // mozilla__ipdltest_IPDLUnitTestUtils
--- a/ipc/ipdl/test/cxx/Makefile.in
+++ b/ipc/ipdl/test/cxx/Makefile.in
@@ -13,24 +13,26 @@ TOOL_DIRS += app
 
 MODULE = ipdlunittest
 
 EXPORTS_NAMESPACES = mozilla/_ipdltest
 EXPORTS_mozilla/_ipdltest =  \
   IPDLUnitTests.h  \
   IPDLUnitTestProcessChild.h  \
   IPDLUnitTestTypes.h \
+  IPDLUnitTestUtils.h \
   $(NULL)
 
 LIBRARY_NAME = $(MODULE)_s
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 
 IPDLTESTS = \
+  TestActorPunning \
   TestBlockChild \
   TestBridgeMain \
   TestCrashCleanup \
   TestDataStructures \
   TestDesc \
   TestFailedCtor \
   TestHangs \
   TestJSON \
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestActorPunning.ipdl
@@ -0,0 +1,39 @@
+
+include protocol PTestActorPunningPunned;
+include protocol PTestActorPunningSub;
+include "mozilla/_ipdltest/IPDLUnitTestUtils.h";
+
+using mozilla::_ipdltest::Bad;
+
+namespace mozilla {
+namespace _ipdltest {
+
+protocol PTestActorPunning {
+    manages PTestActorPunningPunned;
+    manages PTestActorPunningSub;
+
+child:
+    Start();
+
+parent:
+    PTestActorPunningPunned();
+    PTestActorPunningSub();
+    Pun(PTestActorPunningSub a, Bad bad);
+    __delete__();
+
+
+state PING:
+    send Start goto CONSTRUCTING;
+
+state CONSTRUCTING:
+    recv PTestActorPunningPunned goto CONSTRUCTING;
+    recv PTestActorPunningSub goto CONSTRUCTING;
+    recv Pun goto DEAD;
+    // We never make it past this transition, --> error.
+
+state DEAD:
+    recv __delete__;
+};
+
+} // namespace mozilla
+} // namespace _ipdltest
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestActorPunningPunned.ipdl
@@ -0,0 +1,15 @@
+
+include protocol PTestActorPunning;
+
+namespace mozilla {
+namespace _ipdltest {
+
+protocol PTestActorPunningPunned {
+    manager PTestActorPunning;
+
+child:
+    __delete__();
+};
+
+} // namespace mozilla
+} // namespace _ipdltes
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestActorPunningSub.ipdl
@@ -0,0 +1,16 @@
+
+include protocol PTestActorPunning;
+
+namespace mozilla {
+namespace _ipdltest {
+
+protocol PTestActorPunningSub {
+    manager PTestActorPunning;
+
+child:
+    Bad();
+    __delete__();
+};
+
+} // namespace mozilla
+} // namespace _ipdltes
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestActorPunning.cpp
@@ -0,0 +1,131 @@
+#include "TestActorPunning.h"
+
+#include "IPDLUnitTests.h"      // fail etc.
+
+namespace mozilla {
+namespace _ipdltest {
+
+//-----------------------------------------------------------------------------
+// parent
+
+void
+TestActorPunningParent::Main()
+{
+    if (!SendStart())
+        fail("sending Start");
+}
+
+bool
+TestActorPunningParent::RecvPun(PTestActorPunningSubParent* a, const Bad& bad)
+{
+    if (a->SendBad())
+        fail("bad!");
+    fail("shouldn't have received this message in the first place");
+    return true;
+}
+
+PTestActorPunningPunnedParent*
+TestActorPunningParent::AllocPTestActorPunningPunned()
+{
+    return new TestActorPunningPunnedParent();
+}
+
+bool
+TestActorPunningParent::DeallocPTestActorPunningPunned(PTestActorPunningPunnedParent* a)
+{
+    delete a;
+    return true;
+}
+
+PTestActorPunningSubParent*
+TestActorPunningParent::AllocPTestActorPunningSub()
+{
+    return new TestActorPunningSubParent();
+}
+
+bool
+TestActorPunningParent::DeallocPTestActorPunningSub(PTestActorPunningSubParent* a)
+{
+    delete a;
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+// child
+
+PTestActorPunningPunnedChild*
+TestActorPunningChild::AllocPTestActorPunningPunned()
+{
+    return new TestActorPunningPunnedChild();
+}
+
+bool
+TestActorPunningChild::DeallocPTestActorPunningPunned(PTestActorPunningPunnedChild*)
+{
+    fail("should have died by now");
+    return true;
+}
+
+PTestActorPunningSubChild*
+TestActorPunningChild::AllocPTestActorPunningSub()
+{
+    return new TestActorPunningSubChild();
+}
+
+bool
+TestActorPunningChild::DeallocPTestActorPunningSub(PTestActorPunningSubChild*)
+{
+    fail("should have died by now");
+    return true;
+}
+
+bool
+TestActorPunningChild::RecvStart()
+{
+    SendPTestActorPunningSubConstructor();
+    SendPTestActorPunningPunnedConstructor();
+    PTestActorPunningSubChild* a = SendPTestActorPunningSubConstructor();
+    // We can't assert whether this succeeds or fails, due to race
+    // conditions.
+    SendPun(a, Bad());
+    return true;
+}
+
+bool
+TestActorPunningSubChild::RecvBad()
+{
+    fail("things are going really badly right now");
+    return true;
+}
+
+
+} // namespace _ipdltest
+} // namespace mozilla
+
+namespace IPC {
+using namespace mozilla::_ipdltest;
+using namespace mozilla::ipc;
+
+/*static*/ void
+ParamTraits<Bad>::Write(Message* aMsg, const paramType& aParam)
+{
+    char* ptr = aMsg->BeginWriteData(4);
+    ptr -= intptr_t(sizeof(int));
+    ptr -= intptr_t(sizeof(ActorHandle));
+    ActorHandle* ah = reinterpret_cast<ActorHandle*>(ptr);
+    if (ah->mId != -3)
+        fail("guessed wrong offset (value is %d, should be -3)", ah->mId);
+    ah->mId = -2;
+}
+
+/*static*/ bool
+ParamTraits<Bad>::Read(const Message* aMsg, void** aIter, paramType* aResult)
+{
+    const char* ptr;
+    int len;
+    aMsg->ReadData(aIter, &ptr, &len);
+    return true;
+}
+
+} // namespace IPC
+
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestActorPunning.h
@@ -0,0 +1,106 @@
+#ifndef mozilla__ipdltest_TestActorPunning_h
+#define mozilla__ipdltest_TestActorPunning_h 1
+
+#include "mozilla/_ipdltest/IPDLUnitTests.h"
+
+#include "mozilla/_ipdltest/PTestActorPunningParent.h"
+#include "mozilla/_ipdltest/PTestActorPunningPunnedParent.h"
+#include "mozilla/_ipdltest/PTestActorPunningSubParent.h"
+#include "mozilla/_ipdltest/PTestActorPunningChild.h"
+#include "mozilla/_ipdltest/PTestActorPunningPunnedChild.h"
+#include "mozilla/_ipdltest/PTestActorPunningSubChild.h"
+
+namespace mozilla {
+namespace _ipdltest {
+
+
+class TestActorPunningParent :
+    public PTestActorPunningParent
+{
+public:
+    static bool RunTestInProcesses() { return true; }
+    static bool RunTestInThreads() { return false; }
+
+    void Main();
+
+protected:
+    PTestActorPunningPunnedParent* AllocPTestActorPunningPunned() MOZ_OVERRIDE;
+    bool DeallocPTestActorPunningPunned(PTestActorPunningPunnedParent* a) MOZ_OVERRIDE;
+
+    PTestActorPunningSubParent* AllocPTestActorPunningSub() MOZ_OVERRIDE;
+    bool DeallocPTestActorPunningSub(PTestActorPunningSubParent* a) MOZ_OVERRIDE;
+
+    virtual bool RecvPun(PTestActorPunningSubParent* a, const Bad& bad) MOZ_OVERRIDE;
+
+    virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
+    {
+        if (NormalShutdown == why)
+            fail("should have died from error!");  
+        passed("ok");
+        QuitParent();
+    }
+};
+
+class TestActorPunningPunnedParent :
+    public PTestActorPunningPunnedParent
+{
+public:
+    TestActorPunningPunnedParent() {}
+    virtual ~TestActorPunningPunnedParent() {}
+};
+
+class TestActorPunningSubParent :
+    public PTestActorPunningSubParent
+{
+public:
+    TestActorPunningSubParent() {}
+    virtual ~TestActorPunningSubParent() {}
+};
+
+
+class TestActorPunningChild :
+    public PTestActorPunningChild
+{
+public:
+    TestActorPunningChild() {}
+    virtual ~TestActorPunningChild() {}
+
+protected:
+    PTestActorPunningPunnedChild* AllocPTestActorPunningPunned() MOZ_OVERRIDE;
+    bool DeallocPTestActorPunningPunned(PTestActorPunningPunnedChild* a) MOZ_OVERRIDE;
+
+    PTestActorPunningSubChild* AllocPTestActorPunningSub() MOZ_OVERRIDE;
+    bool DeallocPTestActorPunningSub(PTestActorPunningSubChild* a) MOZ_OVERRIDE;
+
+    virtual bool RecvStart() MOZ_OVERRIDE;
+
+    virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
+    {
+        fail("should have been killed off!");
+    }
+};
+
+class TestActorPunningPunnedChild :
+    public PTestActorPunningPunnedChild
+{
+public:
+    TestActorPunningPunnedChild() {}
+    virtual ~TestActorPunningPunnedChild() {}
+};
+
+class TestActorPunningSubChild :
+    public PTestActorPunningSubChild
+{
+public:
+    TestActorPunningSubChild() {}
+    virtual ~TestActorPunningSubChild() {}
+
+    virtual bool RecvBad() MOZ_OVERRIDE;
+};
+
+
+} // namespace _ipdltest
+} // namespace mozilla
+
+
+#endif // ifndef mozilla__ipdltest_TestActorPunning_h
--- a/ipc/ipdl/test/cxx/ipdl.mk
+++ b/ipc/ipdl/test/cxx/ipdl.mk
@@ -1,9 +1,12 @@
 IPDLSRCS =					\
+  PTestActorPunning.ipdl			\
+  PTestActorPunningPunned.ipdl			\
+  PTestActorPunningSub.ipdl			\
   PTestBlockChild.ipdl				\
   PTestBridgeMain.ipdl				\
   PTestBridgeSub.ipdl				\
   PTestBridgeMainSub.ipdl			\
   PTestCrashCleanup.ipdl			\
   PTestDataStructures.ipdl			\
   PTestDataStructuresCommon.ipdlh		\
   PTestDataStructuresSub.ipdl			\
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -26,16 +26,30 @@ using namespace js::types;
 
 //
 // Utilities
 //
 
 typedef ParallelArrayObject::IndexVector IndexVector;
 typedef ParallelArrayObject::IndexInfo IndexInfo;
 
+static bool
+ReportMoreArgsNeeded(JSContext *cx, const char *name, const char *num, const char *p)
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED, name, num, p);
+    return false;
+}
+
+static bool
+ReportBadArg(JSContext *cx, const char *s = "")
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG, s);
+    return false;
+}
+
 bool
 ParallelArrayObject::IndexInfo::isInitialized() const
 {
     return (dimensions.length() > 0 &&
             indices.capacity() >= dimensions.length() &&
             partialProducts.length() == dimensions.length());
 }
 
@@ -461,18 +475,17 @@ ParallelArrayObject::SequentialMode::sca
 
         if (!GetElementFromArrayLikeObject(cx, targets, targetsPA, tiv, i, &telem) ||
             !ToUint32(cx, telem, &targetIndex))
         {
             return ExecutionFailed;
         }
 
         if (targetIndex >= length) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                 JSMSG_PAR_ARRAY_SCATTER_BOUNDS);
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_SCATTER_BOUNDS);
             return ExecutionFailed;
         }
 
         if (!source->getParallelArrayElement(cx, i, &iv, &elem))
             return ExecutionFailed;
 
         targetElem = buffer->getDenseArrayElement(targetIndex);
 
@@ -676,66 +689,61 @@ ParallelArrayObject::ExecutionStatusToSt
         return "success";
     }
     return "(unknown status)";
 }
 
 bool
 ParallelArrayObject::DebugOptions::init(JSContext *cx, const Value &v)
 {
-    if (!v.isObject())
+    RootedObject obj(cx, NonNullObject(cx, v));
+    if (!obj)
         return false;
 
-    RootedObject obj(cx, &v.toObject());
     RootedId id(cx);
     RootedValue propv(cx);
     JSString *propStr;
     JSBool match = false;
+    bool ok;
 
     id = AtomToId(Atomize(cx, "mode", strlen("mode")));
     if (!JSObject::getGeneric(cx, obj, obj, id, &propv))
         return false;
 
     propStr = ToString(cx, propv);
-    if (!JS_StringEqualsAscii(cx, propStr, "par", &match))
+    if (!propStr)
         return false;
-    if (match) {
+
+    if ((ok = JS_StringEqualsAscii(cx, propStr, "par", &match)) && match)
         mode = &parallel;
-    } else {
-        if (!JS_StringEqualsAscii(cx, propStr, "seq", &match))
-            return false;
-        if (match)
-            mode = &sequential;
-        else
-            return false;
-    }
+    else if (ok && (ok = JS_StringEqualsAscii(cx, propStr, "seq", &match)) && match)
+        mode = &sequential;
+    else if (ok)
+        return ReportBadArg(cx);
+    else
+        return false;
 
     id = AtomToId(Atomize(cx, "expect", strlen("expect")));
     if (!JSObject::getGeneric(cx, obj, obj, id, &propv))
         return false;
 
     propStr = ToString(cx, propv);
-    if (!JS_StringEqualsAscii(cx, propStr, "fail", &match))
+    if (!propStr)
         return false;
-    if (match) {
+
+    if ((ok = JS_StringEqualsAscii(cx, propStr, "fail", &match)) && match)
         expect = ExecutionFailed;
-    } else {
-        if (!JS_StringEqualsAscii(cx, propStr, "bail", &match))
-            return false;
-        if (match) {
-            expect = ExecutionCompiled;
-        } else {
-            if (!JS_StringEqualsAscii(cx, propStr, "success", &match))
-                return false;
-            if (match)
-                expect = ExecutionSucceeded;
-            else
-                return false;
-        }
-    }
+    else if (ok && (ok = JS_StringEqualsAscii(cx, propStr, "bail", &match)) && match)
+        expect = ExecutionCompiled;
+    else if (ok && (ok = JS_StringEqualsAscii(cx, propStr, "success", &match)) && match)
+        expect = ExecutionSucceeded;
+    else if (ok)
+        return ReportBadArg(cx);
+    else
+        return false;
 
     return true;
 }
 
 bool
 ParallelArrayObject::DebugOptions::check(JSContext *cx, ExecutionStatus actual)
 {
     if (expect != actual) {
@@ -1038,22 +1046,19 @@ ParallelArrayObject::construct(JSContext
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // Trivial case: create an empty ParallelArray object.
     if (args.length() < 1)
         return create(cx, args.rval());
 
     // First case: initialize using an array value.
     if (args.length() == 1) {
-        if (!args[0].isObject()) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG, "");
+        RootedObject source(cx, NonNullObject(cx, args[0]));
+        if (!source)
             return false;
-        }
-
-        RootedObject source(cx, &(args[0].toObject()));
 
         // When using an array value we can only make one dimensional arrays.
         IndexVector dims(cx);
         uint32_t length;
         if (!dims.resize(1) || !GetLengthProperty(cx, source, &length))
             return false;
         dims[0] = length;
 
@@ -1098,77 +1103,75 @@ ParallelArrayObject::construct(JSContext
     uint32_t length = iv.scalarLengthOfDimensions();
 
     // Create backing store.
     RootedObject buffer(cx, NewDenseArrayWithType(cx, length));
     if (!buffer)
         return false;
 
 #ifdef DEBUG
-    if (args.length() > 1) {
+    if (args.length() > 2) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->build(cx, iv, elementalFun, buffer)))
-                return false;
-            return create(cx, buffer, 0, iv.dimensions, args.rval());
+        if (!options.init(cx, args[2]) ||
+            !options.check(cx, options.mode->build(cx, iv, elementalFun, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, 0, iv.dimensions, args.rval());
     }
 #endif
 
     if (fallback.build(cx, iv, elementalFun, buffer) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, 0, iv.dimensions, args.rval());
 }
 
 bool
 ParallelArrayObject::map(JSContext *cx, CallArgs args)
 {
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "ParallelArray.prototype.map", "0", "s");
-        return false;
-    }
+    if (args.length() < 1)
+        return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.map", "0", "s");
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
 
     uint32_t outer = obj->outermostDimension();
     RootedObject buffer(cx, NewDenseArrayWithType(cx, outer));
     if (!buffer)
         return false;
 
     RootedObject elementalFun(cx, ValueToCallable(cx, &args[0]));
     if (!elementalFun)
         return false;
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->map(cx, obj, elementalFun, buffer)))
-                return false;
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[1]) ||
+            !options.check(cx, options.mode->map(cx, obj, elementalFun, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.map(cx, obj, elementalFun, buffer) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, args.rval());
 }
 
 bool
 ParallelArrayObject::reduce(JSContext *cx, CallArgs args)
 {
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "ParallelArray.prototype.reduce", "0", "s");
-        return false;
-    }
+    if (args.length() < 1)
+        return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.reduce", "0", "s");
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
     uint32_t outer = obj->outermostDimension();
 
     // Throw if the array is empty.
     if (outer == 0) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_REDUCE_EMPTY);
         return false;
@@ -1176,38 +1179,35 @@ ParallelArrayObject::reduce(JSContext *c
 
     RootedObject elementalFun(cx, ValueToCallable(cx, &args[0]));
     if (!elementalFun)
         return false;
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            return options.check(cx, options.mode->reduce(cx, obj, elementalFun, NullPtr(),
-                                                          args.rval()));
-        }
+        if (!options.init(cx, args[1]))
+            return false;
+
+        return options.check(cx, options.mode->reduce(cx, obj, elementalFun, NullPtr(),
+                                                      args.rval()));
     }
 #endif
 
     // Call reduce with a null destination buffer to not store intermediates.
     return fallback.reduce(cx, obj, elementalFun, NullPtr(), args.rval()) == ExecutionSucceeded;
 }
 
 bool
 ParallelArrayObject::scan(JSContext *cx, CallArgs args)
 {
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "ParallelArray.prototype.scan", "0", "s");
-        return false;
-    }
+    if (args.length() < 1)
+        return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.scan", "0", "s");
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
-
     uint32_t outer = obj->outermostDimension();
 
     // Throw if the array is empty.
     if (outer == 0) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_REDUCE_EMPTY);
         return false;
     }
 
@@ -1221,50 +1221,45 @@ ParallelArrayObject::scan(JSContext *cx,
 
     // Call reduce with a dummy out value to be discarded and a buffer to
     // store intermediates.
     RootedValue dummy(cx);
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->reduce(cx, obj, elementalFun, buffer, &dummy)))
-                return false;
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[1]) ||
+            !options.check(cx, options.mode->reduce(cx, obj, elementalFun, buffer, &dummy)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.reduce(cx, obj, elementalFun, buffer, &dummy) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, args.rval());
 }
 
 bool
 ParallelArrayObject::scatter(JSContext *cx, CallArgs args)
 {
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "ParallelArray.prototype.scatter", "0", "s");
-        return false;
-    }
-
-    if (!args[0].isObject()) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG,
-                             ".prototype.scatter");
-        return false;
-    }
+    if (args.length() < 1)
+        return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.scatter", "0", "s");
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
     uint32_t outer = obj->outermostDimension();
 
     // Get the scatter vector.
-    RootedObject targets(cx, &args[0].toObject());
+    RootedObject targets(cx, NonNullObject(cx, args[0]));
+    if (!targets)
+        return false;
 
     // The default value is optional and defaults to undefined.
     Value defaultValue;
     if (args.length() >= 2)
         defaultValue = args[1];
     else
         defaultValue.setUndefined();
 
@@ -1287,70 +1282,65 @@ ParallelArrayObject::scatter(JSContext *
     }
 
     // Create a destination buffer. Fail if we can't maintain denseness.
     RootedObject buffer(cx, NewDenseArrayWithType(cx, resultLength));
     if (!buffer)
         return false;
 
 #ifdef DEBUG
-    if (args.length() > 1) {
+    if (args.length() > 4) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->scatter(cx, obj, targets, defaultValue,
-                                                         conflictFun, buffer)))
-            {
-                return false;
-            }
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[4]) ||
+            !options.check(cx, options.mode->scatter(cx, obj, targets, defaultValue,
+                                                     conflictFun, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.scatter(cx, obj, targets, defaultValue,
                          conflictFun, buffer) != ExecutionSucceeded)
     {
         return false;
     }
 
     return create(cx, buffer, args.rval());
 }
 
 bool
 ParallelArrayObject::filter(JSContext *cx, CallArgs args)
 {
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "ParallelArray.prototype.filter", "0", "s");
-        return false;
-    }
-
-    if (!args[0].isObject()) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG,
-                             ".prototype.filter");
-        return false;
-    }
+    if (args.length() < 1)
+        return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.filter", "0", "s");
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
 
     // Get the filter vector.
-    RootedObject filters(cx, &args[0].toObject());
+    RootedObject filters(cx, NonNullObject(cx, args[0]));
+    if (!filters)
+        return false;
 
     RootedObject buffer(cx, NewDenseArrayWithType(cx, 0));
     if (!buffer)
         return false;
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->filter(cx, obj, filters, buffer)))
-                return false;
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[1]) ||
+            !options.check(cx, options.mode->filter(cx, obj, filters, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.filter(cx, obj, filters, buffer) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, args.rval());
 }
@@ -1376,21 +1366,18 @@ ParallelArrayObject::flatten(JSContext *
 
     RootedObject buffer(cx, obj->buffer());
     return create(cx, buffer, obj->bufferOffset(), dims, args.rval());
 }
 
 bool
 ParallelArrayObject::partition(JSContext *cx, CallArgs args)
 {
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "ParallelArray.prototype.partition", "0", "s");
-        return false;
-    }
+    if (args.length() < 1)
+        return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.partition", "0", "s");
 
     uint32_t newDimension;
     if (!ToUint32(cx, args[0], &newDimension))
         return false;
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
 
     // Throw if the outer dimension is not divisible by the new dimension.
@@ -1414,43 +1401,33 @@ ParallelArrayObject::partition(JSContext
 
     RootedObject buffer(cx, obj->buffer());
     return create(cx, buffer, obj->bufferOffset(), dims, args.rval());
 }
 
 bool
 ParallelArrayObject::get(JSContext *cx, CallArgs args)
 {
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "ParallelArray.prototype.get", "0", "s");
-        return false;
-    }
-
-    if (!args[0].isObject()) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG,
-                             ".prototype.get");
-        return false;
-    }
+    if (args.length() < 1)
+        return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.get", "0", "s");
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
-    RootedObject indicesObj(cx, &(args[0].toObject()));
+    RootedObject indicesObj(cx, NonNullObject(cx, args[0]));
+    if (!indicesObj)
+        return false;
 
     IndexInfo iv(cx);
     if (!iv.initialize(cx, obj, 0))
         return false;
     if (!ArrayLikeToIndexVector(cx, indicesObj, iv.indices))
         return false;
 
     // Throw if the shape of the index vector is wrong.
-    if (iv.indices.length() == 0 || iv.indices.length() > iv.dimensions.length()) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG,
-                             ".prototype.get");
-        return false;
-    }
+    if (iv.indices.length() == 0 || iv.indices.length() > iv.dimensions.length())
+        return ReportBadArg(cx, ".prototype.get");
 
     return obj->getParallelArrayElement(cx, iv, args.rval());
 }
 
 bool
 ParallelArrayObject::dimensionsGetter(JSContext *cx, CallArgs args)
 {
     args.rval().setObject(*(as(&args.thisv().toObject())->dimensionArray()));
--- a/js/src/config/makefiles/target_libs.mk
+++ b/js/src/config/makefiles/target_libs.mk
@@ -39,67 +39,96 @@ else
 EXPORT_LIBRARY = $(DEPTH)/staticlib
 endif
 else
 # If EXPORT_LIBRARY has a value, we'll be installing there. We also need to cleanup there
 GARBAGE += $(foreach lib,$(LIBRARY),$(EXPORT_LIBRARY)/$(lib))
 endif
 endif # EXPORT_LIBRARY
 
-libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
+libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
 ifndef NO_DIST_INSTALL
-ifdef LIBRARY
-ifdef EXPORT_LIBRARY # Stage libs that will be linked into a static build
-	$(INSTALL) $(IFLAGS1) $(LIBRARY) $(EXPORT_LIBRARY)
-endif # EXPORT_LIBRARY
-ifdef DIST_INSTALL
-ifdef IS_COMPONENT
-	$(error Shipping static component libs makes no sense.)
-else
-	$(INSTALL) $(IFLAGS1) $(LIBRARY) $(DIST)/lib
-endif
-endif # DIST_INSTALL
-endif # LIBRARY
 ifdef SHARED_LIBRARY
 ifdef IS_COMPONENT
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
 	$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
 ifndef NO_COMPONENTS_MANIFEST
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
 endif
-else # ! IS_COMPONENT
-ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
-ifndef NO_INSTALL_IMPORT_LIBRARY
-	$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
-endif
-else
-	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
-endif
-	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
 endif # IS_COMPONENT
 endif # SHARED_LIBRARY
-ifdef PROGRAM
-	$(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
-endif
-ifdef SIMPLE_PROGRAMS
-	$(INSTALL) $(IFLAGS2) $(SIMPLE_PROGRAMS) $(FINAL_TARGET)
-endif
-ifdef HOST_PROGRAM
-	$(INSTALL) $(IFLAGS2) $(HOST_PROGRAM) $(DIST)/host/bin
-endif
-ifdef HOST_SIMPLE_PROGRAMS
-	$(INSTALL) $(IFLAGS2) $(HOST_SIMPLE_PROGRAMS) $(DIST)/host/bin
-endif
-ifdef HOST_LIBRARY
-	$(INSTALL) $(IFLAGS1) $(HOST_LIBRARY) $(DIST)/host/lib
-endif
-ifdef JAVA_LIBRARY
-ifdef IS_COMPONENT
-	$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)/components
-else
-	$(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)
-endif
-endif # JAVA_LIBRARY
 endif # !NO_DIST_INSTALL
 	$(LOOP_OVER_DIRS)
 
+ifndef NO_DIST_INSTALL
+
+ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
+PROGRAMS_EXECUTABLES = $(SIMPLE_PROGRAMS) $(PROGRAM)
+PROGRAMS_DEST ?= $(FINAL_TARGET)
+INSTALL_TARGETS += PROGRAMS
+endif
+
+ifdef LIBRARY
+ifdef EXPORT_LIBRARY
+LIBRARY_FILES = $(LIBRARY)
+LIBRARY_DEST ?= $(EXPORT_LIBRARY)
+INSTALL_TARGETS += LIBRARY
+endif
+ifdef DIST_INSTALL
+ifdef IS_COMPONENT
+$(error Shipping static component libs makes no sense.)
+else
+DIST_LIBRARY_FILES = $(LIBRARY)
+DIST_LIBRARY_DEST ?= $(DIST)/lib
+INSTALL_TARGETS += DIST_LIBRARY
+endif
+endif # DIST_INSTALL
+endif # LIBRARY
+
+
+ifdef SHARED_LIBRARY
+ifndef IS_COMPONENT
+SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
+SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)
+INSTALL_TARGETS += SHARED_LIBRARY
+
+ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
+ifndef NO_INSTALL_IMPORT_LIBRARY
+IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
+endif # NO_INSTALL_IMPORT_LIBRARY
+else
+IMPORT_LIB_FILES = $(SHARED_LIBRARY)
+endif
+
+IMPORT_LIB_DEST ?= $(DIST)/lib
+ifdef IMPORT_LIB_FILES
+INSTALL_TARGETS += IMPORT_LIB
+endif
+
+endif # ! IS_COMPONENT
+endif # SHARED_LIBRARY
+
+ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)$(HOST_PROGRAM)))
+HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_PROGRAM)
+HOST_PROGRAMS_DEST ?= $(DIST)/host/bin
+INSTALL_TARGETS += HOST_PROGRAMS
+endif
+
+ifdef HOST_LIBRARY
+HOST_LIBRARY_FILES = $(HOST_LIBRARY)
+HOST_LIBRARY_DEST ?= $(DIST)/host/lib
+INSTALL_TARGETS += HOST_LIBRARY
+endif
+
+ifdef JAVA_LIBRARY
+JAVA_LIBRARY_FILES = $(JAVA_LIBRARY)
+ifdef IS_COMPONENT
+JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)/components
+else
+JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)
+endif
+INSTALL_TARGETS += JAVA_LIBRARY
+endif
+
+endif # !NO_DIST_INSTALL
+
 # EOF
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -57,22 +57,16 @@ else
   ELOG :=
 endif # -s
 else
   ELOG :=
 endif # ifndef .PYMAKE
 
 _VPATH_SRCS = $(abspath $<)
 
-# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
-VPATH += $(DIST)/lib
-ifdef LIBXUL_SDK
-VPATH += $(LIBXUL_SDK)/lib
-endif
-
 ifdef EXTRA_DSO_LIBS
 EXTRA_DSO_LIBS	:= $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
 endif
 
 ################################################################################
 # Testing frameworks support
 ################################################################################
 
@@ -1604,19 +1598,16 @@ endif
 .PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE
 
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
-# Properly set LIBPATTERNS for the platform
-.LIBPATTERNS = $(if $(IMPORT_LIB_SUFFIX),$(LIB_PREFIX)%.$(IMPORT_LIB_SUFFIX)) $(LIB_PREFIX)%.$(LIB_SUFFIX) $(DLL_PREFIX)%$(DLL_SUFFIX)
-
 tags: TAGS
 
 TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	-etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 
 ifndef INCLUDED_DEBUGMAKE_MK #{
--- a/js/src/config/version_win.pl
+++ b/js/src/config/version_win.pl
@@ -229,17 +229,17 @@ for ($j = 1; $j < 4; $j++)
         $appver[$j] = "0";
     }
     else {
         $appver[$j] =~s/\D.*$//;
     }
 }
 my $winappversion = "$appver[0],$appver[1],$appver[2],$appver[3]";
 
-my $copyright = "License: MPL 1.1/GPL 2.0/LGPL 2.1";
+my $copyright = "License: MPL 2";
 my $company = "Mozilla Foundation";
 my $trademarks = "Mozilla";
 my $productname = $displayname;
 
 
 if (defined($override_comment)){$override_comment =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $comment=$override_comment;}
 if (defined($override_description)){$override_description =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $description=$override_description;}
 if (defined($override_fileversion)){$override_fileversion =~ s/\@MOZ_APP_WINVERSION\@/$winappversion/g; $fileversion=$override_fileversion;}
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -2609,17 +2609,17 @@ IonBuilder::pushConstant(const Value &v)
 
 bool
 IonBuilder::jsop_bitnot()
 {
     MDefinition *input = current->pop();
     MBitNot *ins = MBitNot::New(input);
 
     current->add(ins);
-    ins->infer(oracle->unaryOp(script, pc));
+    ins->infer(oracle->unaryTypes(script, pc));
 
     current->push(ins);
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
     return true;
 }
 bool
 IonBuilder::jsop_bitop(JSOp op)
@@ -2655,17 +2655,17 @@ IonBuilder::jsop_bitop(JSOp op)
         break;
 
       default:
         JS_NOT_REACHED("unexpected bitop");
         return false;
     }
 
     current->add(ins);
-    ins->infer(oracle->binaryOp(script, pc));
+    ins->infer(oracle->binaryTypes(script, pc));
 
     current->push(ins);
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
 
     return true;
 }
 
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -483,19 +483,19 @@ MCall::addArg(size_t argnum, MPassArg *a
 {
     // The operand vector is initialized in reverse order by the IonBuilder.
     // It cannot be checked for consistency until all arguments are added.
     arg->setArgnum(argnum);
     MNode::initOperand(argnum + NumNonArgumentOperands, arg->toDefinition());
 }
 
 void
-MBitNot::infer(const TypeOracle::Unary &u)
+MBitNot::infer(const TypeOracle::UnaryTypes &u)
 {
-    if (u.ival == MIRType_Object)
+    if (u.inTypes->maybeObject())
         specialization_ = MIRType_None;
     else
         specialization_ = MIRType_Int32;
 }
 
 static inline bool
 IsConstant(MDefinition *def, double v)
 {
@@ -528,45 +528,45 @@ MBinaryBitwiseInstruction::foldsTo(bool 
 
     if (EqualValues(useValueNumbers, lhs, rhs))
         return foldIfEqual();
 
     return this;
 }
 
 void
-MBinaryBitwiseInstruction::infer(const TypeOracle::Binary &b)
+MBinaryBitwiseInstruction::infer(const TypeOracle::BinaryTypes &b)
 {
-    if (b.lhs == MIRType_Object || b.rhs == MIRType_Object) {
+    if (b.lhsTypes->maybeObject() || b.rhsTypes->maybeObject()) {
         specialization_ = MIRType_None;
     } else {
         specialization_ = MIRType_Int32;
         setCommutative();
     }
 }
 
 void
-MShiftInstruction::infer(const TypeOracle::Binary &b)
+MShiftInstruction::infer(const TypeOracle::BinaryTypes &b)
 {
-    if (b.lhs == MIRType_Object || b.rhs == MIRType_Object)
+    if (b.lhsTypes->maybeObject() || b.rhsTypes->maybeObject())
         specialization_ = MIRType_None;
     else
         specialization_ = MIRType_Int32;
 }
 
 void
-MUrsh::infer(const TypeOracle::Binary &b)
+MUrsh::infer(const TypeOracle::BinaryTypes &b)
 {
-    if (b.lhs == MIRType_Object || b.rhs == MIRType_Object) {
+    if (b.lhsTypes->maybeObject() || b.rhsTypes->maybeObject()) {
         specialization_ = MIRType_None;
         setResultType(MIRType_Value);
         return;
     }
 
-    if (b.rval == MIRType_Double) {
+    if (b.outTypes->getKnownTypeTag() == JSVAL_TYPE_DOUBLE) {
         specialization_ = MIRType_Double;
         setResultType(MIRType_Double);
         return;
     }
 
     specialization_ = MIRType_Int32;
     JS_ASSERT(type() == MIRType_Int32);
 }
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -1787,17 +1787,17 @@ class MBitNot
     INSTRUCTION_HEADER(BitNot);
     static MBitNot *New(MDefinition *input);
 
     TypePolicy *typePolicy() {
         return this;
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
-    void infer(const TypeOracle::Unary &u);
+    void infer(const TypeOracle::UnaryTypes &u);
 
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         if (specialization_ == MIRType_None)
             return AliasSet::Store(AliasSet::Any);
         return AliasSet::None();
@@ -1883,17 +1883,17 @@ class MBinaryBitwiseInstruction
     TypePolicy *typePolicy() {
         return this;
     }
 
     MDefinition *foldsTo(bool useValueNumbers);
     virtual MDefinition *foldIfZero(size_t operand) = 0;
     virtual MDefinition *foldIfNegOne(size_t operand) = 0;
     virtual MDefinition *foldIfEqual()  = 0;
-    virtual void infer(const TypeOracle::Binary &b);
+    virtual void infer(const TypeOracle::BinaryTypes &b);
 
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         if (specialization_ >= MIRType_Object)
             return AliasSet::Store(AliasSet::Any);
         return AliasSet::None();
@@ -1973,17 +1973,17 @@ class MShiftInstruction
 
   public:
     MDefinition *foldIfNegOne(size_t operand) {
         return this;
     }
     MDefinition *foldIfEqual() {
         return this;
     }
-    virtual void infer(const TypeOracle::Binary &b);
+    virtual void infer(const TypeOracle::BinaryTypes &b);
 };
 
 class MLsh : public MShiftInstruction
 {
     MLsh(MDefinition *left, MDefinition *right)
       : MShiftInstruction(left, right)
     { }
 
@@ -2050,17 +2050,17 @@ class MUrsh : public MShiftInstruction
     MDefinition *foldIfZero(size_t operand) {
         // 0 >>> x => 0
         if (operand == 0)
             return getOperand(0);
 
         return this;
     }
 
-    void infer(const TypeOracle::Binary &b);
+    void infer(const TypeOracle::BinaryTypes &b);
 
     bool canOverflow() {
         // solution is only negative when lhs < 0 and rhs & 0x1f == 0
         MDefinition *lhs = getOperand(0);
         MDefinition *rhs = getOperand(1);
 
         if (lhs->isConstant()) {
             Value lhsv = lhs->toConstant()->value();
--- a/js/src/ion/arm/MacroAssembler-arm.cpp
+++ b/js/src/ion/arm/MacroAssembler-arm.cpp
@@ -2079,26 +2079,26 @@ MacroAssemblerARMCompat::testPrimitive(A
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testGCThing(Assembler::Condition cond, const Address &address)
 {
     JS_ASSERT(cond == Equal || cond == NotEqual);
     extractTag(address, ScratchRegister);
     ma_cmp(ScratchRegister, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
-    return cond;
+    return cond == Equal ? AboveOrEqual : Below;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testGCThing(Assembler::Condition cond, const BaseIndex &address)
 {
     JS_ASSERT(cond == Equal || cond == NotEqual);
     extractTag(address, ScratchRegister);
     ma_cmp(ScratchRegister, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
-    return cond;
+    return cond == Equal ? AboveOrEqual : Below;
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testMagic(Assembler::Condition cond, const Address &address)
 {
     JS_ASSERT(cond == Equal || cond == NotEqual);
     extractTag(address, ScratchRegister);
     ma_cmp(ScratchRegister, ImmTag(JSVAL_TAG_MAGIC));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug789420.js
@@ -0,0 +1,38 @@
+function g1(x, y) {
+    return 0 & y;
+}
+var c1 = 0;
+function f1() {
+    for (var i=0; i<100; i++) {
+        g1(i, i);
+        g1(i, {valueOf: function() { c1++; return 0; }});
+    }
+}
+f1();
+assertEq(c1, 100);
+
+function g2(x, y) {
+    ~y;
+}
+var c2 = 0;
+function f2() {
+    for (var i=0; i<100; i++) {
+        g2(i, i);
+        g2(i, {valueOf: function() { c2++; return 0; }});
+    }
+}
+f2();
+assertEq(c2, 100);
+
+function g3(x, y) {
+    return 0 >>> y;
+}
+var c3 = 0;
+function f3() {
+    for (var i=0; i<100; i++) {
+        g3(i, i);
+        g3(i, {valueOf: function() { c3++; return 0; }});
+    }
+}
+f3();
+assertEq(c3, 100);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3752,16 +3752,19 @@ PartitionCompartments::processNode(Node 
         } while (w != v);
         nextSCC++;
     }
 }
 
 void
 PartitionCompartments::partition()
 {
+    if (failed())
+        return;
+
     for (Node n = 0; n < runtime->compartments.length(); n++) {
         if (discoveryTime[n] == Undefined)
             processNode(n);
     }
 }
 
 static void
 BeginSweepPhase(JSRuntime *rt)
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -488,16 +488,19 @@ class StackTypeSet : public TypeSet
      * to new type information, the script's jitcode will be discarded.
      */
 
     /* Get any type tag which all values in this set must have. */
     JSValueType getKnownTypeTag();
 
     bool isMagicArguments() { return getKnownTypeTag() == JSVAL_TYPE_MAGIC; }
 
+    /* Whether this value may be an object. */
+    bool maybeObject() { return unknownObject() || baseObjectCount() > 0; }
+
     /* Whether the type set contains objects with any of a set of flags. */
     bool hasObjectFlags(JSContext *cx, TypeObjectFlags flags);
 
     /*
      * Get the typed array type of all objects in this set. Returns
      * TypedArray::TYPE_MAX if the set contains different array types.
      */
     int getTypedArrayType();
--- a/js/src/tests/browser.js
+++ b/js/src/tests/browser.js
@@ -158,31 +158,32 @@ function options(aOptionName)
     value = value.substring(0, value.length-1);
   }
 
   if (aOptionName === 'moar_xml')
     aOptionName = 'xml';
 
   if (aOptionName && aOptionName !== 'allow_xml') {
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-    if (!(aOptionName in Components.utils))
-    {
+    if (!(aOptionName in Components.utils)) {
+//    if (!(aOptionName in SpecialPowers.wrap(Components).utils)) {
       // This test is trying to flip an unsupported option, so it's
       // likely no longer testing what it was supposed to.  Fail it
       // hard.
       throw "Unsupported JSContext option '"+ aOptionName +"'";
     }
 
     if (options.currvalues.hasOwnProperty(aOptionName))
       // option is set, toggle it to unset
       delete options.currvalues[aOptionName];
     else
       // option is not set, toggle it to set
       options.currvalues[aOptionName] = true;
 
+//    SpecialPowers.wrap(Components).utils[aOptionName] = options.currvalues.hasOwnProperty(aOptionName);
     Components.utils[aOptionName] =
       options.currvalues.hasOwnProperty(aOptionName);
   }  
 
   return value;
 }
 
 function optionsInit() {
@@ -209,20 +210,22 @@ function optionsInit() {
 
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   for (var optionName in options.currvalues)
   {
     var propName = optionName;
     if (optionName === "moar_xml")
       propName = "xml";
 
+//    if (!(propName in SpecialPowers.wrap(Components).utils))
     if (!(propName in Components.utils))
     {
       throw "options.currvalues is out of sync with Components.utils";
     }
+//    if (!SpecialPowers.wrap(Components).utils[propName])
     if (!Components.utils[propName])
     {
       delete options.currvalues[optionName];
     }
     else
     {
       options.initvalues[optionName] = true;
     }
@@ -454,123 +457,70 @@ var dlog = (function (s) {});
 
 // dialog closer from http://bclary.com/projects/spider/spider/chrome/content/spider/dialog-closer.js
 
 var gDialogCloser;
 var gDialogCloserObserver;
 
 function registerDialogCloser()
 {
-  dlog('registerDialogCloser: start');
-  try
-  {
-    netscape.security.PrivilegeManager.
-      enablePrivilege('UniversalXPConnect');
-  }
-  catch(excp)
-  {
-    print('registerDialogCloser: ' + excp);
-    return;
-  }
-
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+//  gDialogCloser = SpecialPowers.wrap(Components).
   gDialogCloser = Components.
     classes['@mozilla.org/embedcomp/window-watcher;1'].
     getService(Components.interfaces.nsIWindowWatcher);
 
   gDialogCloserObserver = {observe: dialogCloser_observe};
 
   gDialogCloser.registerNotification(gDialogCloserObserver);
-
-  dlog('registerDialogCloser: complete');
 }
 
 function unregisterDialogCloser()
 {
-  dlog('unregisterDialogCloser: start');
-
   gczeal(0);
 
   if (!gDialogCloserObserver || !gDialogCloser)
   {
     return;
   }
-  try
-  {
-    netscape.security.PrivilegeManager.
-      enablePrivilege('UniversalXPConnect');
-  }
-  catch(excp)
-  {
-    print('unregisterDialogCloser: ' + excp);
-    return;
-  }
 
   gDialogCloser.unregisterNotification(gDialogCloserObserver);
 
   gDialogCloserObserver = null;
   gDialogCloser = null;
-
-  dlog('unregisterDialogCloser: stop');
 }
 
 // use an array to handle the case where multiple dialogs
 // appear at one time
 var gDialogCloserSubjects = [];
 
 function dialogCloser_observe(subject, topic, data)
 {
-  try
-  {
-    netscape.security.PrivilegeManager.
-      enablePrivilege('UniversalXPConnect');
-
-    dlog('dialogCloser_observe: ' +
-         'subject: ' + subject + 
-         ', topic=' + topic + 
-         ', data=' + data + 
-         ', subject.document.documentURI=' + subject.document.documentURI +
-         ', subjects pending=' + gDialogCloserSubjects.length);
-  }
-  catch(excp)
-  {
-    print('dialogCloser_observe: ' + excp);
-    return;
-  }
-
   if (subject instanceof ChromeWindow && topic == 'domwindowopened' )
   {
     gDialogCloserSubjects.push(subject);
     // timeout of 0 needed when running under reftest framework.
     subject.setTimeout(closeDialog, 0);
   }
-  dlog('dialogCloser_observe: subjects pending: ' + gDialogCloserSubjects.length);
 }
 
 function closeDialog()
 {
   var subject;
-  dlog('closeDialog: subjects pending: ' + gDialogCloserSubjects.length);
 
   while ( (subject = gDialogCloserSubjects.pop()) != null)
   {
-    dlog('closeDialog: subject=' + subject);
-
-    dlog('closeDialog: subject.document instanceof XULDocument: ' + (subject.document instanceof XULDocument));
-    dlog('closeDialog: subject.document.documentURI: ' + subject.document.documentURI);
-
     if (subject.document instanceof XULDocument && 
         subject.document.documentURI == 'chrome://global/content/commonDialog.xul')
     {
-      dlog('closeDialog: close XULDocument dialog?');
       subject.close();
     }
     else
     {
       // alerts inside of reftest framework are not XULDocument dialogs.
-      dlog('closeDialog: close chrome dialog?');
       subject.close();
     }
   }
 }
 
 registerDialogCloser();
 window.addEventListener('unload', unregisterDialogCloser, true);
 
--- a/js/src/tests/e4x/QName/regress-619529.js
+++ b/js/src/tests/e4x/QName/regress-619529.js
@@ -1,9 +1,10 @@
 // |reftest| pref(javascript.options.xml.content,true)
+// |reftest| skip
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  */
 
 var b = Proxy.create({ enumerateOwn: function () { @f; }});
 Object.freeze(this);
--- a/js/src/tests/ecma_5/Global/adding-global-var-nonextensible-error.js
+++ b/js/src/tests/ecma_5/Global/adding-global-var-nonextensible-error.js
@@ -1,9 +1,9 @@
-// |reftest| fails-if(!xulRuntime.shell)
+// |reftest| skip
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 621432;
 var summary =
   "If a var statement can't create a global property because the global " +
   "object isn't extensible, and an error is thrown while decompiling the " +
--- a/js/src/tests/js1_5/extensions/regress-369696-02.js
+++ b/js/src/tests/js1_5/extensions/regress-369696-02.js
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 369696;
 var summary = 'Do not assert: map->depth > 0" in js_LeaveSharpObject';
 var actual = '';
 var expect = '';
 
+// Bug 762908 requires us to set sp=null;
+window.SpecialPowers = null;
 
 //-----------------------------------------------------------------------------
 test();
 //-----------------------------------------------------------------------------
 
 function test()
 {
   enterFunc ('test');
--- a/js/src/tests/js1_8_5/extensions/set-property-non-extensible.js
+++ b/js/src/tests/js1_8_5/extensions/set-property-non-extensible.js
@@ -1,8 +1,9 @@
+// |reftest| skip
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 600128;
 var summary =
   "Properly handle attempted addition of properties to non-extensible objects";
 
--- a/js/src/tests/js1_8_5/regress/regress-633741.js
+++ b/js/src/tests/js1_8_5/regress/regress-633741.js
@@ -1,8 +1,9 @@
+// |reftest| skip
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  * Contributors: Jan de Mooij
  */
 
 Object.preventExtensions(this);
 delete Function;
--- a/js/xpconnect/src/XPCCallContext.cpp
+++ b/js/xpconnect/src/XPCCallContext.cpp
@@ -319,67 +319,20 @@ XPCCallContext::~XPCCallContext()
             NS_ASSERTION(!XPCJSRuntime::Get()->GetJSContextStack()->
                          DEBUG_StackHasJSContext(mJSContext),
                          "JSContext still in threadjscontextstack!");
 
             JS_DestroyContext(mJSContext);
         }
     }
 
-#ifdef DEBUG
-    for (uint32_t i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) {
-        NS_ASSERTION(!mScratchStrings[i].mInUse, "Uh, string wrapper still in use!");
-    }
-#endif
-
     if (shouldReleaseXPC && mXPC)
         NS_RELEASE(mXPC);
 }
 
-XPCReadableJSStringWrapper *
-XPCCallContext::NewStringWrapper(const PRUnichar *str, uint32_t len)
-{
-    for (uint32_t i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) {
-        StringWrapperEntry& ent = mScratchStrings[i];
-
-        if (!ent.mInUse) {
-            ent.mInUse = true;
-
-            // Construct the string using placement new.
-
-            return new (ent.mString.addr()) XPCReadableJSStringWrapper(str, len);
-        }
-    }
-
-    // All our internal string wrappers are used, allocate a new string.
-
-    return new XPCReadableJSStringWrapper(str, len);
-}
-
-void
-XPCCallContext::DeleteString(nsAString *string)
-{
-    for (uint32_t i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) {
-        StringWrapperEntry& ent = mScratchStrings[i];
-        if (string == ent.mString.addr()) {
-            // One of our internal strings is no longer in use, mark
-            // it as such and destroy the string.
-
-            ent.mInUse = false;
-            ent.mString.addr()->~XPCReadableJSStringWrapper();
-
-            return;
-        }
-    }
-
-    // We're done with a string that's not one of our internal
-    // strings, delete it.
-    delete string;
-}
-
 /* readonly attribute nsISupports Callee; */
 NS_IMETHODIMP
 XPCCallContext::GetCallee(nsISupports * *aCallee)
 {
     nsISupports* temp = mWrapper ? mWrapper->GetIdentityObject() : nullptr;
     NS_IF_ADDREF(temp);
     *aCallee = temp;
     return NS_OK;
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -1398,17 +1398,20 @@ nsXPCComponents_Results::NewResolve(nsIX
     JSAutoByteString name;
 
     if (JSID_IS_STRING(id) && name.encode(cx, JSID_TO_STRING(id))) {
         const char* rv_name;
         void* iter = nullptr;
         nsresult rv;
         while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) {
             if (!strcmp(name.ptr(), rv_name)) {
-                jsval val = JS_NumberValue((double)rv);
+                // The double cast below is required since nsresult is an enum,
+                // and it can be interpreted as a signed integer if we directly
+                // cast to a double.
+                jsval val = JS_NumberValue((double)(uint32_t)rv);
 
                 *objp = obj;
                 if (!JS_DefinePropertyById(cx, obj, id, val,
                                            nullptr, nullptr,
                                            JSPROP_ENUMERATE |
                                            JSPROP_READONLY |
                                            JSPROP_PERMANENT)) {
                     return NS_ERROR_UNEXPECTED;
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -360,25 +360,23 @@ CheckJSCharInCharRange(jschar c)
 template<typename T>
 bool ConvertToPrimitive(JSContext *cx, const JS::Value& v, T *retval)
 {
     return ValueToPrimitive<T, eDefault>(cx, v, retval);
 }
 
 // static
 JSBool
-XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
+XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
                           const nsXPTType& type,
                           JSBool useAllocator, const nsID* iid,
                           nsresult* pErr)
 {
     NS_PRECONDITION(d, "bad param");
 
-    JSContext* cx = ccx.GetJSContext();
-
     JSBool isDOMString = true;
 
     if (pErr)
         *pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
 
     switch (type.TagPart()) {
     case nsXPTType::T_I8     :
         return ConvertToPrimitive(cx, s, static_cast<int8_t*>(d));
@@ -510,17 +508,17 @@ XPCConvert::JSData2Native(XPCCallContext
             // XXX extra string copy when isNewString
             if (str && !isNewString) {
                 size_t strLength;
                 const jschar *strChars = JS_GetStringCharsZAndLength(cx, str, &strLength);
                 if (!strChars)
                     return false;
 
                 XPCReadableJSStringWrapper *wrapper =
-                    ccx.NewStringWrapper(strChars, strLength);
+                    nsXPConnect::GetRuntimeInstance()->NewStringWrapper(strChars, strLength);
                 if (!wrapper)
                     return false;
 
                 *((const nsAString**)d) = wrapper;
             } else if (JSVAL_IS_NULL(s)) {
                 XPCReadableJSStringWrapper *wrapper =
                     new XPCReadableJSStringWrapper();
                 if (!wrapper)
@@ -710,17 +708,17 @@ XPCConvert::JSData2Native(XPCCallContext
     }
 
     case nsXPTType::T_INTERFACE:
     case nsXPTType::T_INTERFACE_IS:
     {
         NS_ASSERTION(iid,"can't do interface conversions without iid");
 
         if (iid->Equals(NS_GET_IID(nsIVariant))) {
-            XPCVariant* variant = XPCVariant::newVariant(ccx, s);
+            XPCVariant* variant = XPCVariant::newVariant(cx, s);
             if (!variant)
                 return false;
             *((nsISupports**)d) = static_cast<nsIVariant*>(variant);
             return true;
         } else if (iid->Equals(NS_GET_IID(nsIAtom)) &&
                    JSVAL_IS_STRING(s)) {
             // We're trying to pass a string as an nsIAtom.  Let's atomize!
             JSString* str = JSVAL_TO_STRING(s);
@@ -747,17 +745,17 @@ XPCConvert::JSData2Native(XPCCallContext
 
         // only wrap JSObjects
         if (!s.isObject()) {
             if (pErr && s.isInt32() && 0 == s.toInt32())
                 *pErr = NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL;
             return false;
         }
 
-        return JSObject2NativeInterface(ccx, (void**)d, &s.toObject(), iid,
+        return JSObject2NativeInterface(cx, (void**)d, &s.toObject(), iid,
                                         nullptr, pErr);
     }
     default:
         NS_ERROR("bad type");
         return false;
     }
     return true;
 }
@@ -1005,27 +1003,26 @@ XPCConvert::NativeInterface2JSObject(XPC
 
     return true;
 }
 
 /***************************************************************************/
 
 // static
 JSBool
-XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx,
+XPCConvert::JSObject2NativeInterface(JSContext* cx,
                                      void** dest, JSObject* src,
                                      const nsID* iid,
                                      nsISupports* aOuter,
                                      nsresult* pErr)
 {
     NS_ASSERTION(dest, "bad param");
     NS_ASSERTION(src, "bad param");
     NS_ASSERTION(iid, "bad param");
 
-    JSContext* cx = ccx.GetJSContext();
     JSAutoCompartment ac(cx, src);
 
     *dest = nullptr;
      if (pErr)
         *pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
 
     nsISupports* iface;
 
@@ -1073,17 +1070,17 @@ XPCConvert::JSObject2NativeInterface(XPC
 
             return false;
         }
     }
 
     // else...
 
     nsXPCWrappedJS* wrapper;
-    nsresult rv = nsXPCWrappedJS::GetNewOrUsed(ccx, src, *iid, aOuter, &wrapper);
+    nsresult rv = nsXPCWrappedJS::GetNewOrUsed(cx, src, *iid, aOuter, &wrapper);
     if (pErr)
         *pErr = rv;
     if (NS_SUCCEEDED(rv) && wrapper) {
         // We need to go through the QueryInterface logic to make this return
         // the right thing for the various 'special' interfaces; e.g.
         // nsIPropertyBag. We must use AggregatedQueryInterface in cases where
         // there is an outer to avoid nasty recursion.
         rv = aOuter ? wrapper->AggregatedQueryInterface(*iid, dest) :
@@ -1529,26 +1526,25 @@ CheckTargetAndPopulate(JSContext *cx,
 // JSarray2Native whenever a TypedArray is met. ArrayBuffers
 // are not accepted; create a properly typed array view on them
 // first. The element type of array must match the XPCOM
 // type in size, type and signedness exactly. As an exception,
 // Uint8ClampedArray is allowed for arrays of uint8_t.
 
 // static
 JSBool
-XPCConvert::JSTypedArray2Native(XPCCallContext& ccx,
+XPCConvert::JSTypedArray2Native(JSContext* cx,
                                 void** d,
                                 JSObject* jsArray,
                                 uint32_t count,
                                 const nsXPTType& type,
                                 nsresult* pErr)
 {
     NS_ABORT_IF_FALSE(jsArray, "bad param");
     NS_ABORT_IF_FALSE(d, "bad param");
-    JSContext* cx = ccx.GetJSContext();
     NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(jsArray, cx), "not a typed array");
 
     // Check the actual length of the input array against the
     // given size_is.
     uint32_t len = JS_GetTypedArrayLength(jsArray, cx);
     if (len < count) {
         if (pErr)
             *pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
@@ -1636,24 +1632,22 @@ XPCConvert::JSTypedArray2Native(XPCCallC
     if (pErr)
         *pErr = NS_OK;
 
     return true;
 }
 
 // static
 JSBool
-XPCConvert::JSArray2Native(XPCCallContext& ccx, void** d, JS::Value s,
+XPCConvert::JSArray2Native(JSContext* cx, void** d, JS::Value s,
                            uint32_t count, const nsXPTType& type,
                            const nsID* iid, nsresult* pErr)
 {
     NS_ABORT_IF_FALSE(d, "bad param");
 
-    JSContext* cx = ccx.GetJSContext();
-
     // XXX add support for getting chars from strings
 
     // XXX add support to indicate *which* array element was not convertable
 
     if (s.isNullOrUndefined()) {
         if (0 != count) {
             if (pErr)
                 *pErr = NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY;
@@ -1669,17 +1663,17 @@ XPCConvert::JSArray2Native(XPCCallContex
             *pErr = NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY;
         return false;
     }
 
     JSObject* jsarray = &s.toObject();
 
     // If this is a typed array, then try a fast conversion with memcpy.
     if (JS_IsTypedArrayObject(jsarray, cx)) {
-        return JSTypedArray2Native(ccx, d, jsarray, count, type, pErr);
+        return JSTypedArray2Native(cx, d, jsarray, count, type, pErr);
     }
 
     if (!JS_IsArrayObject(cx, jsarray)) {
         if (pErr)
             *pErr = NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY;
         return false;
     }
 
@@ -1700,17 +1694,17 @@ XPCConvert::JSArray2Native(XPCCallContex
         if (count > max ||                                                    \
             nullptr == (array = nsMemory::Alloc(count * sizeof(_t)))) {        \
             if (pErr)                                                         \
                 *pErr = NS_ERROR_OUT_OF_MEMORY;                               \
             goto failure;                                                     \
         }                                                                     \
         for (initedCount = 0; initedCount < count; initedCount++) {           \
             if (!JS_GetElement(cx, jsarray, initedCount, &current) ||         \
-                !JSData2Native(ccx, ((_t*)array)+initedCount, current, type,  \
+                !JSData2Native(cx, ((_t*)array)+initedCount, current, type,  \
                                true, iid, pErr))                              \
                 goto failure;                                                 \
         }                                                                     \
     PR_END_MACRO
 
     // No Action, FRee memory, RElease object
     enum CleanupMode {na, fr, re};
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -991,16 +991,57 @@ XPCJSRuntime::SizeOfIncludingThis(nsMall
 
     // There are other XPCJSRuntime members that could be measured; the above
     // ones have been seen by DMD to be worth measuring.  More stuff may be
     // added later.
 
     return n;
 }
 
+XPCReadableJSStringWrapper *
+XPCJSRuntime::NewStringWrapper(const PRUnichar *str, uint32_t len)
+{
+    for (uint32_t i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) {
+        StringWrapperEntry& ent = mScratchStrings[i];
+
+        if (!ent.mInUse) {
+            ent.mInUse = true;
+
+            // Construct the string using placement new.
+
+            return new (ent.mString.addr()) XPCReadableJSStringWrapper(str, len);
+        }
+    }
+
+    // All our internal string wrappers are used, allocate a new string.
+
+    return new XPCReadableJSStringWrapper(str, len);
+}
+
+void
+XPCJSRuntime::DeleteString(nsAString *string)
+{
+    for (uint32_t i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) {
+        StringWrapperEntry& ent = mScratchStrings[i];
+        if (string == ent.mString.addr()) {
+            // One of our internal strings is no longer in use, mark
+            // it as such and destroy the string.
+
+            ent.mInUse = false;
+            ent.mString.addr()->~XPCReadableJSStringWrapper();
+
+            return;
+        }
+    }
+
+    // We're done with a string that's not one of our internal
+    // strings, delete it.
+    delete string;
+}
+
 /***************************************************************************/
 
 #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
 static JSDHashOperator
 DEBUG_WrapperChecker(JSDHashTable *table, JSDHashEntryHdr *hdr,
                      uint32_t number, void *arg)
 {
     XPCWrappedNative* wrapper = (XPCWrappedNative*)((JSDHashEntryStub*)hdr)->key;
@@ -1188,16 +1229,22 @@ XPCJSRuntime::~XPCJSRuntime()
 
     if (mJSRuntime) {
         JS_DestroyRuntime(mJSRuntime);
         JS_ShutDown();
 #ifdef DEBUG_shaver_off
         fprintf(stderr, "nJRSI: destroyed runtime %p\n", (void *)mJSRuntime);
 #endif
     }
+
+#ifdef DEBUG
+    for (uint32_t i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) {
+        NS_ASSERTION(!mScratchStrings[i].mInUse, "Uh, string wrapper still in use!");
+    }
+#endif
 }
 
 static void
 GetCompartmentName(JSCompartment *c, nsCString &name, bool replaceSlashes)
 {
     if (js::IsAtomsCompartment(c)) {
         name.AssignLiteral("atoms");
     } else if (JSPrincipals *principals = JS_GetCompartmentPrincipals(c)) {
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -20,32 +20,32 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_IMPL_QUERY_CLASSINFO(XPCVariant)
 NS_INTERFACE_MAP_END
 NS_IMPL_CI_INTERFACE_GETTER2(XPCVariant, XPCVariant, nsIVariant)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCVariant)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant)
 
-XPCVariant::XPCVariant(XPCCallContext& ccx, jsval aJSVal)
+XPCVariant::XPCVariant(JSContext* cx, jsval aJSVal)
     : mJSVal(aJSVal), mCCGeneration(0)
 {
     nsVariant::Initialize(&mData);
     if (!JSVAL_IS_PRIMITIVE(mJSVal)) {
-        JSObject *obj = JS_ObjectToInnerObject(ccx, JSVAL_TO_OBJECT(mJSVal));
+        JSObject *obj = JS_ObjectToInnerObject(cx, JSVAL_TO_OBJECT(mJSVal));
 
         mJSVal = OBJECT_TO_JSVAL(obj);
 
         // If the incoming object is an XPCWrappedNative, then it could be a
         // double-wrapped object, and we should return the double-wrapped
         // object back out to script.
 
         JSObject* proto;
         XPCWrappedNative* wn =
-            XPCWrappedNative::GetWrappedNativeOfJSObject(ccx,
+            XPCWrappedNative::GetWrappedNativeOfJSObject(cx,
                                                          JSVAL_TO_OBJECT(mJSVal),
                                                          nullptr,
                                                          &proto);
         mReturnRawObject = !wn && !proto;
     } else
         mReturnRawObject = false;
 }
 
@@ -102,30 +102,30 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XP
     if (val.isMarkable()) {
         XPCTraceableVariant *v = static_cast<XPCTraceableVariant*>(tmp);
         v->RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock());
     }
     tmp->mJSVal = JS::NullValue();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 // static
-XPCVariant* XPCVariant::newVariant(XPCCallContext& ccx, jsval aJSVal)
+XPCVariant* XPCVariant::newVariant(JSContext* cx, jsval aJSVal)
 {
     XPCVariant* variant;
 
     if (!JSVAL_IS_TRACEABLE(aJSVal))
-        variant = new XPCVariant(ccx, aJSVal);
+        variant = new XPCVariant(cx, aJSVal);
     else
-        variant = new XPCTraceableVariant(ccx, aJSVal);
+        variant = new XPCTraceableVariant(cx, aJSVal);
 
     if (!variant)
         return nullptr;
     NS_ADDREF(variant);
 
-    if (!variant->InitializeData(ccx))
+    if (!variant->InitializeData(cx))
         NS_RELEASE(variant);     // Also sets variant to nullptr.
 
     return variant;
 }
 
 // Helper class to give us a namespace for the table based code below.
 class XPCArrayHomogenizer
 {
@@ -147,17 +147,17 @@ private:
         tVar       ,  // nsVariant - last ditch if no other common type found.
         tErr          // No valid state or type has this value.
     };
 
     // Table has tUnk as a state (column) but not as a type (row).
     static const Type StateTable[tTypeCount][tTypeCount-1];
 
 public:
-    static JSBool GetTypeForArray(XPCCallContext& ccx, JSObject* array,
+    static JSBool GetTypeForArray(JSContext* cx, JSObject* array,
                                   uint32_t length,
                                   nsXPTType* resultType, nsID* resultID);
 };
 
 
 // Current state is the column down the side.
 // Current type is the row along the top.
 // New state is in the box at the intersection.
@@ -172,26 +172,26 @@ XPCArrayHomogenizer::StateTable[tTypeCou
 /* tStr  */{tStr ,tVar ,tVar ,tVar ,tStr ,tVar ,tVar ,tVar  },
 /* tID   */{tID  ,tVar ,tVar ,tVar ,tVar ,tID  ,tVar ,tVar  },
 /* tArr  */{tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr  },
 /* tISup */{tISup,tVar ,tVar ,tVar ,tVar ,tVar ,tVar ,tISup },
 /* tUnk  */{tNull,tInt ,tDbl ,tBool,tStr ,tID  ,tVar ,tISup }};
 
 // static
 JSBool
-XPCArrayHomogenizer::GetTypeForArray(XPCCallContext& ccx, JSObject* array,
+XPCArrayHomogenizer::GetTypeForArray(JSContext* cx, JSObject* array,
                                      uint32_t length,
                                      nsXPTType* resultType, nsID* resultID)
 {
     Type state = tUnk;
     Type type;
 
     for (uint32_t i = 0; i < length; i++) {
         JS::Value val;
-        if (!JS_GetElement(ccx, array, i, &val))
+        if (!JS_GetElement(cx, array, i, &val))
             return false;
 
         if (val.isInt32()) {
             type = tInt;
         } else if (val.isDouble()) {
             type = tDbl;
         } else if (val.isBoolean()) {
             type = tBool;
@@ -200,19 +200,19 @@ XPCArrayHomogenizer::GetTypeForArray(XPC
             break;
         } else if (val.isNull()) {
             type = tNull;
         } else if (val.isString()) {
             type = tStr;
         } else {
             NS_ASSERTION(val.isObject(), "invalid type of jsval!");
             JSObject* jsobj = &val.toObject();
-            if (JS_IsArrayObject(ccx, jsobj))
+            if (JS_IsArrayObject(cx, jsobj))
                 type = tArr;
-            else if (xpc_JSObjectIsID(ccx, jsobj))
+            else if (xpc_JSObjectIsID(cx, jsobj))
                 type = tID;
             else
                 type = tISup;
         }
 
         NS_ASSERTION(state != tErr, "bad state table!");
         NS_ASSERTION(type  != tErr, "bad type!");
         NS_ASSERTION(type  != tVar, "bad type!");
@@ -261,19 +261,19 @@ XPCArrayHomogenizer::GetTypeForArray(XPC
             // FALL THROUGH
         default:
             NS_ERROR("bad state");
             return false;
     }
     return true;
 }
 
-JSBool XPCVariant::InitializeData(XPCCallContext& ccx)
+JSBool XPCVariant::InitializeData(JSContext* cx)
 {
-    JS_CHECK_RECURSION(ccx.GetJSContext(), return false);
+    JS_CHECK_RECURSION(cx, return false);
 
     JS::Value val = GetJSVal();
 
     if (val.isInt32())
         return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, val.toInt32()));
     if (val.isDouble())
         return NS_SUCCEEDED(nsVariant::SetFromDouble(&mData, val.toDouble()));
     if (val.isBoolean())
@@ -291,17 +291,17 @@ JSBool XPCVariant::InitializeData(XPCCal
         // the data.  Just handle this ourselves.  Note that it's ok to not
         // copy because we added mJSVal as a GC root.
         NS_ASSERTION(mData.mType == nsIDataType::VTYPE_EMPTY,
                      "Why do we already have data?");
 
         // Despite the fact that the variant holds the length, there are
         // implicit assumptions that mWStringValue[mWStringLength] == 0
         size_t length;
-        const jschar *chars = JS_GetStringCharsZAndLength(ccx, str, &length);
+        const jschar *chars = JS_GetStringCharsZAndLength(cx, str, &length);
         if (!chars)
             return false;
 
         mData.u.wstr.mWStringValue = const_cast<jschar *>(chars);
         // Use C-style cast, because reinterpret cast from size_t to
         // uint32_t is not valid on some platforms.
         mData.u.wstr.mWStringLength = (uint32_t)length;
         mData.mType = nsIDataType::VTYPE_WSTRING_SIZE_IS;
@@ -311,38 +311,38 @@ JSBool XPCVariant::InitializeData(XPCCal
 
     // leaving only JSObject...
     NS_ASSERTION(val.isObject(), "invalid type of jsval!");
 
     JSObject* jsobj = &val.toObject();
 
     // Let's see if it is a xpcJSID.
 
-    const nsID* id = xpc_JSObjectToID(ccx, jsobj);
+    const nsID* id = xpc_JSObjectToID(cx, jsobj);
     if (id)
         return NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
 
     // Let's see if it is a js array object.
 
     uint32_t len;
 
-    if (JS_IsArrayObject(ccx, jsobj) && JS_GetArrayLength(ccx, jsobj, &len)) {
+    if (JS_IsArrayObject(cx, jsobj) && JS_GetArrayLength(cx, jsobj, &len)) {
         if (!len) {
             // Zero length array
             nsVariant::SetToEmptyArray(&mData);
             return true;
         }
 
         nsXPTType type;
         nsID id;
 
-        if (!XPCArrayHomogenizer::GetTypeForArray(ccx, jsobj, len, &type, &id))
+        if (!XPCArrayHomogenizer::GetTypeForArray(cx, jsobj, len, &type, &id))
             return false;
 
-        if (!XPCConvert::JSArray2Native(ccx, &mData.u.array.mArrayValue,
+        if (!XPCConvert::JSArray2Native(cx, &mData.u.array.mArrayValue,
                                         val, len, type, &id, nullptr))
             return false;
 
         mData.mType = nsIDataType::VTYPE_ARRAY;
         if (type.IsInterfacePointer())
             mData.u.array.mArrayInterfaceID = id;
         mData.u.array.mArrayCount = len;
         mData.u.array.mArrayType = type.TagPart();
@@ -352,17 +352,17 @@ JSBool XPCVariant::InitializeData(XPCCal
 
     // XXX This could be smarter and pick some more interesting iface.
 
     nsXPConnect*  xpc;
     nsCOMPtr<nsISupports> wrapper;
     const nsIID& iid = NS_GET_IID(nsISupports);
 
     return nullptr != (xpc = nsXPConnect::GetXPConnect()) &&
-           NS_SUCCEEDED(xpc->WrapJS(ccx, jsobj,
+           NS_SUCCEEDED(xpc->WrapJS(cx, jsobj,
                                     iid, getter_AddRefs(wrapper))) &&
            NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper));
 }
 
 NS_IMETHODIMP
 XPCVariant::GetAsJSVal(jsval* result)
 {
   NS_PRECONDITION(result, "null result arg.");
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -268,43 +268,43 @@ CheckMainThreadOnly(nsXPCWrappedJS *aWra
 
     aWrapper->SetIsMainThreadOnly();
 
     return true;
 }
 
 // static
 nsresult
-nsXPCWrappedJS::GetNewOrUsed(XPCCallContext& ccx,
+nsXPCWrappedJS::GetNewOrUsed(JSContext* cx,
                              JSObject* aJSObj,
                              REFNSIID aIID,
                              nsISupports* aOuter,
                              nsXPCWrappedJS** wrapperResult)
 {
     JSObject2WrappedJSMap* map;
     JSObject* rootJSObj;
     nsXPCWrappedJS* root = nullptr;
     nsXPCWrappedJS* wrapper = nullptr;
     nsXPCWrappedJSClass* clazz = nullptr;
-    XPCJSRuntime* rt = ccx.GetRuntime();
+    XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
     JSBool release_root = false;
 
     map = rt->GetWrappedJSMap();
     if (!map) {
         NS_ASSERTION(map,"bad map");
         return NS_ERROR_FAILURE;
     }
 
-    nsXPCWrappedJSClass::GetNewOrUsed(ccx, aIID, &clazz);
+    nsXPCWrappedJSClass::GetNewOrUsed(cx, aIID, &clazz);
     if (!clazz)
         return NS_ERROR_FAILURE;
     // from here on we need to return through 'return_wrapper'
 
     // always find the root JSObject
-    rootJSObj = clazz->GetRootJSObject(ccx, aJSObj);
+    rootJSObj = clazz->GetRootJSObject(cx, aJSObj);
     if (!rootJSObj)
         goto return_wrapper;
 
     // look for the root wrapper, and if found, hold the map lock until
     // we've added our ref to prevent another thread from destroying it
     // under us
     {   // scoped lock
         XPCAutoLock lock(rt->GetMapLock());
@@ -317,17 +317,17 @@ nsXPCWrappedJS::GetNewOrUsed(XPCCallCont
             }
         }
     }
 
     if (!root) {
         // build the root wrapper
         if (rootJSObj == aJSObj) {
             // the root will do double duty as the interface wrapper
-            wrapper = root = new nsXPCWrappedJS(ccx, aJSObj, clazz, nullptr,
+            wrapper = root = new nsXPCWrappedJS(cx, aJSObj, clazz, nullptr,
                                                 aOuter);
             if (!root)
                 goto return_wrapper;
 
             {   // scoped lock
 #if DEBUG_xpc_leaks
                 printf("Created nsXPCWrappedJS %p, JSObject is %p\n",
                        (void*)wrapper, (void*)aJSObj);
@@ -342,22 +342,22 @@ nsXPCWrappedJS::GetNewOrUsed(XPCCallCont
 
                 wrapper = NULL;
             }
 
             goto return_wrapper;
         } else {
             // just a root wrapper
             nsXPCWrappedJSClass* rootClazz = nullptr;
-            nsXPCWrappedJSClass::GetNewOrUsed(ccx, NS_GET_IID(nsISupports),
+            nsXPCWrappedJSClass::GetNewOrUsed(cx, NS_GET_IID(nsISupports),
                                               &rootClazz);
             if (!rootClazz)
                 goto return_wrapper;
 
-            root = new nsXPCWrappedJS(ccx, rootJSObj, rootClazz, nullptr, aOuter);
+            root = new nsXPCWrappedJS(cx, rootJSObj, rootClazz, nullptr, aOuter);
             NS_RELEASE(rootClazz);
 
             if (!root)
                 goto return_wrapper;
 
             release_root = true;
 
             {   // scoped lock
@@ -378,17 +378,17 @@ nsXPCWrappedJS::GetNewOrUsed(XPCCallCont
         }
     }
 
     // at this point we have a root and may need to build the specific wrapper
     NS_ASSERTION(root,"bad root");
     NS_ASSERTION(clazz,"bad clazz");
 
     if (!wrapper) {
-        wrapper = new nsXPCWrappedJS(ccx, aJSObj, clazz, root, aOuter);
+        wrapper = new nsXPCWrappedJS(cx, aJSObj, clazz, root, aOuter);
         if (!wrapper)
             goto return_wrapper;
 #if DEBUG_xpc_leaks
         printf("Created nsXPCWrappedJS %p, JSObject is %p\n",
                (void*)wrapper, (void*)aJSObj);
 #endif
     }
 
@@ -404,17 +404,17 @@ return_wrapper:
 
     if (!wrapper)
         return NS_ERROR_FAILURE;
 
     *wrapperResult = wrapper;
     return NS_OK;
 }
 
-nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx,
+nsXPCWrappedJS::nsXPCWrappedJS(JSContext* cx,
                                JSObject* aJSObj,
                                nsXPCWrappedJSClass* aClass,
                                nsXPCWrappedJS* root,
                                nsISupports* aOuter)
     : mJSObj(aJSObj),
       mClass(aClass),
       mRoot(root ? root : this),
       mNext(nullptr),
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -102,50 +102,50 @@ JSBool xpc_IsReportableErrorCode(nsresul
             return false;
         default:
             return true;
     }
 }
 
 // static
 nsresult
-nsXPCWrappedJSClass::GetNewOrUsed(XPCCallContext& ccx, REFNSIID aIID,
+nsXPCWrappedJSClass::GetNewOrUsed(JSContext* cx, REFNSIID aIID,
                                   nsXPCWrappedJSClass** resultClazz)
 {
     nsXPCWrappedJSClass* clazz = nullptr;
-    XPCJSRuntime* rt = ccx.GetRuntime();
+    XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
 
     {   // scoped lock
         XPCAutoLock lock(rt->GetMapLock());
         IID2WrappedJSClassMap* map = rt->GetWrappedJSClassMap();
         clazz = map->Find(aIID);
         NS_IF_ADDREF(clazz);
     }
 
     if (!clazz) {
         nsCOMPtr<nsIInterfaceInfo> info;
-        ccx.GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
+        nsXPConnect::GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
         if (info) {
             bool canScript, isBuiltin;
             if (NS_SUCCEEDED(info->IsScriptable(&canScript)) && canScript &&
                 NS_SUCCEEDED(info->IsBuiltinClass(&isBuiltin)) && !isBuiltin &&
                 nsXPConnect::IsISupportsDescendant(info)) {
-                clazz = new nsXPCWrappedJSClass(ccx, aIID, info);
+                clazz = new nsXPCWrappedJSClass(cx, aIID, info);
                 if (clazz && !clazz->mDescriptors)
                     NS_RELEASE(clazz);  // sets clazz to nullptr
             }
         }
     }
     *resultClazz = clazz;
     return NS_OK;
 }
 
-nsXPCWrappedJSClass::nsXPCWrappedJSClass(XPCCallContext& ccx, REFNSIID aIID,
+nsXPCWrappedJSClass::nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID,
                                          nsIInterfaceInfo* aInfo)
-    : mRuntime(ccx.GetRuntime()),
+    : mRuntime(nsXPConnect::GetRuntimeInstance()),
       mInfo(aInfo),
       mName(nullptr),
       mIID(aIID),
       mDescriptors(nullptr)
 {
     NS_ADDREF(mInfo);
     NS_ADDREF_THIS();
 
@@ -191,21 +191,20 @@ nsXPCWrappedJSClass::~nsXPCWrappedJSClas
         mRuntime->GetWrappedJSClassMap()->Remove(this);
     }
     if (mName)
         nsMemory::Free(mName);
     NS_IF_RELEASE(mInfo);
 }
 
 JSObject*
-nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
+nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
                                                   JSObject* jsobj,
                                                   REFNSIID aIID)
 {
-    JSContext* cx = ccx.GetJSContext();
     JSObject* id;
     jsval retval;
     JSObject* retObj;
     JSBool success = false;
     jsid funid;
     jsval fun;
 
     // Don't call the actual function on a content object. We'll determine
@@ -225,27 +224,27 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
         return nullptr;
 
     // check upfront for the existence of the function property
     funid = mRuntime->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE);
     if (!JS_GetPropertyById(cx, jsobj, funid, &fun) || JSVAL_IS_PRIMITIVE(fun))
         return nullptr;
 
     // protect fun so that we're sure it's alive when we call it
-    AUTO_MARK_JSVAL(ccx, fun);
+    AUTO_MARK_JSVAL(cx, fun);
 
     // Ensure that we are asking for a scriptable interface.
     // NB:  It's important for security that this check is here rather
     // than later, since it prevents untrusted objects from implementing
     // some interfaces in JS and aggregating a trusted object to
     // implement intentionally (for security) unscriptable interfaces.
     // We so often ask for nsISupports that we can short-circuit the test...
     if (!aIID.Equals(NS_GET_IID(nsISupports))) {
         nsCOMPtr<nsIInterfaceInfo> info;
-        ccx.GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
+        nsXPConnect::GetXPConnect()->GetInfoForIID(&aIID, getter_AddRefs(info));
         if (!info)
             return nullptr;
         bool canScript, isBuiltin;
         if (NS_FAILED(info->IsScriptable(&canScript)) || !canScript ||
             NS_FAILED(info->IsBuiltinClass(&isBuiltin)) || isBuiltin)
             return nullptr;
     }
 
@@ -263,27 +262,27 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
 
         JS_SetOptions(cx, oldOpts);
 
         if (!success) {
             NS_ASSERTION(JS_IsExceptionPending(cx),
                          "JS failed without setting an exception!");
 
             jsval jsexception = JSVAL_NULL;
-            AUTO_MARK_JSVAL(ccx, &jsexception);
+            AUTO_MARK_JSVAL(cx, &jsexception);
 
             if (JS_GetPendingException(cx, &jsexception)) {
                 nsresult rv;
                 if (jsexception.isObject()) {
                     // XPConnect may have constructed an object to represent a
                     // C++ QI failure. See if that is the case.
                     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
 
                     nsXPConnect::GetXPConnect()->
-                        GetWrappedNativeOfJSObject(ccx,
+                        GetWrappedNativeOfJSObject(cx,
                                                    &jsexception.toObject(),
                                                    getter_AddRefs(wrapper));
 
                     if (wrapper) {
                         nsCOMPtr<nsIException> exception =
                             do_QueryWrappedNative(wrapper);
                         if (exception &&
                             NS_SUCCEEDED(exception->GetResult(&rv)) &&
@@ -741,23 +740,23 @@ nsXPCWrappedJSClass::DelegatedQueryInter
 
     // else...
     // no can do
     *aInstancePtr = nullptr;
     return NS_NOINTERFACE;
 }
 
 JSObject*
-nsXPCWrappedJSClass::GetRootJSObject(XPCCallContext& ccx, JSObject* aJSObj)
+nsXPCWrappedJSClass::GetRootJSObject(JSContext* cx, JSObject* aJSObj)
 {
-    JSObject* result = CallQueryInterfaceOnJSObject(ccx, aJSObj,
+    JSObject* result = CallQueryInterfaceOnJSObject(cx, aJSObj,
                                                     NS_GET_IID(nsISupports));
     if (!result)
         return aJSObj;
-    JSObject* inner = XPCWrapper::Unwrap(ccx, result);
+    JSObject* inner = XPCWrapper::Unwrap(cx, result);
     if (inner)
         return inner;
     return result;
 }
 
 void
 xpcWrappedJSErrorReporter(JSContext *cx, const char *message,
                           JSErrorReport *report)
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -3019,17 +3019,17 @@ CallMethodHelper::CleanupParam(nsXPTCMin
             JS_RemoveValueRoot(mCallContext, (jsval*)&param.val);
             break;
         case nsXPTType::T_INTERFACE:
         case nsXPTType::T_INTERFACE_IS:
             ((nsISupports*)param.val.p)->Release();
             break;
         case nsXPTType::T_ASTRING:
         case nsXPTType::T_DOMSTRING:
-            mCallContext.DeleteString((nsAString*)param.val.p);
+            nsXPConnect::GetRuntimeInstance()->DeleteString((nsAString*)param.val.p);
             break;
         case nsXPTType::T_UTF8STRING:
         case nsXPTType::T_CSTRING:
             delete (nsCString*) param.val.p;
             break;
         default:
             NS_ABORT_IF_FALSE(!type.IsArithmetic(),
                               "Cleanup requested on unexpected type.");
--- a/js/xpconnect/src/codegen.py
+++ b/js/xpconnect/src/codegen.py
@@ -156,17 +156,17 @@ argumentUnboxingTemplates = {
     }
 
 # From JSData2Native.
 #
 # Omitted optional arguments are treated as though the caller had passed JS
 # `null`; this behavior is from XPCWrappedNative::CallMethod. The 'jsval' type,
 # however, defaults to 'undefined'.
 #
-def writeArgumentUnboxing(f, i, name, type, haveCcx, optional, rvdeclared,
+def writeArgumentUnboxing(f, i, name, type, optional, rvdeclared,
                           nullBehavior, undefinedBehavior):
     # f - file to write to
     # i - int or None - Indicates the source jsval.  If i is an int, the source
     #     jsval is argv[i]; otherwise it is *vp.  But if Python i >= C++ argc,
     #     which can only happen if optional is True, the argument is missing;
     #     use JSVAL_NULL as the source jsval instead.
     # name - str - name of the native C++ variable to create.
     # type - xpidl.{Interface,Native,Builtin} - IDL type of argument
@@ -203,22 +203,21 @@ def writeArgumentUnboxing(f, i, name, ty
         template = argumentUnboxingTemplates.get(typeName)
         if template is not None:
             f.write(string.Template(template).substitute(params))
             return rvdeclared
         # else fall through; the type isn't supported yet.
     elif isInterfaceType(type):
         if type.name == 'nsIVariant':
             # Totally custom.
-            assert haveCcx
             template = (
                 "    nsCOMPtr<nsIVariant> ${name}(already_AddRefed<nsIVariant>("
-                "XPCVariant::newVariant(ccx, ${argVal})));\n"
+                "XPCVariant::newVariant(cx, ${argVal})));\n"
                 "    if (!${name}) {\n"
-                "        xpc_qsThrowBadArgWithCcx(ccx, NS_ERROR_XPC_BAD_CONVERT_JS, %d);\n"
+                "        xpc_qsThrowBadArg(cx, NS_ERROR_INVALID_ARG, vp, %d);\n"
                 "        return JS_FALSE;\n"
                 "    }\n") % i
             f.write(string.Template(template).substitute(params))
             return rvdeclared
         elif type.name == 'nsIAtom':
             # Should have special atomizing behavior.  Fall through.
             pass
         else:
@@ -228,18 +227,16 @@ def writeArgumentUnboxing(f, i, name, ty
             f.write("    xpc_qsSelfRef %sref;\n" % name)
             f.write("    rv = xpc_qsUnwrapArg<%s>("
                     "cx, %s, &%s, &%sref.ptr, %s);\n"
                     % (type.name, argVal, name, name, argPtr))
             f.write("    if (NS_FAILED(rv)) {\n")
             if isSetter:
                 f.write("        xpc_qsThrowBadSetterValue("
                         "cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);\n")
-            elif haveCcx:
-                f.write("        xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
             else:
                 f.write("        xpc_qsThrowBadArgWithDetails(cx, rv, %d, %s, %s);\n" % (i, "\"\"", "\"\""))
             f.write("        return JS_FALSE;\n"
                     "    }\n")
             return True
 
     warn("Unable to unbox argument of type %s (native type %s)" % (type.name, typeName))
     if i is None:
@@ -386,25 +383,16 @@ def writeResultConv(f, type, interfaceRe
         return
     # else fall through; this type isn't supported yet
 
     warn("Unable to convert result of type %s" % type.name)
     f.write("    !; // TODO - Convert `result` to jsval, store in `%s`.\n"
             % jsvalRef)
     f.write("    return xpc_qsThrow(cx, NS_ERROR_UNEXPECTED); // FIXME\n")
 
-def anyParamRequiresCcx(member):
-    for p in member.params:
-        if isVariantType(p.realtype):
-            return True
-    return False
-
-def memberNeedsCcx(member):
-    return member.kind == 'method' and anyParamRequiresCcx(member)
-
 def validateParam(member, param):
     def pfail(msg):
         raise UserError(
             member.iface.name + '.' + member.name + ": "
             "parameter " + param.name + ": " + msg)
 
     if param.iid_is is not None:
         pfail("iid_is parameters are not supported.")
@@ -521,25 +509,17 @@ def writeStub(f, customMethodCalls, memb
         f.write("    jsval *vp = vp_.address();\n")
 
     # For methods, compute "this".
     if isMethod:
         f.write("    JSObject *obj = JS_THIS_OBJECT(cx, vp);\n"
                 "    if (!obj)\n"
                 "        return JS_FALSE;\n")
 
-    # Create ccx if needed.
-    haveCcx = memberNeedsCcx(member)
-    if haveCcx:
-        f.write("    XPCCallContext ccx(JS_CALLER, cx, obj, "
-                "JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));\n")
-        if isInterfaceType(member.realtype):
-            f.write("    XPCLazyCallContext lccx(ccx);\n")
-
-    selfname = writeThisUnwrapping(f, member, isMethod, isGetter, customMethodCall, haveCcx)
+    selfname = writeThisUnwrapping(f, member, isMethod, isGetter, customMethodCall)
 
     rvdeclared = False
     if isMethod:
         inArgs = argumentsLength(member)
         # If there are any required arguments, check argc.
         requiredArgs = inArgs
         while requiredArgs and member.params[requiredArgs-1].optional:
             requiredArgs -= 1
@@ -559,26 +539,25 @@ def writeStub(f, customMethodCalls, memb
                 validateParam(member, param)
                 realtype = param.realtype
             else:
                 realtype = xpidl.Forward(name=customMethodCall[argTypeKey],
                                          location='', doccomments='')
             # Emit code to convert this argument from jsval.
             rvdeclared = writeArgumentUnboxing(
                 f, i, argName, realtype,
-                haveCcx=haveCcx,
                 optional=param.optional,
                 rvdeclared=rvdeclared,
                 nullBehavior=param.null,
                 undefinedBehavior=param.undefined)
         if inArgs < len(member.params):
             f.write("    nsWrapperCache *cache;\n")
     elif isSetter:
         rvdeclared = writeArgumentUnboxing(f, None, 'arg0', member.realtype,
-                                           haveCcx=False, optional=False,
+                                           optional=False,
                                            rvdeclared=rvdeclared,
                                            nullBehavior=member.null,
                                            undefinedBehavior=member.undefined)
 
     canFail = not isNotxpcom and (customMethodCall is None or customMethodCall.get('canFail', True))
     if canFail and not rvdeclared:
         f.write("    nsresult rv;\n")
         rvdeclared = True
@@ -642,17 +621,17 @@ def writeStub(f, customMethodCalls, memb
             f.write("    NS_ASSERTION(%s && "
                     "xpc_qsSameResult(debug_result, result),\n"
                     "                 \"Got the wrong answer from the custom "
                     "method call!\");\n" % checkSuccess)
             f.write("#endif\n")
 
     if canFail:
         # Check for errors.
-        writeCheckForFailure(f, isMethod, isGetter, haveCcx)
+        writeCheckForFailure(f, isMethod, isGetter)
 
     # Convert the return value.
     if isMethod or isGetter:
         writeResultWrapping(f, member, 'vp', '*vp')
     else:
         f.write("    return JS_TRUE;\n")
 
     # Epilog.
--- a/js/xpconnect/src/dombindingsgen.py
+++ b/js/xpconnect/src/dombindingsgen.py
@@ -568,26 +568,26 @@ listTemplateFooter = (
 "${nativeClass}*\n"
 "${name}::getNative(JSObject *obj)\n"
 "{\n"
 "    return ${name}Wrapper::getListObject(obj);\n"
 "}\n"
 "\n")
 
 def writeBindingStub(f, classname, member, stubName, isSetter=False):
-    def writeThisUnwrapping(f, member, isMethod, isGetter, customMethodCall, haveCcx):
+    def writeThisUnwrapping(f, member, isMethod, isGetter, customMethodCall):
         if isMethod:
             f.write("    JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));\n"
                     "    if (!%sWrapper::instanceIsListObject(cx, obj, callee))\n"
                     "        return false;\n" % classname)
         else:
             f.write("    if (!%sWrapper::instanceIsListObject(cx, obj, NULL))\n"
                     "        return false;\n" % classname)
         return "%sWrapper::getListObject(obj)" % classname
-    def writeCheckForFailure(f, isMethod, isGeter, haveCcx):
+    def writeCheckForFailure(f, isMethod, isGeter):
         f.write("    if (NS_FAILED(rv))\n"
                 "        return xpc_qsThrowMethodFailedWithDetails(cx, rv, \"%s\", \"%s\");\n" % (classname, member.name))
     def writeResultWrapping(f, member, jsvalPtr, jsvalRef):
         if member.kind == 'method' and member.notxpcom and len(member.params) > 0 and member.params[len(member.params) - 1].paramtype == 'out':
             assert member.params[len(member.params) - 1].realtype.kind == 'native' and member.params[len(member.params) - 1].realtype.nativename == 'nsWrapperCache'
             template = "    return Wrap(cx, obj, result, cache, ${jsvalPtr});\n"
         else:
             template = "    return Wrap(cx, obj, result, ${jsvalPtr});\n"
--- a/js/xpconnect/src/qsgen.py
+++ b/js/xpconnect/src/qsgen.py
@@ -485,17 +485,17 @@ argumentUnboxingTemplates = {
     }
 
 # From JSData2Native.
 #
 # Omitted optional arguments are treated as though the caller had passed JS
 # `null`; this behavior is from XPCWrappedNative::CallMethod. The 'jsval' type,
 # however, defaults to 'undefined'.
 #
-def writeArgumentUnboxing(f, i, name, type, haveCcx, optional, rvdeclared,
+def writeArgumentUnboxing(f, i, name, type, optional, rvdeclared,
                           nullBehavior, undefinedBehavior):
     # f - file to write to
     # i - int or None - Indicates the source jsval.  If i is an int, the source
     #     jsval is argv[i]; otherwise it is *vp.  But if Python i >= C++ argc,
     #     which can only happen if optional is True, the argument is missing;
     #     use JSVAL_NULL as the source jsval instead.
     # name - str - name of the native C++ variable to create.
     # type - xpidl.{Interface,Native,Builtin} - IDL type of argument
@@ -532,22 +532,21 @@ def writeArgumentUnboxing(f, i, name, ty
         template = argumentUnboxingTemplates.get(typeName)
         if template is not None:
             f.write(substitute(template, params))
             return rvdeclared
         # else fall through; the type isn't supported yet.
     elif isInterfaceType(type):
         if type.name == 'nsIVariant':
             # Totally custom.
-            assert haveCcx
             template = (
                 "    nsCOMPtr<nsIVariant> ${name}(already_AddRefed<nsIVariant>("
-                "XPCVariant::newVariant(ccx, ${argVal})));\n"
+                "XPCVariant::newVariant(cx, ${argVal})));\n"
                 "    if (!${name}) {\n"
-                "        xpc_qsThrowBadArgWithCcx(ccx, NS_ERROR_XPC_BAD_CONVERT_JS, %d);\n"
+                "        xpc_qsThrowBadArg(cx, NS_ERROR_INVALID_ARG, vp, %d);\n"
                 "        return JS_FALSE;\n"
                 "    }") % i
             f.write(substitute(template, params))
             return rvdeclared
         elif type.name == 'nsIAtom':
             # Should have special atomizing behavior.  Fall through.
             pass
         else:
@@ -557,18 +556,16 @@ def writeArgumentUnboxing(f, i, name, ty
             f.write("    xpc_qsSelfRef %sref;\n" % name)
             f.write("    rv = xpc_qsUnwrapArg<%s>("
                     "cx, %s, &%s, &%sref.ptr, %s);\n"
                     % (type.name, argVal, name, name, argPtr))
             f.write("    if (NS_FAILED(rv)) {\n")
             if isSetter:
                 f.write("        xpc_qsThrowBadSetterValue("
                         "cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);\n")
-            elif haveCcx:
-                f.write("        xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
             else:
                 f.write("        xpc_qsThrowBadArg(cx, rv, vp, %d);\n" % i)
             f.write("        return JS_FALSE;\n"
                     "    }\n")
             return True
 
     warn("Unable to unbox argument of type %s (native type %s)" % (type.name, typeName))
     if i is None:
@@ -719,27 +716,18 @@ def writeResultConv(f, type, jsvalPtr, j
                     % (jsvalPtr, jsvalPtr, type.name, type.name, jsvalPtr))
             return
 
     warn("Unable to convert result of type %s" % type.name)
     f.write("    !; // TODO - Convert `result` to jsval, store in `%s`.\n"
             % jsvalRef)
     f.write("    return xpc_qsThrow(cx, NS_ERROR_UNEXPECTED); // FIXME\n")
 
-def anyParamRequiresCcx(member):
-    for p in member.params:
-        if isVariantType(p.realtype):
-            return True
-    return False
-
-def memberNeedsCcx(member):
-    return member.kind == 'method' and anyParamRequiresCcx(member)
-
 def memberNeedsCallee(member):
-    return memberNeedsCcx(member) or isInterfaceType(member.realtype)
+    return isInterfaceType(member.realtype)
 
 def validateParam(member, param):
     def pfail(msg):
         raise UserError(
             member.iface.name + '.' + member.name + ": "
             "parameter " + param.name + ": " + msg)
 
     if param.iid_is is not None:
@@ -850,71 +838,50 @@ def writeQuickStub(f, customMethodCalls,
         f.write("    jsval *vp = vp_.address();\n")
 
     # For methods, compute "this".
     if isMethod:
         f.write("    JSObject *obj = JS_THIS_OBJECT(cx, vp);\n"
                 "    if (!obj)\n"
                 "        return JS_FALSE;\n")
 
-    # Create ccx if needed.
-    haveCcx = memberNeedsCcx(member)
-    if haveCcx and not unwrapThisFailureFatal:
-        raise UserError(member.iface.name + '.' + member.name + ": "
-                        "Unwrapping this failure must be fatal when we have a ccx")
-
-    if haveCcx:
-        f.write("    XPCCallContext ccx(JS_CALLER, cx, obj, "
-                "JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));\n")
-        if isInterfaceType(member.realtype):
-            f.write("    XPCLazyCallContext lccx(ccx);\n")
-
     # Get the 'self' pointer.
     if customMethodCall is None or not 'thisType' in customMethodCall:
         f.write("    %s *self;\n" % member.iface.name)
     else:
         f.write("    %s *self;\n" % customMethodCall['thisType'])
     f.write("    xpc_qsSelfRef selfref;\n")
-    # Don't use FromCcx for getters or setters; the way we construct the ccx in
-    # a getter/setter causes it to find the wrong wrapper in some cases.
-    if haveCcx:
-        # Undocumented, but the interpreter puts 'this' at argv[-1],
-        # which is vp[1]; and it's ok to overwrite it.
-        f.write("    if (!xpc_qsUnwrapThisFromCcx(ccx, &self, &selfref.ptr, "
-                "&vp[1]))\n")
-        f.write("        return JS_FALSE;\n")
+    if isGetter:
+        pthisval = 'vp'
+    elif isSetter:
+        f.write("    JS::AutoValueRooter tvr(cx);\n")
+        pthisval = 'tvr.jsval_addr()'
     else:
-        if isGetter:
-            pthisval = 'vp'
-        elif isSetter:
-            f.write("    JS::AutoValueRooter tvr(cx);\n")
-            pthisval = 'tvr.jsval_addr()'
-        else:
-            pthisval = '&vp[1]' # as above, ok to overwrite vp[1]
+        pthisval = '&vp[1]' # as above, ok to overwrite vp[1]
+
+    if unwrapThisFailureFatal:
+        unwrapFatalArg = "true"
+    else:
+        unwrapFatalArg = "false"
 
-        if unwrapThisFailureFatal:
-            unwrapFatalArg = "true"
-        else:
-            unwrapFatalArg = "false"
+    if not isSetter and isInterfaceType(member.realtype):
+        f.write("    XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
+        f.write("    if (!xpc_qsUnwrapThis(cx, obj, &self, "
+                "&selfref.ptr, %s, &lccx, %s))\n" % (pthisval, unwrapFatalArg))
+    else:
+        f.write("    if (!xpc_qsUnwrapThis(cx, obj, &self, "
+                "&selfref.ptr, %s, nullptr, %s))\n" % (pthisval, unwrapFatalArg))
+    f.write("        return JS_FALSE;\n")
 
-        if not isSetter and isInterfaceType(member.realtype):
-            f.write("    XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
-            f.write("    if (!xpc_qsUnwrapThis(cx, obj, &self, "
-                    "&selfref.ptr, %s, &lccx, %s))\n" % (pthisval, unwrapFatalArg))
-        else:
-            f.write("    if (!xpc_qsUnwrapThis(cx, obj, &self, "
-                    "&selfref.ptr, %s, nullptr, %s))\n" % (pthisval, unwrapFatalArg))
-        f.write("        return JS_FALSE;\n")
-
-        if not unwrapThisFailureFatal:
-            f.write("      if (!self) {\n")
-            if (isGetter):
-                f.write("        *vp = JSVAL_NULL;\n")
-            f.write("        return JS_TRUE;\n")
-            f.write("    }\n");
+    if not unwrapThisFailureFatal:
+        f.write("      if (!self) {\n")
+        if (isGetter):
+            f.write("        *vp = JSVAL_NULL;\n")
+        f.write("        return JS_TRUE;\n")
+        f.write("    }\n");
 
     if isMethod:
         # If there are any required arguments, check argc.
         requiredArgs = len(member.params)
         while requiredArgs and member.params[requiredArgs-1].optional:
             requiredArgs -= 1
         if requiredArgs:
             f.write("    if (argc < %d)\n" % requiredArgs)
@@ -933,24 +900,23 @@ def writeQuickStub(f, customMethodCalls,
                 validateParam(member, param)
                 realtype = param.realtype
             else:
                 realtype = xpidl.Forward(name=customMethodCall[argTypeKey],
                                          location='', doccomments='')
             # Emit code to convert this argument from jsval.
             rvdeclared = writeArgumentUnboxing(
                 f, i, argName, realtype,
-                haveCcx=haveCcx,
                 optional=param.optional,
                 rvdeclared=rvdeclared,
                 nullBehavior=param.null,
                 undefinedBehavior=param.undefined)
     elif isSetter:
         rvdeclared = writeArgumentUnboxing(f, None, 'arg0', member.realtype,
-                                           haveCcx=False, optional=False,
+                                           optional=False,
                                            rvdeclared=rvdeclared,
                                            nullBehavior=member.null,
                                            undefinedBehavior=member.undefined)
 
     canFail = customMethodCall is None or customMethodCall.get('canFail', True)
     if canFail and not rvdeclared:
         f.write("    nsresult rv;\n")
         rvdeclared = True
@@ -1013,22 +979,18 @@ def writeQuickStub(f, customMethodCalls,
                     "                 \"Got the wrong answer from the custom "
                     "method call!\");\n" % checkSuccess)
             f.write("#endif\n")
 
     if canFail:
         # Check for errors.
         f.write("    if (NS_FAILED(rv))\n")
         if isMethod:
-            if haveCcx:
-                f.write("        return xpc_qsThrowMethodFailedWithCcx("
-                        "ccx, rv);\n")
-            else:
-                f.write("        return xpc_qsThrowMethodFailed("
-                        "cx, rv, vp);\n")
+            f.write("        return xpc_qsThrowMethodFailed("
+                    "cx, rv, vp);\n")
         else:
             if isGetter:
                 thisval = '*vp'
             else:
                 thisval = '*tvr.jsval_addr()'
             f.write("        return xpc_qsThrowGetterSetterFailed(cx, rv, " +
                     "JSVAL_TO_OBJECT(%s), id);\n" % thisval)
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -626,16 +626,43 @@ public:
 
 private:
     XPCRootSetElem *mNext;
     XPCRootSetElem **mSelfp;
 };
 
 /***************************************************************************/
 
+// class to export a JSString as an const nsAString, no refcounting :(
+class XPCReadableJSStringWrapper : public nsDependentString
+{
+public:
+    typedef nsDependentString::char_traits char_traits;
+
+    XPCReadableJSStringWrapper(const PRUnichar *chars, size_t length) :
+        nsDependentString(chars, length)
+    { }
+
+    XPCReadableJSStringWrapper() :
+        nsDependentString(char_traits::sEmptyBuffer, char_traits::sEmptyBuffer)
+    { SetIsVoid(true); }
+
+    JSBool init(JSContext* aContext, JSString* str)
+    {
+        size_t length;
+        const jschar* chars = JS_GetStringCharsZAndLength(aContext, str, &length);
+        if (!chars)
+            return false;
+
+        NS_ASSERTION(IsEmpty(), "init() on initialized string");
+        new(static_cast<nsDependentString *>(this)) nsDependentString(chars, length);
+        return true;
+    }
+};
+
 // In the current xpconnect system there can only be one XPCJSRuntime.
 // So, xpconnect can only be used on one JSRuntime within the process.
 
 // no virtuals. no refcounting.
 class XPCJSContextStack;
 class XPCIncrementalReleaseRunnable;
 class XPCJSRuntime
 {
@@ -818,16 +845,18 @@ public:
             xs->GetCurrentExceptionManager(getter_AddRefs(mExceptionManager));
         if (mExceptionManager)
             return true;
 
         mExceptionManagerNotAvailable = true;
         return false;
     }
 
+    XPCReadableJSStringWrapper *NewStringWrapper(const PRUnichar *str, uint32_t len);
+    void DeleteString(nsAString *string);
 
 #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
    void DEBUG_AddWrappedNative(nsIXPConnectWrappedNative* wrapper)
         {XPCAutoLock lock(GetMapLock());
          JSDHashEntryHdr *entry =
             JS_DHashTableOperate(DEBUG_WrappedNativeHashtable,
                                  wrapper, JS_DHASH_ADD);
          if (entry) ((JSDHashEntryStub *)entry)->key = wrapper;}
@@ -913,16 +942,33 @@ private:
     PRTime mLastActiveTime; // -1 if active NOW
     XPCIncrementalReleaseRunnable *mReleaseRunnable;
     js::GCSliceCallback mPrevGCSliceCallback;
 
     nsCOMPtr<nsIException>   mPendingException;
     nsCOMPtr<nsIExceptionManager> mExceptionManager;
     bool mExceptionManagerNotAvailable;
 
+#define XPCCCX_STRING_CACHE_SIZE 2
+
+    // String wrapper entry, holds a string, and a boolean that tells
+    // whether the string is in use or not.
+    //
+    // NB: The string is not stored by value so that we avoid the cost of
+    // construction/destruction.
+    struct StringWrapperEntry
+    {
+        StringWrapperEntry() : mInUse(false) { }
+
+        mozilla::AlignedStorage2<XPCReadableJSStringWrapper> mString;
+        bool mInUse;
+    };
+
+    StringWrapperEntry mScratchStrings[XPCCCX_STRING_CACHE_SIZE];
+
     friend class AutoLockWatchdog;
     friend class XPCIncrementalReleaseRunnable;
 };
 
 /***************************************************************************/
 /***************************************************************************/
 // XPCContext is mostly a dumb class to hold JSContext specific data and
 // maps that let us find wrappers created for the given JSContext.
@@ -1039,43 +1085,16 @@ private:
     PRCList mScopes;
 };
 
 /***************************************************************************/
 
 #define NATIVE_CALLER  XPCContext::LANG_NATIVE
 #define JS_CALLER      XPCContext::LANG_JS
 
-// class to export a JSString as an const nsAString, no refcounting :(
-class XPCReadableJSStringWrapper : public nsDependentString
-{
-public:
-    typedef nsDependentString::char_traits char_traits;
-
-    XPCReadableJSStringWrapper(const PRUnichar *chars, size_t length) :
-        nsDependentString(chars, length)
-    { }
-
-    XPCReadableJSStringWrapper() :
-        nsDependentString(char_traits::sEmptyBuffer, char_traits::sEmptyBuffer)
-    { SetIsVoid(true); }
-
-    JSBool init(JSContext* aContext, JSString* str)
-    {
-        size_t length;
-        const jschar* chars = JS_GetStringCharsZAndLength(aContext, str, &length);
-        if (!chars)
-            return false;
-
-        NS_ASSERTION(IsEmpty(), "init() on initialized string");
-        new(static_cast<nsDependentString *>(this)) nsDependentString(chars, length);
-        return true;
-    }
-};
-
 // No virtuals
 // XPCCallContext is ALWAYS declared as a local variable in some function;
 // i.e. instance lifetime is always controled by some C++ function returning.
 //
 // These things are created frequently in many places. We *intentionally* do
 // not inialialize all members in order to save on construction overhead.
 // Some constructor pass more valid params than others. We init what must be
 // init'd and leave other members undefined. In debug builds the accessors
@@ -1176,19 +1195,16 @@ public:
                      JSBool isSetter);
 
     nsresult  CanCallNow();
 
     void SystemIsBeingShutDown();
 
     operator JSContext*() const {return GetJSContext();}
 
-    XPCReadableJSStringWrapper *NewStringWrapper(const PRUnichar *str, uint32_t len);
-    void DeleteString(nsAString *string);
-
 private:
 
     // no copy ctor or assignment allowed
     XPCCallContext(const XPCCallContext& r); // not implemented
     XPCCallContext& operator= (const XPCCallContext& r); // not implemented
 
     friend class XPCLazyCallContext;
     XPCCallContext(XPCContext::LangType callerLanguage,
@@ -1266,33 +1282,16 @@ private:
     jsid                            mName;
     JSBool                          mStaticMemberIsLocal;
 
     unsigned                           mArgc;
     jsval*                          mArgv;
     jsval*                          mRetVal;
 
     uint16_t                        mMethodIndex;
-
-#define XPCCCX_STRING_CACHE_SIZE 2
-
-    // String wrapper entry, holds a string, and a boolean that tells
-    // whether the string is in use or not.
-    //
-    // NB: The string is not stored by value so that we avoid the cost of
-    // construction/destruction.
-    struct StringWrapperEntry
-    {
-        StringWrapperEntry() : mInUse(false) { }
-
-        js::AlignedStorage2<XPCReadableJSStringWrapper> mString;
-        bool mInUse;
-    };
-
-    StringWrapperEntry mScratchStrings[XPCCCX_STRING_CACHE_SIZE];
 };
 
 class XPCLazyCallContext
 {
 public:
     XPCLazyCallContext(XPCCallContext& ccx)
         : mCallBeginRequest(DONT_CALL_BEGINREQUEST),
           mCcx(&ccx),
@@ -3033,37 +3032,37 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPCWrap
 class nsXPCWrappedJSClass : public nsIXPCWrappedJSClass
 {
     // all the interface method declarations...
     NS_DECL_ISUPPORTS
     NS_IMETHOD DebugDump(int16_t depth);
 public:
 
     static nsresult
-    GetNewOrUsed(XPCCallContext& ccx,
+    GetNewOrUsed(JSContext* cx,
                  REFNSIID aIID,
                  nsXPCWrappedJSClass** clazz);
 
     REFNSIID GetIID() const {return mIID;}
     XPCJSRuntime* GetRuntime() const {return mRuntime;}
     nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
     const char* GetInterfaceName();
 
     static JSBool IsWrappedJS(nsISupports* aPtr);
 
     NS_IMETHOD DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
                                        void** aInstancePtr);
 
-    JSObject* GetRootJSObject(XPCCallContext& ccx, JSObject* aJSObj);
+    JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj);
 
     NS_IMETHOD CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
                           const XPTMethodDescriptor* info,
                           nsXPTCMiniVariant* params);
 
-    JSObject*  CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
+    JSObject*  CallQueryInterfaceOnJSObject(JSContext* cx,
                                             JSObject* jsobj, REFNSIID aIID);
 
     static nsresult BuildPropertyEnumerator(XPCCallContext& ccx,
                                             JSObject* aJSObj,
                                             nsISimpleEnumerator** aEnumerate);
 
     static nsresult GetNamedPropertyAsVariant(XPCCallContext& ccx,
                                               JSObject* aJSObj,
@@ -3073,17 +3072,17 @@ public:
     virtual ~nsXPCWrappedJSClass();
 
     static nsresult CheckForException(XPCCallContext & ccx,
                                       const char * aPropertyName,
                                       const char * anInterfaceName,
                                       bool aForceReport);
 private:
     nsXPCWrappedJSClass();   // not implemented
-    nsXPCWrappedJSClass(XPCCallContext& ccx, REFNSIID aIID,
+    nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID,
                         nsIInterfaceInfo* aInfo);
 
     JSObject*  NewOutObject(JSContext* cx, JSObject* scope);
 
     JSBool IsReflectable(uint16_t i) const
         {return (JSBool)(mDescriptors[i/32] & (1 << (i%32)));}
     void SetReflectable(uint16_t i, JSBool b)
         {if (b) mDescriptors[i/32] |= (1 << (i%32));
@@ -3147,17 +3146,17 @@ public:
 
     /*
     * This is rarely called directly. Instead one usually calls
     * XPCConvert::JSObject2NativeInterface which will handles cases where the
     * JS object is already a wrapped native or a DOM object.
     */
 
     static nsresult
-    GetNewOrUsed(XPCCallContext& ccx,
+    GetNewOrUsed(JSContext* cx,
                  JSObject* aJSObj,
                  REFNSIID aIID,
                  nsISupports* aOuter,
                  nsXPCWrappedJS** wrapper);
 
     nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
 
     /**
@@ -3205,17 +3204,17 @@ public:
     bool IsMainThreadOnly() const {return mMainThreadOnly;}
 
     void TraceJS(JSTracer* trc);
     static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize);
 
     virtual ~nsXPCWrappedJS();
 protected:
     nsXPCWrappedJS();   // not implemented
-    nsXPCWrappedJS(XPCCallContext& ccx,
+    nsXPCWrappedJS(JSContext* cx,
                    JSObject* aJSObj,
                    nsXPCWrappedJSClass* aClass,
                    nsXPCWrappedJS* root,
                    nsISupports* aOuter);
 
    void Unlink();
 
 private:
@@ -3291,28 +3290,30 @@ public:
      * @param d [out] the resulting jsval
      * @param s the native object we're working with
      * @param type the type of object that s is
      * @param iid the interface of s that we want
      * @param scope the default scope to put on the new JSObject's parent
      *        chain
      * @param pErr [out] relevant error code, if any.
      */
+
     static JSBool NativeData2JS(XPCCallContext& ccx, jsval* d, const void* s,
                                 const nsXPTType& type, const nsID* iid,
                                 nsresult* pErr)
     {
         XPCLazyCallContext lccx(ccx);
         return NativeData2JS(lccx, d, s, type, iid, pErr);
     }
+
     static JSBool NativeData2JS(XPCLazyCallContext& lccx, jsval* d,
                                 const void* s, const nsXPTType& type,
                                 const nsID* iid, nsresult* pErr);
 
-    static JSBool JSData2Native(XPCCallContext& ccx, void* d, jsval s,
+    static JSBool JSData2Native(JSContext* cx, void* d, jsval s,
                                 const nsXPTType& type,
                                 JSBool useAllocator, const nsID* iid,
                                 nsresult* pErr);
 
     /**
      * Convert a native nsISupports into a JSObject.
      *
      * @param ccx the context for the whole procedure
@@ -3349,17 +3350,17 @@ public:
                                            XPCNativeInterface** Interface,
                                            bool allowNativeWrapper,
                                            nsresult* pErr);
 
     static JSBool GetNativeInterfaceFromJSObject(XPCCallContext& ccx,
                                                  void** dest, JSObject* src,
                                                  const nsID* iid,
                                                  nsresult* pErr);
-    static JSBool JSObject2NativeInterface(XPCCallContext& ccx,
+    static JSBool JSObject2NativeInterface(JSContext* cx,
                                            void** dest, JSObject* src,
                                            const nsID* iid,
                                            nsISupports* aOuter,
                                            nsresult* pErr);
     static JSBool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
 
     /**
      * Convert a native array into a jsval.
@@ -3373,21 +3374,21 @@ public:
      * @param scope the default scope to put on the new JSObjects' parent chain
      * @param pErr [out] relevant error code, if any.
      */
     static JSBool NativeArray2JS(XPCLazyCallContext& ccx,
                                  jsval* d, const void** s,
                                  const nsXPTType& type, const nsID* iid,
                                  uint32_t count, nsresult* pErr);
 
-    static JSBool JSArray2Native(XPCCallContext& ccx, void** d, jsval s,
+    static JSBool JSArray2Native(JSContext* cx, void** d, jsval s,
                                  uint32_t count, const nsXPTType& type,
                                  const nsID* iid, nsresult* pErr);
 
-    static JSBool JSTypedArray2Native(XPCCallContext& ccx,
+    static JSBool JSTypedArray2Native(JSContext* cx,
                                       void** d,
                                       JSObject* jsarray,
                                       uint32_t count,
                                       const nsXPTType& type,
                                       nsresult* pErr);
 
     static JSBool NativeStringWithSize2JS(JSContext* cx,
                                           jsval* d, const void* s,
@@ -3934,17 +3935,17 @@ private:
 // below. This system allows us to temporarily protect instances of our garbage
 // collected types after they are constructed but before they are safely
 // attached to other rooted objects.
 // This base class has pure virtual support for marking.
 
 class AutoMarkingPtr
 {
   public:
-    AutoMarkingPtr(XPCCallContext& ccx) {
+    AutoMarkingPtr(JSContext* cx) {
         mRoot = XPCJSRuntime::Get()->GetAutoRootsAdr();
         mNext = *mRoot;
         *mRoot = this;
     }
 
     virtual ~AutoMarkingPtr() {
         if (mRoot) {
             MOZ_ASSERT(*mRoot == this);
@@ -3970,18 +3971,18 @@ class AutoMarkingPtr
     AutoMarkingPtr** mRoot;
     AutoMarkingPtr* mNext;
 };
 
 template<class T>
 class TypedAutoMarkingPtr : public AutoMarkingPtr
 {
   public:
-    TypedAutoMarkingPtr(XPCCallContext& ccx) : AutoMarkingPtr(ccx), mPtr(nullptr) {}
-    TypedAutoMarkingPtr(XPCCallContext& ccx, T* ptr) : AutoMarkingPtr(ccx), mPtr(ptr) {}
+    TypedAutoMarkingPtr(JSContext* cx) : AutoMarkingPtr(cx), mPtr(nullptr) {}
+    TypedAutoMarkingPtr(JSContext* cx, T* ptr) : AutoMarkingPtr(cx), mPtr(ptr) {}
 
     T* get() const { return mPtr; }
     operator T *() const { return mPtr; }
     T* operator->() const { return mPtr; }
 
     TypedAutoMarkingPtr<T>& operator =(T* ptr) { mPtr = ptr; return *this; }
 
   protected:
@@ -4010,20 +4011,20 @@ typedef TypedAutoMarkingPtr<XPCWrappedNa
 typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
 typedef TypedAutoMarkingPtr<XPCMarkableJSVal> AutoMarkingJSVal;
 typedef TypedAutoMarkingPtr<XPCNativeScriptableInfo> AutoMarkingNativeScriptableInfoPtr;
 
 template<class T>
 class ArrayAutoMarkingPtr : public AutoMarkingPtr
 {
   public:
-    ArrayAutoMarkingPtr(XPCCallContext& ccx)
-      : AutoMarkingPtr(ccx), mPtr(nullptr), mCount(0) {}
-    ArrayAutoMarkingPtr(XPCCallContext& ccx, T** ptr, uint32_t count, bool clear)
-      : AutoMarkingPtr(ccx), mPtr(ptr), mCount(count)
+    ArrayAutoMarkingPtr(JSContext* cx)
+      : AutoMarkingPtr(cx), mPtr(nullptr), mCount(0) {}
+    ArrayAutoMarkingPtr(JSContext* cx, T** ptr, uint32_t count, bool clear)
+      : AutoMarkingPtr(cx), mPtr(ptr), mCount(count)
     {
         if (!mPtr) mCount = 0;
         else if (clear) memset(mPtr, 0, mCount*sizeof(T*));
     }
 
     T** get() const { return mPtr; }
     operator T **() const { return mPtr; }
     T** operator->() const { return mPtr; }
@@ -4059,20 +4060,20 @@ class ArrayAutoMarkingPtr : public AutoM
     uint32_t mCount;
 };
 
 typedef ArrayAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtrArrayPtr;
 
 #define AUTO_MARK_JSVAL_HELPER2(tok, line) tok##line
 #define AUTO_MARK_JSVAL_HELPER(tok, line) AUTO_MARK_JSVAL_HELPER2(tok, line)
 
-#define AUTO_MARK_JSVAL(ccx, val)                                             \
+#define AUTO_MARK_JSVAL(cx, val)                                              \
     XPCMarkableJSVal AUTO_MARK_JSVAL_HELPER(_val_,__LINE__)(val);             \
     AutoMarkingJSVal AUTO_MARK_JSVAL_HELPER(_automarker_,__LINE__)            \
-    (ccx, &AUTO_MARK_JSVAL_HELPER(_val_,__LINE__))
+    (cx, &AUTO_MARK_JSVAL_HELPER(_val_,__LINE__))
 
 /***************************************************************************/
 // Allocates a string that grants all access ("AllAccess")
 
 extern char* xpc_CloneAllAccess();
 /***************************************************************************/
 // Returns access if wideName is in list
 
@@ -4101,17 +4102,17 @@ public:
     // If this class ever implements nsIWritableVariant, take special care with
     // the case when mJSVal is JSVAL_STRING, since we don't own the data in
     // that case.
 
     // We #define and iid so that out module local code can use QI to detect
     // if a given nsIVariant is in fact an XPCVariant.
     NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
 
-    static XPCVariant* newVariant(XPCCallContext& ccx, jsval aJSVal);
+    static XPCVariant* newVariant(JSContext* cx, jsval aJSVal);
 
     /**
      * This getter clears the gray bit before handing out the jsval if the jsval
      * represents a JSObject. That means that the object is guaranteed to be
      * kept alive past the next CC.
      */
     jsval GetJSVal() const
         {if (!JSVAL_IS_PRIMITIVE(mJSVal))
@@ -4124,17 +4125,17 @@ public:
      * alive past the next CC.
      *
      * This should only be called if you are certain that the return value won't
      * be passed into a JS API function and that it won't be stored without
      * being rooted (or otherwise signaling the stored value to the CC).
      */
     jsval GetJSValPreserveColor() const {return mJSVal;}
 
-    XPCVariant(XPCCallContext& ccx, jsval aJSVal);
+    XPCVariant(JSContext* cx, jsval aJSVal);
 
     /**
      * Convert a variant into a jsval.
      *
      * @param ccx the context for the whole procedure
      * @param variant the variant to convert
      * @param scope the default scope to put on the new JSObject's parent chain
      * @param pErr [out] relevant error code, if any.
@@ -4158,35 +4159,35 @@ public:
     {
         mCCGeneration = aGen;
     }
 
     uint32_t CCGeneration() { return mCCGeneration; }
 protected:
     virtual ~XPCVariant() { }
 
-    JSBool InitializeData(XPCCallContext& ccx);
+    JSBool InitializeData(JSContext* cx);
 
 protected:
     nsDiscriminatedUnion mData;
     jsval                mJSVal;
     bool                 mReturnRawObject : 1;
     uint32_t             mCCGeneration : 31;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(XPCVariant, XPCVARIANT_IID)
 
 class XPCTraceableVariant: public XPCVariant,
                            public XPCRootSetElem
 {
 public:
-    XPCTraceableVariant(XPCCallContext& ccx, jsval aJSVal)
-        : XPCVariant(ccx, aJSVal)
+    XPCTraceableVariant(JSContext* cx, jsval aJSVal)
+        : XPCVariant(cx, aJSVal)
     {
-        ccx.GetRuntime()->AddVariantRoot(this);
+         nsXPConnect::GetRuntimeInstance()->AddVariantRoot(this);
     }
 
     virtual ~XPCTraceableVariant();
 
     void TraceJS(JSTracer* trc);
     static void GetTraceName(JSTracer* trc, char *buf, size_t bufsize);
 };
 
--- a/js/xpconnect/tests/mochitest/Makefile.in
+++ b/js/xpconnect/tests/mochitest/Makefile.in
@@ -72,16 +72,17 @@ MOCHITEST_FILES =	bug500931_helper.html 
 		file_expandosharing.html \
 		file_empty.html \
 		file_documentdomain.html \
 		test_lookupMethod.html \
 		file_bug738244.html \
 		file_mozMatchesSelector.html \
 		file_bug720619.html \
 		test_bug720619.html \
+		test_bug785096.html \
 		$(NULL)
 
 MOCHITEST_CHROME_FILES	= \
 		test_bug361111.xul \
 		test_bug760131.html \
 		$(NULL)
 
 ifneq ($(OS_TARGET),Android)
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/mochitest/test_bug785096.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=390488
+-->
+<head>
+  <title>Test for Bug 785096</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=785096">Mozilla Bug 785096</a>
+
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 785096 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function test()
+{
+  var sel = document.createElementNS('http://www.w3.org/1999/xhtml', 'select');
+  var option=document.createElement("option");
+  option.text="Fubar";
+  sel.options.add(option);
+  try {
+    Components.lookupMethod(sel.options, "add")(option);
+    ok(true, "function call should not throw")
+  } catch(e) {
+    do_throw("this call should just work without any exceptions");
+  }
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -428,17 +428,17 @@ protected:
   unsigned                         mPrintPreviewZoomed : 1;
 
   // These data members support delayed printing when the document is loading
   unsigned                         mPrintIsPending : 1;
   unsigned                         mPrintDocIsFullyLoaded : 1;
   nsCOMPtr<nsIPrintSettings>       mCachedPrintSettings;
   nsCOMPtr<nsIWebProgressListener> mCachedPrintWebProgressListner;
 
-  nsCOMPtr<nsPrintEngine>          mPrintEngine;
+  nsRefPtr<nsPrintEngine>          mPrintEngine;
   float                            mOriginalPrintPreviewScale;
   float                            mPrintPreviewZoom;
   nsAutoPtr<nsPrintEventDispatcher> mBeforeAndAfterPrint;
 #endif // NS_PRINT_PREVIEW
 
 #ifdef DEBUG
   FILE* mDebugFile;
 #endif // DEBUG
@@ -2137,22 +2137,16 @@ DocumentViewerImpl::CreateStyleSet(nsIDo
   // different sets for different media
   nsStyleSet *styleSet = new nsStyleSet();
 
   styleSet->BeginUpdate();
   
   // The document will fill in the document sheets when we create the presshell
   
   // Handle the user sheets.
-#ifdef DEBUG
-  nsCOMPtr<nsISupports> debugDocContainer = aDocument->GetContainer();
-  nsCOMPtr<nsIDocShellTreeItem> debugDocShell(do_QueryReferent(mContainer));
-  NS_ASSERTION(SameCOMIdentity(debugDocContainer, debugDocShell),
-               "Unexpected containers");
-#endif
   nsCSSStyleSheet* sheet = nullptr;
   if (nsContentUtils::IsInChromeDocshell(aDocument)) {
     sheet = nsLayoutStylesheetCache::UserChromeSheet();
   }
   else {
     sheet = nsLayoutStylesheetCache::UserContentSheet();
   }
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -514,16 +514,25 @@ nsRefreshDriver::IsRefreshObserver(nsARe
                                    mozFlushType aFlushType)
 {
   ObserverArray& array = ArrayFor(aFlushType);
   return array.Contains(aObserver);
 }
 #endif
 
 void
+nsRefreshDriver::ScheduleViewManagerFlush()
+{
+  NS_ASSERTION(mPresContext->IsRoot(),
+               "Should only schedule view manager flush on root prescontexts");
+  mViewManagerFlushIsPending = true;
+  EnsureTimerStarted(false);
+}
+
+void
 nsRefreshDriver::ScheduleFrameRequestCallbacks(nsIDocument* aDocument)
 {
   NS_ASSERTION(mFrameRequestCallbackDocs.IndexOf(aDocument) ==
                mFrameRequestCallbackDocs.NoIndex,
                "Don't schedule the same document multiple times");
   mFrameRequestCallbackDocs.AppendElement(aDocument);
   // No need to worry about restarting our timer in precise mode if it's
   // already running; that will happen automatically when it fires.
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -143,20 +143,17 @@ public:
   }
   bool IsLayoutFlushObserver(nsIPresShell* aShell) {
     return mLayoutFlushObservers.Contains(aShell);
   }
 
   /**
    * Remember whether our presshell's view manager needs a flush
    */
-  void ScheduleViewManagerFlush() {
-    mViewManagerFlushIsPending = true;
-    EnsureTimerStarted(false);
-  }
+  void ScheduleViewManagerFlush();
   void RevokeViewManagerFlush() {
     mViewManagerFlushIsPending = false;
   }
 
   /**
    * Add a document for which we have nsIFrameRequestCallbacks
    */
   void ScheduleFrameRequestCallbacks(nsIDocument* aDocument);
--- a/layout/printing/Makefile.in
+++ b/layout/printing/Makefile.in
@@ -32,11 +32,12 @@ CPPSRCS		= \
 
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
 		-I$(srcdir)/../base \
 		-I$(srcdir)/../../content/base/src \
+		-I$(srcdir)/../../view/src \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/layout/printing/nsPagePrintTimer.cpp
+++ b/layout/printing/nsPagePrintTimer.cpp
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsPagePrintTimer.h"
 #include "nsIContentViewer.h"
 #include "nsIServiceManager.h"
 #include "nsPrintEngine.h"
 
-NS_IMPL_ISUPPORTS1(nsPagePrintTimer, nsITimerCallback)
+NS_IMPL_ISUPPORTS_INHERITED1(nsPagePrintTimer, nsRunnable, nsITimerCallback)
 
 nsPagePrintTimer::~nsPagePrintTimer()
 {
   // "Destroy" the document viewer; this normally doesn't actually
   // destroy it because of the IncrementDestroyRefCount call below
   // XXX This is messy; the document viewer should use a single approach
   // to keep itself alive during printing
   nsCOMPtr<nsIContentViewer> cv(do_QueryInterface(mDocViewerPrint));
--- a/layout/printing/nsPagePrintTimer.h
+++ b/layout/printing/nsPagePrintTimer.h
@@ -13,18 +13,18 @@
 #include "mozilla/Attributes.h"
 #include "nsThreadUtils.h"
 
 class nsPrintEngine;
 
 //---------------------------------------------------
 //-- Page Timer Class
 //---------------------------------------------------
-class nsPagePrintTimer MOZ_FINAL : public nsITimerCallback,
-                                   public nsRunnable
+class nsPagePrintTimer MOZ_FINAL : public nsRunnable,
+                                   public nsITimerCallback
 {
 public:
 
   NS_DECL_ISUPPORTS
 
   nsPagePrintTimer(nsPrintEngine* aPrintEngine,
                    nsIDocumentViewerPrint* aDocViewerPrint,
                    uint32_t aDelay)
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -13,16 +13,19 @@
 #include "nsIScriptGlobalObject.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocShell.h"
 #include "nsIFrame.h"
 #include "nsIURI.h"
 #include "nsITextToSubURI.h"
 #include "nsError.h"
 
+#include "nsView.h"
+#include "nsAsyncDOMEvent.h"
+
 // Print Options
 #include "nsIPrintSettings.h"
 #include "nsIPrintSettingsService.h"
 #include "nsIPrintOptions.h"
 #include "nsIPrintSession.h"
 #include "nsGfxCIID.h"
 #include "nsIServiceManager.h"
 #include "nsGkAtoms.h"
@@ -204,33 +207,36 @@ public:
 protected:
   nsRefPtr<nsPrintEngine> mPrintEngine;
   bool                    mSuppressed;
 };
 
 // Class IDs
 static NS_DEFINE_CID(kViewManagerCID,       NS_VIEW_MANAGER_CID);
 
-NS_IMPL_ISUPPORTS1(nsPrintEngine, nsIObserver)
+NS_IMPL_ISUPPORTS3(nsPrintEngine, nsIWebProgressListener,
+                   nsISupportsWeakReference, nsIObserver)
 
 //---------------------------------------------------
 //-- nsPrintEngine Class Impl
 //---------------------------------------------------
 nsPrintEngine::nsPrintEngine() :
   mIsCreatingPrintPreview(false),
   mIsDoingPrinting(false),
   mIsDoingPrintPreview(false),
   mProgressDialogIsShown(false),
   mScreenDPI(115.0f),
   mPrt(nullptr),
   mPagePrintTimer(nullptr),
   mPageSeqFrame(nullptr),
   mPrtPreview(nullptr),
   mOldPrtPreview(nullptr),
-  mDebugFile(nullptr)
+  mDebugFile(nullptr),
+  mLoadCounter(0),
+  mDidLoadDataForPrinting(false)
 {
 }
 
 //-------------------------------------------------------
 nsPrintEngine::~nsPrintEngine()
 {
   Destroy(); // for insurance
 }
@@ -667,37 +673,54 @@ nsPrintEngine::DoCommonPrint(bool       
           mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType);
         }
       }
     } else {
       mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType);
     }
   }
 
+  if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
+    CheckForChildFrameSets(mPrt->mPrintObject);
+  }
+
+  if (NS_FAILED(EnablePOsForPrinting())) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Attach progressListener to catch network requests.
+  nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell);
+  webProgress->AddProgressListener(
+    static_cast<nsIWebProgressListener*>(this),
+    nsIWebProgress::NOTIFY_STATE_REQUEST);
+
+  mLoadCounter = 0;
+  mDidLoadDataForPrinting = false;
+
   if (aIsPrintPreview) {
     bool notifyOnInit = false;
     ShowPrintProgress(false, notifyOnInit);
 
     // Very important! Turn Off scripting
     TurnScriptingOn(false);
 
     if (!notifyOnInit) {
-      rv = FinishPrintPreview();
+      InstallPrintPreviewListener();
+      rv = InitPrintDocConstruction(false);
     } else {
       rv = NS_OK;
     }
-    NS_ENSURE_SUCCESS(rv, rv);
   } else {
     bool doNotify;
     ShowPrintProgress(true, doNotify);
     if (!doNotify) {
       // Print listener setup...
       mPrt->OnStartPrinting();
-      rv = DocumentReadyForPrinting();
-      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = InitPrintDocConstruction(false);
     }
   }
 
   // We will enable scripting later after printing has finished.
   scriptSuppressor.Disconnect();
 
   return NS_OK;
 }
@@ -799,20 +822,29 @@ nsPrintEngine::GetIsFramesetFrameSelecte
 
 //----------------------------------------------------------------------------------
 /* readonly attribute long printPreviewNumPages; */
 NS_IMETHODIMP
 nsPrintEngine::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages)
 {
   NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages);
 
+  nsPrintData* prt = nullptr;
   nsIFrame* seqFrame  = nullptr;
   *aPrintPreviewNumPages = 0;
-  if (!mPrtPreview ||
-      NS_FAILED(GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, seqFrame, *aPrintPreviewNumPages))) {
+
+  // When calling this function, the FinishPrintPreview() function might not
+  // been called as there are still some 
+  if (mPrtPreview) {
+    prt = mPrtPreview;
+  } else {
+    prt = mPrt;
+  }
+  if ((!prt) ||
+      NS_FAILED(GetSeqFrameAndCountPagesInternal(prt->mPrintObject, seqFrame, *aPrintPreviewNumPages))) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 //----------------------------------------------------------------------------------
 // Enumerate all the documents for their titles
 NS_IMETHODIMP
@@ -1593,111 +1625,136 @@ nsPrintEngine::ShowPrintErrorDialog(nsre
   dialog->Alert(title.get(), msg.get());
   PR_PL(("ShowPrintErrorDialog(): alert displayed successfully.\n"));
 }
 
 //-----------------------------------------------------------------
 //-- Section: Reflow Methods
 //-----------------------------------------------------------------
 
+nsresult
+nsPrintEngine::ReconstructAndReflow(bool doSetPixelScale)
+{
+#if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING)
+  // We need to clear all the output files here
+  // because they will be re-created with second reflow of the docs
+  if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) {
+    RemoveFilesInDir(".\\");
+    gDumpFileNameCnt   = 0;
+    gDumpLOFileNameCnt = 0;
+  }
+#endif
+
+  for (uint32_t i = 0; i < mPrt->mPrintDocList.Length(); ++i) {
+    nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
+    NS_ASSERTION(po, "nsPrintObject can't be null!");
+
+    if (po->mDontPrint || po->mInvisible) {
+      continue;
+    }
+
+    UpdateZoomRatio(po, doSetPixelScale);
+
+    po->mPresContext->SetPageScale(po->mZoomRatio);
+
+    // Calculate scale factor from printer to screen
+    float printDPI = float(mPrt->mPrintDC->AppUnitsPerCSSInch()) /
+                     float(mPrt->mPrintDC->AppUnitsPerDevPixel());
+    po->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI);
+
+    po->mPresShell->ReconstructFrames();
+
+    // For all views except the first one, setup the root view.
+    // ??? Can there be multiple po for the top-level-document?
+    bool documentIsTopLevel = true;
+    if (i != 0) {
+      nsSize adjSize;
+      bool doReturn; 
+      nsresult rv = SetRootView(po, doReturn, documentIsTopLevel, adjSize);
+
+      MOZ_ASSERT(!documentIsTopLevel, "How could this happen?");
+      
+      if (NS_FAILED(rv) || doReturn) {
+        return rv; 
+      }
+    }
+
+    po->mPresShell->FlushPendingNotifications(Flush_Layout);
+
+    nsresult rv = UpdateSelectionAndShrinkPrintObject(po, documentIsTopLevel);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return NS_OK;
+}
+
 //-------------------------------------------------------
 nsresult
 nsPrintEngine::SetupToPrintContent()
 {
-  // In this step we figure out which documents should be printed
-  // i.e. if we are printing the selection then only enable that nsPrintObject
-  // for printing
-  if (NS_FAILED(EnablePOsForPrinting())) {
-    return NS_ERROR_FAILURE;
+  nsresult rv;
+
+  bool didReconstruction = false;
+  
+  // If some new content got loaded since the initial reflow rebuild
+  // everything.
+  if (mDidLoadDataForPrinting) {
+    rv = ReconstructAndReflow(DoSetPixelScale());
+    didReconstruction = true;
+    NS_ENSURE_SUCCESS(rv, rv);
   }
-  DUMP_DOC_LIST("\nAfter Enable------------------------------------------");
-
-  // This is an Optimization
-  // If we are in PP then we already know all the shrinkage information
-  // so just transfer it to the PrintData and we will skip the extra shrinkage reflow
-  //
-  // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC
-  // The first time we do not want to do this, the second time through we do
-  bool doSetPixelScale = false;
+
+  // Here is where we figure out if extra reflow for shrinking the content
+  // is required.
+  // But skip this step if we are in PrintPreview
   bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit;
-  if (ppIsShrinkToFit) {
-    mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio;
-    doSetPixelScale = true;
-  }
-
-  // Here we reflow all the PrintObjects
-  nsresult rv = ReflowDocList(mPrt->mPrintObject, doSetPixelScale);
-  if (NS_FAILED(rv)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Here is where we do the extra reflow for shrinking the content
-  // But skip this step if we are in PrintPreview
   if (mPrt->mShrinkToFit && !ppIsShrinkToFit) {
     // Now look for the PO that has the smallest percent for shrink to fit
     if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) {
       nsPrintObject* smallestPO = FindSmallestSTF();
       NS_ASSERTION(smallestPO, "There must always be an XMost PO!");
       if (smallestPO) {
         // Calc the shrinkage based on the entire content area
         mPrt->mShrinkRatio = smallestPO->mShrinkRatio;
       }
     } else {
       // Single document so use the Shrink as calculated for the PO
       mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio;
     }
 
-    // Only Shrink if we are smaller
     if (mPrt->mShrinkRatio < 0.998f) {
-      for (uint32_t i=0;i<mPrt->mPrintDocList.Length();i++) {
-        nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
-        NS_ASSERTION(po, "nsPrintObject can't be null!");
-        // Wipe out the presentation before we reflow
-        po->DestroyPresentation();
-      }
-
-#if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING)
-      // We need to clear all the output files here
-      // because they will be re-created with second reflow of the docs
-      if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) {
-        RemoveFilesInDir(".\\");
-        gDumpFileNameCnt   = 0;
-        gDumpLOFileNameCnt = 0;
-      }
-#endif
-
-      // Here we reflow all the PrintObjects a second time
-      // this time using the shrinkage values
-      // The last param here tells reflow to NOT calc the shrinkage values
-      if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, true))) {
-        return NS_ERROR_FAILURE;
-      }
+      rv = ReconstructAndReflow(true);
+      didReconstruction = true;
+      NS_ENSURE_SUCCESS(rv, rv);
     }
 
 #ifdef PR_LOGGING
-    {
-      float calcRatio = 0.0f;
-      if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) {
-        nsPrintObject* smallestPO = FindSmallestSTF();
-        NS_ASSERTION(smallestPO, "There must always be an XMost PO!");
-        if (smallestPO) {
-          // Calc the shrinkage based on the entire content area
-          calcRatio = smallestPO->mShrinkRatio;
-        }
-      } else {
-        // Single document so use the Shrink as calculated for the PO
-        calcRatio = mPrt->mPrintObject->mShrinkRatio;
+    float calcRatio = 0.0f;
+    if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) {
+      nsPrintObject* smallestPO = FindSmallestSTF();
+      NS_ASSERTION(smallestPO, "There must always be an XMost PO!");
+      if (smallestPO) {
+        // Calc the shrinkage based on the entire content area
+        calcRatio = smallestPO->mShrinkRatio;
       }
-      PR_PL(("**************************************************************************\n"));
-      PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio,  mPrt->mShrinkRatio-calcRatio));
-      PR_PL(("**************************************************************************\n"));
+    } else {
+      // Single document so use the Shrink as calculated for the PO
+      calcRatio = mPrt->mPrintObject->mShrinkRatio;
     }
+    PR_PL(("**************************************************************************\n"));
+    PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio,  mPrt->mShrinkRatio-calcRatio));
+    PR_PL(("**************************************************************************\n"));
 #endif
   }
-
+  
+  // If the frames got reconstructed and reflowed the number of pages might
+  // has changed.
+  if (didReconstruction) {
+    FirePrintPreviewUpdateEvent();
+  }
+  
   DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------"));
   PR_PL(("\n"));
   PR_PL(("-------------------------------------------------------\n"));
   PR_PL(("\n"));
 
   CalcNumPrintablePages(mPrt->mNumPrintablePages);
 
   PR_PL(("--- Printing %d pages\n", mPrt->mNumPrintablePages));
@@ -1787,67 +1844,273 @@ nsPrintEngine::ReflowDocList(nsPrintObje
     nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr;
     if (!frame || !frame->GetStyleVisibility()->IsVisible()) {
       aPO->mDontPrint = true;
       aPO->mInvisible = true;
       return NS_OK;
     }
   }
 
+  UpdateZoomRatio(aPO, aSetPixelScale);
+
+  nsresult rv;
+  // Reflow the PO
+  rv = ReflowPrintObject(aPO);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  int32_t cnt = aPO->mKids.Length();
+  for (int32_t i=0;i<cnt;i++) {
+    rv = ReflowDocList(aPO->mKids[i], aSetPixelScale);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return NS_OK;
+}
+
+void
+nsPrintEngine::FirePrintPreviewUpdateEvent()
+{
+  // Dispatch the event only while in PrintPreview. When printing, there is no
+  // listener bound to this event and therefore no need to dispatch it.
+  if (mIsDoingPrintPreview && !mIsDoingPrinting) {
+    nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
+    (new nsAsyncDOMEvent(
+       cv->GetDocument(), NS_LITERAL_STRING("printPreviewUpdate"), true, true)
+    )->RunDOMEventWhenSafe();
+  }
+}
+
+nsresult
+nsPrintEngine::InitPrintDocConstruction(bool aHandleError)
+{
+  nsresult rv;
+  rv = ReflowDocList(mPrt->mPrintObject, DoSetPixelScale());
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  FirePrintPreviewUpdateEvent();
+
+  if (mLoadCounter == 0) {
+    AfterNetworkPrint(aHandleError);
+  }
+  return rv;
+}
+
+nsresult
+nsPrintEngine::AfterNetworkPrint(bool aHandleError)
+{
+  nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell);
+
+  webProgress->RemoveProgressListener(
+    static_cast<nsIWebProgressListener*>(this));
+
+  nsresult rv;
+  if (mIsDoingPrinting) {
+    rv = DocumentReadyForPrinting();
+  } else {
+    rv = FinishPrintPreview();
+  }
+
+  /* cleaup on failure + notify user */
+  if (aHandleError && NS_FAILED(rv)) {
+    CleanupOnFailure(rv, !mIsDoingPrinting);
+  }
+
+  return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIWebProgressListener
+
+NS_IMETHODIMP
+nsPrintEngine::OnStateChange(nsIWebProgress* aWebProgress,
+                             nsIRequest* aRequest,
+                             uint32_t aStateFlags,
+                             nsresult aStatus)
+{
+  nsAutoCString name;
+  aRequest->GetName(name);
+  if (name.Equals("about:document-onload-blocker")) {
+    return NS_OK;
+  }
+  if (aStateFlags & STATE_START) {
+    nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+
+    ++mLoadCounter;
+  } else if (aStateFlags & STATE_STOP) {
+    mDidLoadDataForPrinting = true;
+    --mLoadCounter;
+   
+    // If all resources are loaded, then do a small timeout and if there
+    // are still no new requests, then another reflow.
+    if (mLoadCounter == 0) {
+      AfterNetworkPrint(true);
+    }
+  }
+  return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+nsPrintEngine::OnProgressChange(nsIWebProgress* aWebProgress,
+                                 nsIRequest* aRequest,
+                                 int32_t aCurSelfProgress,
+                                 int32_t aMaxSelfProgress,
+                                 int32_t aCurTotalProgress,
+                                 int32_t aMaxTotalProgress)
+{
+  NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintEngine::OnLocationChange(nsIWebProgress* aWebProgress,
+                                nsIRequest* aRequest,
+                                nsIURI* aLocation,
+                                uint32_t aFlags)
+{
+  NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintEngine::OnStatusChange(nsIWebProgress *aWebProgress,
+                              nsIRequest *aRequest,
+                              nsresult aStatus,
+                              const PRUnichar *aMessage)
+{
+  NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintEngine::OnSecurityChange(nsIWebProgress *aWebProgress,
+                                  nsIRequest *aRequest,
+                                  uint32_t aState)
+{
+  NS_NOTREACHED("notification excluded in AddProgressListener(...)");
+  return NS_OK;
+}
+
+//-------------------------------------------------------
+
+void
+nsPrintEngine::UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale)
+{
   // Here is where we set the shrinkage value into the DC
   // and this is what actually makes it shrink
   if (aSetPixelScale && aPO->mFrameType != eIFrame) {
     float ratio;
     if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) {
       ratio = mPrt->mShrinkRatio - 0.005f; // round down
     } else {
       ratio = aPO->mShrinkRatio - 0.005f; // round down
     }
     aPO->mZoomRatio = ratio;
   } else if (!mPrt->mShrinkToFit) {
     double scaling;
     mPrt->mPrintSettings->GetScaling(&scaling);
     aPO->mZoomRatio = float(scaling);
+  } 
+}
+
+nsresult
+nsPrintEngine::UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO,
+                                                   bool aDocumentIsTopLevel)
+{
+  nsCOMPtr<nsIPresShell> displayShell;
+  aPO->mDocShell->GetPresShell(getter_AddRefs(displayShell));
+  // Transfer Selection Ranges to the new Print PresShell
+  nsCOMPtr<nsISelection> selection, selectionPS;
+  // It's okay if there is no display shell, just skip copying the selection
+  if (displayShell) {
+    selection = displayShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
   }
-
-  nsresult rv;
-  // Reflow the PO
-  rv = ReflowPrintObject(aPO);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  int32_t cnt = aPO->mKids.Length();
-  for (int32_t i=0;i<cnt;i++) {
-    rv = ReflowDocList(aPO->mKids[i], aSetPixelScale);
-    NS_ENSURE_SUCCESS(rv, rv);
+  selectionPS = aPO->mPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
+
+  // Reset all existing selection ranges that might have been added by calling
+  // this function before.
+  if (selectionPS) {
+    selectionPS->RemoveAllRanges();
+  }
+  if (selection && selectionPS) {
+    int32_t cnt;
+    selection->GetRangeCount(&cnt);
+    int32_t inx;
+    for (inx = 0; inx < cnt; ++inx) {
+      nsCOMPtr<nsIDOMRange> range;
+      if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range))))
+        selectionPS->AddRange(range);
+    }
+  }
+
+  // If we are trying to shrink the contents to fit on the page
+  // we must first locate the "pageContent" frame
+  // Then we walk the frame tree and look for the "xmost" frame
+  // this is the frame where the right-hand side of the frame extends
+  // the furthest
+  if (mPrt->mShrinkToFit && aDocumentIsTopLevel) {
+    nsIPageSequenceFrame* pageSequence = aPO->mPresShell->GetPageSequenceFrame();
+    NS_ENSURE_STATE(pageSequence);
+    pageSequence->GetSTFPercent(aPO->mShrinkRatio);
   }
   return NS_OK;
 }
 
-//-------------------------------------------------------
-// Reflow a nsPrintObject
-nsresult
-nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO)
+bool
+nsPrintEngine::DoSetPixelScale()
+{
+  // This is an Optimization
+  // If we are in PP then we already know all the shrinkage information
+  // so just transfer it to the PrintData and we will skip the extra shrinkage reflow
+  //
+  // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC
+  // The first time we do not want to do this, the second time through we do
+  bool doSetPixelScale = false;
+  bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit;
+  if (ppIsShrinkToFit) {
+    mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio;
+    doSetPixelScale = true;
+  }
+  return doSetPixelScale;
+}
+
+nsIView*
+nsPrintEngine::GetParentViewForRoot()
 {
-  NS_ASSERTION(aPO, "Pointer is null!");
-  if (!aPO) return NS_ERROR_FAILURE;
-
-  nsSize adjSize;
-  bool documentIsTopLevel;
-  if (!aPO->IsPrintable())
-    return NS_OK;
-
+  if (mIsCreatingPrintPreview) {
+    nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
+    if (cv) {
+      return cv->FindContainerView();
+    }
+  }
+  return nullptr;
+}
+
+nsresult
+nsPrintEngine::SetRootView(
+    nsPrintObject* aPO, 
+    bool& doReturn, 
+    bool& documentIsTopLevel, 
+    nsSize& adjSize
+)
+{
   bool canCreateScrollbars = true;
+
+  nsIView* rootView;
   nsIView* parentView = nullptr;
 
+  doReturn = false;
+
   if (aPO->mParent && aPO->mParent->IsPrintable()) {
     nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr;
     // Without a frame, this document can't be displayed; therefore, there is no
     // point to reflowing it
     if (!frame) {
       SetPrintPO(aPO, false);
+      doReturn = true;
       return NS_OK;
     }
 
     //XXX If printing supported printing document hierarchies with non-constant
     // zoom this would be wrong as we use the same mPrt->mPrintDC for all
     // subdocuments.
     adjSize = frame->GetContentRect().Size();
     documentIsTopLevel = false;
@@ -1862,31 +2125,61 @@ nsPrintEngine::ReflowPrintObject(nsPrint
       parentView = view;
       canCreateScrollbars = false;
     }
   } else {
     nscoord pageWidth, pageHeight;
     mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight);
     adjSize = nsSize(pageWidth, pageHeight);
     documentIsTopLevel = true;
-
-    if (mIsCreatingPrintPreview) {
-      nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
-      if (cv) {
-        parentView = cv->FindContainerView();
-      }
-    }
+    parentView = GetParentViewForRoot();
+  }
+
+  if (aPO->mPresShell->GetViewManager()->GetRootView()) {
+    // Reuse the root view that is already on the root frame.
+    rootView = aPO->mPresShell->GetRootFrame()->GetView();
+    reinterpret_cast<nsView*>(rootView)->SetParent(reinterpret_cast<nsView*>(parentView));
+  } else {
+    // Create a child window of the parent that is our "root view/window"
+    nsRect tbounds = nsRect(nsPoint(0, 0), adjSize);
+    rootView = aPO->mViewManager->CreateView(tbounds, parentView);
+    NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY);
+  }
+    
+  if (mIsCreatingPrintPreview && documentIsTopLevel) {
+    aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars);
   }
 
+  // Setup hierarchical relationship in view manager
+  aPO->mViewManager->SetRootView(rootView);
+
+  return NS_OK;
+}
+
+// Reflow a nsPrintObject
+nsresult
+nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO)
+{
+  NS_ENSURE_STATE(aPO);
+
+  if (!aPO->IsPrintable()) {
+    return NS_OK;
+  }
+  
   NS_ASSERTION(!aPO->mPresContext, "Recreating prescontext");
 
   // create the PresContext
-  aPO->mPresContext = new nsPresContext(aPO->mDocument,
-    mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview:
-                              nsPresContext::eContext_Print);
+  nsPresContext::nsPresContextType type =
+      mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview:
+                                nsPresContext::eContext_Print;
+  nsIView* parentView =
+    aPO->mParent && aPO->mParent->IsPrintable() ? nullptr : GetParentViewForRoot();
+  aPO->mPresContext = parentView ?
+      new nsPresContext(aPO->mDocument, type) :
+      new nsRootPresContext(aPO->mDocument, type);
   NS_ENSURE_TRUE(aPO->mPresContext, NS_ERROR_OUT_OF_MEMORY);
   aPO->mPresContext->SetPrintSettings(mPrt->mPrintSettings);
 
   // set the presentation context to the value in the print settings
   bool printBGColors;
   mPrt->mPrintSettings->GetPrintBGColors(&printBGColors);
   aPO->mPresContext->SetBackgroundColorDraw(printBGColors);
   mPrt->mPrintSettings->GetPrintBGImages(&printBGColors);
@@ -1912,30 +2205,30 @@ nsPrintEngine::ReflowPrintObject(nsPrint
     delete styleSet;
     return rv;
   }
 
   styleSet->EndUpdate();
   
   // The pres shell now owns the style set object.
 
-  PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO,
+
+  bool doReturn = false;;
+  bool documentIsTopLevel = false;
+  nsSize adjSize; 
+
+  rv = SetRootView(aPO, doReturn, documentIsTopLevel, adjSize);
+
+  if (NS_FAILED(rv) || doReturn) {
+    return rv; 
+  }
+
+  PR_PL(("In DV::ReflowPrintObject PO: %p pS: %p (%9s) Setting w,h to %d,%d\n", aPO, aPO->mPresShell.get(),
          gFrameTypesStr[aPO->mFrameType], adjSize.width, adjSize.height));
 
-  // Create a child window of the parent that is our "root view/window"
-  nsRect tbounds = nsRect(nsPoint(0, 0), adjSize);
-  nsIView* rootView = aPO->mViewManager->CreateView(tbounds, parentView);
-  NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY);
-
-  if (mIsCreatingPrintPreview && documentIsTopLevel) {
-    aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars);
-  }
-
-  // Setup hierarchical relationship in view manager
-  aPO->mViewManager->SetRootView(rootView);
 
   // This docshell stuff is weird; will go away when we stop having multiple
   // presentations per document
   nsCOMPtr<nsISupports> supps(do_QueryInterface(aPO->mDocShell));
   aPO->mPresContext->SetContainer(supps);
 
   aPO->mPresShell->BeginObservingDocument();
 
@@ -1956,46 +2249,18 @@ nsPrintEngine::ReflowPrintObject(nsPrint
   rv = aPO->mPresShell->Initialize(adjSize.width, adjSize.height);
 
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(aPO->mPresShell, "Presshell should still be here");
 
   // Process the reflow event Initialize posted
   aPO->mPresShell->FlushPendingNotifications(Flush_Layout);
 
-  nsCOMPtr<nsIPresShell> displayShell;
-  aPO->mDocShell->GetPresShell(getter_AddRefs(displayShell));
-  // Transfer Selection Ranges to the new Print PresShell
-  nsCOMPtr<nsISelection> selection, selectionPS;
-  // It's okay if there is no display shell, just skip copying the selection
-  if (displayShell) {
-    selection = displayShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
-  }
-  selectionPS = aPO->mPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
-  if (selection && selectionPS) {
-    int32_t cnt;
-    selection->GetRangeCount(&cnt);
-    int32_t inx;
-    for (inx=0;inx<cnt;inx++) {
-      nsCOMPtr<nsIDOMRange> range;
-      if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range))))
-        selectionPS->AddRange(range);
-    }
-  }
-
-  // If we are trying to shrink the contents to fit on the page
-  // we must first locate the "pageContent" frame
-  // Then we walk the frame tree and look for the "xmost" frame
-  // this is the frame where the right-hand side of the frame extends
-  // the furthest
-  if (mPrt->mShrinkToFit && documentIsTopLevel) {
-    nsIPageSequenceFrame* pageSequence = aPO->mPresShell->GetPageSequenceFrame();
-    NS_ENSURE_STATE(pageSequence);
-    pageSequence->GetSTFPercent(aPO->mShrinkRatio);
-  }
+  rv = UpdateSelectionAndShrinkPrintObject(aPO, documentIsTopLevel);
+  NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef EXTENDED_DEBUG_PRINTING
     if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) {
       char * docStr;
       char * urlStr;
       GetDocTitleAndURL(aPO, docStr, urlStr);
       char filename[256];
       sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++);
@@ -3304,17 +3569,16 @@ nsPrintEngine::FinishPrintPreview()
   // before it is to be created
 
 
   if (mIsDoingPrintPreview && mOldPrtPreview) {
     delete mOldPrtPreview;
     mOldPrtPreview = nullptr;
   }
 
-  InstallPrintPreviewListener();
 
   mPrt->OnEndPrinting();
 
   // PrintPreview was built using the mPrt (code reuse)
   // then we assign it over
   mPrtPreview = mPrt;
   mPrt        = nullptr;
 
@@ -3347,32 +3611,19 @@ nsPrintEngine::StartPagePrintTimer(nsPri
 }
 
 /*=============== nsIObserver Interface ======================*/
 NS_IMETHODIMP 
 nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
 {
   nsresult rv = NS_ERROR_FAILURE;
 
-  if (mIsDoingPrinting) {
-    rv = DocumentReadyForPrinting();
- 
-    /* cleaup on failure + notify user */
-    if (NS_FAILED(rv)) {
-      CleanupOnFailure(rv, true);
-    }
-  } else {
-    rv = FinishPrintPreview();
-    if (NS_FAILED(rv)) {
-      CleanupOnFailure(rv, false);
-    }
-    if (mPrtPreview) {
+  rv = InitPrintDocConstruction(true);
+  if (!mIsDoingPrinting && mPrtPreview) {
       mPrtPreview->OnEndPrinting();
-    }
-    rv = NS_OK;
   }
 
   return rv;
 
 }
 
 //---------------------------------------------------------------
 //-- PLEvent Notification
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -8,17 +8,20 @@
 #include "mozilla/Attributes.h"
 
 #include "nsCOMPtr.h"
 
 #include "nsPrintObject.h"
 #include "nsPrintData.h"
 #include "nsFrameList.h"
 #include "mozilla/Attributes.h"
+#include "nsIWebProgress.h"
 #include "nsHTMLCanvasElement.h"
+#include "nsIWebProgressListener.h"
+#include "nsWeakReference.h"
 
 // Interfaces
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsIObserver.h"
 
 // Classes
 class nsPagePrintTimer;
@@ -29,25 +32,29 @@ class nsPrintObject;
 class nsIDocShell;
 class nsIPageSequenceFrame;
 class nsIWeakReference;
 
 //------------------------------------------------------------------------
 // nsPrintEngine Class
 //
 //------------------------------------------------------------------------
-class nsPrintEngine MOZ_FINAL : public nsIObserver
+class nsPrintEngine MOZ_FINAL : public nsIObserver,
+                                public nsIWebProgressListener,
+                                public nsSupportsWeakReference
 {
 public:
   // nsISupports interface...
   NS_DECL_ISUPPORTS
 
   // nsIObserver
   NS_DECL_NSIOBSERVER
 
+  NS_DECL_NSIWEBPROGRESSLISTENER
+
   // Old nsIWebBrowserPrint methods; not cleaned up yet
   NS_IMETHOD Print(nsIPrintSettings*       aPrintSettings,
                    nsIWebProgressListener* aWebProgressListener);
   NS_IMETHOD PrintPreview(nsIPrintSettings* aPrintSettings,
                           nsIDOMWindow *aChildDOMWin,
                           nsIWebProgressListener* aWebProgressListener);
   NS_IMETHOD GetIsFramesetDocument(bool *aIsFramesetDocument);
   NS_IMETHOD GetIsIFrameSelected(bool *aIsIFrameSelected);
@@ -266,13 +273,30 @@ protected:
   // Print Preview
   nsPrintData*            mPrtPreview;
   nsPrintData*            mOldPrtPreview;
 
   nsCOMPtr<nsIDocument>   mDocument;
 
   FILE* mDebugFile;
 
+  int32_t mLoadCounter;
+  bool mDidLoadDataForPrinting;
+
+  nsresult AfterNetworkPrint(bool aHandleError);
+
+  nsresult SetRootView(nsPrintObject* aPO,
+                       bool& aDoReturn,
+                       bool& aDocumentIsTopLevel,
+                       nsSize& aAdjSize);
+  nsIView* GetParentViewForRoot();
+  bool DoSetPixelScale();
+  void UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale);
+  nsresult ReconstructAndReflow(bool aDoSetPixelScale);
+  nsresult UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO,
+                                               bool aDocumentIsTopLevel);
+  nsresult InitPrintDocConstruction(bool aHandleError);
+  void FirePrintPreviewUpdateEvent();
 private:
   nsPrintEngine& operator=(const nsPrintEngine& aOther) MOZ_DELETE;
 };
 
 #endif /* nsPrintEngine_h___ */
--- a/media/omx-plugin/OmxPlugin.cpp
+++ b/media/omx-plugin/OmxPlugin.cpp
@@ -7,26 +7,30 @@
 #include <stagefright/MediaExtractor.h>
 #include <stagefright/MetaData.h>
 #include <stagefright/OMXCodec.h>
 #ifdef MOZ_WIDGET_GONK
 #include <OMX.h>
 #else
 #include <stagefright/OMXClient.h>
 #endif
+
+#include "mozilla/Assertions.h"
 #include "mozilla/Types.h"
 #include "MPAPI.h"
 
 #include "android/log.h"
 
 #undef LOG
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "OmxPlugin" , ## args)
 
 using namespace MPAPI;
 
+const int OMX_QCOM_COLOR_FormatYVU420PackedSemiPlanar32m4ka = 0x7FA30C01;
+
 namespace android {
 
 // MediaStreamSource is a DataSource that reads from a MPAPI media stream.
 
 class MediaStreamSource : public DataSource {
   PluginHost *mPluginHost;
 public:
   MediaStreamSource(PluginHost *aPluginHost, Decoder *aDecoder);
@@ -112,36 +116,39 @@ class OmxDecoder {
   sp<MediaSource> mVideoSource;
   sp<MediaSource> mAudioTrack;
   sp<MediaSource> mAudioSource;
   int32_t mVideoWidth;
   int32_t mVideoHeight;
   int32_t mVideoColorFormat;
   int32_t mVideoStride;
   int32_t mVideoSliceHeight;
+  int32_t mVideoCropLeft;
+  int32_t mVideoCropTop;
   int32_t mVideoRotation;
   int32_t mAudioChannels;
   int32_t mAudioSampleRate;
   int64_t mDurationUs;
   MediaBuffer *mVideoBuffer;
   VideoFrame mVideoFrame;
   MediaBuffer *mAudioBuffer;
   AudioFrame mAudioFrame;
 
   // 'true' if a read from the audio stream was done while reading the metadata
   bool mAudioMetadataRead;
 
   void ReleaseVideoBuffer();
   void ReleaseAudioBuffer();
 
-  void PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
-  void CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
-  void SemiPlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
-  void SemiPlanarYVU420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
-  void SemiPlanarYVU420Packed32m4ka(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void ToVideoFrame_YUV420Planar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void ToVideoFrame_CbYCrY(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void ToVideoFrame_YUV420SemiPlanar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void ToVideoFrame_YVU420SemiPlanar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void ToVideoFrame_YUV420PackedSemiPlanar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void ToVideoFrame_YVU420PackedSemiPlanar32m4ka(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
   bool ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
   bool ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize,
                     int32_t aAudioChannels, int32_t aAudioSampleRate);
 public:
   OmxDecoder(PluginHost *aPluginHost, Decoder *aDecoder);
   ~OmxDecoder();
 
   bool Init();
@@ -177,16 +184,18 @@ public:
 OmxDecoder::OmxDecoder(PluginHost *aPluginHost, Decoder *aDecoder) :
   mPluginHost(aPluginHost),
   mDecoder(aDecoder),
   mVideoWidth(0),
   mVideoHeight(0),
   mVideoColorFormat(0),
   mVideoStride(0),
   mVideoSliceHeight(0),
+  mVideoCropLeft(0),
+  mVideoCropTop(0),
   mVideoRotation(0),
   mAudioChannels(-1),
   mAudioSampleRate(-1),
   mDurationUs(-1),
   mVideoBuffer(NULL),
   mAudioBuffer(NULL),
   mAudioMetadataRead(false)
 {
@@ -276,20 +285,16 @@ bool OmxDecoder::Init() {
   ssize_t audioTrackIndex = -1;
   ssize_t videoTrackIndex = -1;
   const char *audioMime = NULL;
   const char *videoMime = NULL;
 
   for (size_t i = 0; i < extractor->countTracks(); ++i) {
     sp<MetaData> meta = extractor->getTrackMetaData(i);
 
-    int32_t bitRate;
-    if (!meta->findInt32(kKeyBitRate, &bitRate))
-      bitRate = 0;
-
     const char *mime;
     if (!meta->findCString(kKeyMIMEType, &mime)) {
       continue;
     }
 
     if (videoTrackIndex == -1 && !strncasecmp(mime, "video/", 6)) {
       videoTrackIndex = i;
       videoMime = mime;
@@ -337,16 +342,18 @@ bool OmxDecoder::Init() {
     status_t status = videoSource->start();
     if (status != OK) {
       LOG("videoSource->start() failed with status %#x", status);
       return false;
     }
 
     int64_t durationUs;
     if (videoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+      if (durationUs < 0)
+        LOG("video duration %lld should be nonnegative", durationUs);
       if (durationUs > totalDurationUs)
         totalDurationUs = durationUs;
     }
   }
 
   sp<MediaSource> audioTrack;
   sp<MediaSource> audioSource;
   if (audioTrackIndex != -1 && (audioTrack = extractor->getTrack(audioTrackIndex)) != NULL)
@@ -368,16 +375,18 @@ bool OmxDecoder::Init() {
     status_t status = audioSource->start();
     if (status != OK) {
       LOG("audioSource->start() failed with status %#x", status);
       return false;
     }
 
     int64_t durationUs;
     if (audioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+      if (durationUs < 0)
+        LOG("audio duration %lld should be nonnegative", durationUs);
       if (durationUs > totalDurationUs)
         totalDurationUs = durationUs;
     }
   }
 
   // set decoder state
   mVideoTrack = videoTrack;
   mVideoSource = videoSource;
@@ -393,65 +402,125 @@ bool OmxDecoder::Init() {
   if (mAudioSource.get()) {
     if (mAudioSource->read(&mAudioBuffer) != INFO_FORMAT_CHANGED) {
       sp<MetaData> meta = mAudioSource->getFormat();
       if (!meta->findInt32(kKeyChannelCount, &mAudioChannels) ||
           !meta->findInt32(kKeySampleRate, &mAudioSampleRate)) {
         return false;
       }
       mAudioMetadataRead = true;
+
+      if (mAudioChannels < 0) {
+        LOG("audio channel count %d must be nonnegative", mAudioChannels);
+        return false;
+      }
+
+      if (mAudioSampleRate < 0) {
+        LOG("audio sample rate %d must be nonnegative", mAudioSampleRate);
+        return false;
+      }
     }
     else if (!SetAudioFormat()) {
         return false;
     }
   }
   return true;
 }
 
 bool OmxDecoder::SetVideoFormat() {
+  sp<MetaData> format = mVideoSource->getFormat();
+
+  // Stagefright's kKeyWidth and kKeyHeight are what MPAPI calls stride and
+  // slice height. Stagefright only seems to use its kKeyStride and
+  // kKeySliceHeight to initialize camera video formats.
+
+#ifdef DEBUG
+  int32_t unexpected;
+  if (format->findInt32(kKeyStride, &unexpected))
+    LOG("Expected kKeyWidth, but found kKeyStride %d", unexpected);
+  if (format->findInt32(kKeySliceHeight, &unexpected))
+    LOG("Expected kKeyHeight, but found kKeySliceHeight %d", unexpected);
+#endif // DEBUG
+
   const char *componentName;
 
-  if (!mVideoSource->getFormat()->findInt32(kKeyWidth, &mVideoWidth) ||
-      !mVideoSource->getFormat()->findInt32(kKeyHeight, &mVideoHeight) ||
-      !mVideoSource->getFormat()->findCString(kKeyDecoderComponent, &componentName) ||
-      !mVideoSource->getFormat()->findInt32(kKeyColorFormat, &mVideoColorFormat) ) {
+  if (!format->findInt32(kKeyWidth, &mVideoStride) ||
+      !format->findInt32(kKeyHeight, &mVideoSliceHeight) ||
+      !format->findCString(kKeyDecoderComponent, &componentName) ||
+      !format->findInt32(kKeyColorFormat, &mVideoColorFormat) ) {
+    return false;
+  }
+
+  if (mVideoStride <= 0) {
+    LOG("stride %d must be positive", mVideoStride);
     return false;
   }
 
-  if (!mVideoSource->getFormat()->findInt32(kKeyStride, &mVideoStride)) {
-    mVideoStride = mVideoWidth;
-    LOG("stride not available, assuming width");
+  if (mVideoSliceHeight <= 0) {
+    LOG("slice height %d must be positive", mVideoSliceHeight);
+    return false;
   }
 
-  if (!mVideoSource->getFormat()->findInt32(kKeySliceHeight, &mVideoSliceHeight)) {
-    mVideoSliceHeight = mVideoHeight;
-    LOG("slice height not available, assuming height");
+  int32_t cropRight, cropBottom;
+  if (!format->findRect(kKeyCropRect, &mVideoCropLeft, &mVideoCropTop,
+                                      &cropRight, &cropBottom)) {
+    mVideoCropLeft = 0;
+    mVideoCropTop = 0;
+    cropRight = mVideoStride - 1;
+    cropBottom = mVideoSliceHeight - 1;
+    LOG("crop rect not available, assuming no cropping");
   }
 
-  if (!mVideoSource->getFormat()->findInt32(kKeyRotation, &mVideoRotation)) {
+  if (mVideoCropLeft < 0 || mVideoCropLeft >= cropRight || cropRight >= mVideoStride ||
+      mVideoCropTop < 0 || mVideoCropTop >= cropBottom || cropBottom >= mVideoSliceHeight) {
+    LOG("invalid crop rect %d,%d-%d,%d", mVideoCropLeft, mVideoCropTop, cropRight, cropBottom);
+    return false;
+  }
+
+  mVideoWidth = cropRight - mVideoCropLeft + 1;
+  mVideoHeight = cropBottom - mVideoCropTop + 1;
+  MOZ_ASSERT(mVideoWidth > 0 && mVideoWidth <= mVideoStride);
+  MOZ_ASSERT(mVideoHeight > 0 && mVideoHeight <= mVideoSliceHeight);
+
+  if (!format->findInt32(kKeyRotation, &mVideoRotation)) {
     mVideoRotation = 0;
     LOG("rotation not available, assuming 0");
   }
 
-  LOG("width: %d height: %d component: %s format: %#x stride: %d sliceHeight: %d rotation: %d",
+  if (mVideoRotation != 0 && mVideoRotation != 90 &&
+      mVideoRotation != 180 && mVideoRotation != 270) {
+    LOG("invalid rotation %d, assuming 0", mVideoRotation);
+  }
+
+  LOG("width: %d height: %d component: %s format: %#x stride: %d sliceHeight: %d rotation: %d crop: %d,%d-%d,%d",
       mVideoWidth, mVideoHeight, componentName, mVideoColorFormat,
-      mVideoStride, mVideoSliceHeight, mVideoRotation);
+      mVideoStride, mVideoSliceHeight, mVideoRotation,
+      mVideoCropLeft, mVideoCropTop, cropRight, cropBottom);
 
   return true;
 }
 
 bool OmxDecoder::SetAudioFormat() {
   // If the format changed, update our cached info.
   if (!mAudioSource->getFormat()->findInt32(kKeyChannelCount, &mAudioChannels) ||
       !mAudioSource->getFormat()->findInt32(kKeySampleRate, &mAudioSampleRate)) {
     return false;
   }
 
-  LOG("channelCount: %d sampleRate: %d",
-      mAudioChannels, mAudioSampleRate);
+  LOG("channelCount: %d sampleRate: %d", mAudioChannels, mAudioSampleRate);
+
+  if (mAudioChannels < 0) {
+    LOG("audio channel count %d must be nonnegative", mAudioChannels);
+    return false;
+  }
+
+  if (mAudioSampleRate < 0) {
+    LOG("audio sample rate %d must be nonnegative", mAudioSampleRate);
+    return false;
+  }
 
   return true;
 }
 
 void OmxDecoder::ReleaseVideoBuffer() {
   if (mVideoBuffer) {
     mVideoBuffer->release();
     mVideoBuffer = NULL;
@@ -460,100 +529,113 @@ void OmxDecoder::ReleaseVideoBuffer() {
 
 void OmxDecoder::ReleaseAudioBuffer() {
   if (mAudioBuffer) {
     mAudioBuffer->release();
     mAudioBuffer = NULL;
   }
 }
 
-void OmxDecoder::PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void OmxDecoder::ToVideoFrame_YUV420Planar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   void *y = aData;
   void *u = static_cast<uint8_t *>(y) + mVideoStride * mVideoSliceHeight;
   void *v = static_cast<uint8_t *>(u) + mVideoStride/2 * mVideoSliceHeight/2;
-
   aFrame->Set(aTimeUs, aKeyFrame,
               aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
               y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
               u, mVideoStride/2, mVideoWidth/2, mVideoHeight/2, 0, 0,
               v, mVideoStride/2, mVideoWidth/2, mVideoHeight/2, 0, 0);
 }
 
-void OmxDecoder::CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void OmxDecoder::ToVideoFrame_CbYCrY(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   aFrame->Set(aTimeUs, aKeyFrame,
               aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
               aData, mVideoStride, mVideoWidth, mVideoHeight, 1, 1,
               aData, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 3,
               aData, mVideoStride, mVideoWidth/2, mVideoHeight/2, 2, 3);
 }
 
-void OmxDecoder::SemiPlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void OmxDecoder::ToVideoFrame_YUV420SemiPlanar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   void *y = aData;
   void *uv = static_cast<uint8_t *>(y) + (mVideoStride * mVideoSliceHeight);
-
   aFrame->Set(aTimeUs, aKeyFrame,
               aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
               y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
               uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 1,
               uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 1, 1);
 }
 
-void OmxDecoder::SemiPlanarYVU420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
-  SemiPlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+void OmxDecoder::ToVideoFrame_YVU420SemiPlanar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+  ToVideoFrame_YUV420SemiPlanar(aFrame, aTimeUs, aData, aSize, aKeyFrame);
   aFrame->Cb.mOffset = 1;
   aFrame->Cr.mOffset = 0;
 }
 
-void OmxDecoder::SemiPlanarYVU420Packed32m4ka(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+void OmxDecoder::ToVideoFrame_YUV420PackedSemiPlanar(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+  void *y = aData;
+  void *uv = static_cast<uint8_t *>(y) + mVideoStride * (mVideoSliceHeight - mVideoCropTop/2);
+  aFrame->Set(aTimeUs, aKeyFrame,
+              aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
+              y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
+              uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 1,
+              uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 1, 1);
+}
+
+void OmxDecoder::ToVideoFrame_YVU420PackedSemiPlanar32m4ka(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   size_t roundedSliceHeight = (mVideoSliceHeight + 31) & ~31;
   size_t roundedStride = (mVideoStride + 31) & ~31;
   void *y = aData;
   void *uv = static_cast<uint8_t *>(y) + (roundedStride * roundedSliceHeight);
   aFrame->Set(aTimeUs, aKeyFrame,
               aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
               y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
               uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 1, 1,
               uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 1);
 }
 
 bool OmxDecoder::ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
   const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
   const int OMX_QCOM_COLOR_FormatYVU420PackedSemiPlanar32m4ka = 0x7FA30C01;
 
   switch (mVideoColorFormat) {
-  case OMX_COLOR_FormatYUV420Planar:
-    PlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+  case OMX_COLOR_FormatYUV420Planar: // e.g. Asus Transformer, Stagefright's software decoder
+    ToVideoFrame_YUV420Planar(aFrame, aTimeUs, aData, aSize, aKeyFrame);
     break;
-  case OMX_COLOR_FormatCbYCrY:
-    CbYCrYFrame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+  case OMX_COLOR_FormatCbYCrY: // e.g. Droid 1
+    ToVideoFrame_CbYCrY(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+    break;
+  case OMX_COLOR_FormatYUV420SemiPlanar: // e.g. Galaxy S III
+    ToVideoFrame_YUV420SemiPlanar(aFrame, aTimeUs, aData, aSize, aKeyFrame);
     break;
-  case OMX_COLOR_FormatYUV420SemiPlanar:
-    SemiPlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+  case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: // e.g. Nexus One
+    ToVideoFrame_YVU420SemiPlanar(aFrame, aTimeUs, aData, aSize, aKeyFrame);
     break;
-  case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
-    SemiPlanarYVU420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+  case OMX_QCOM_COLOR_FormatYVU420PackedSemiPlanar32m4ka: // e.g. Otoro
+    ToVideoFrame_YVU420PackedSemiPlanar32m4ka(aFrame, aTimeUs, aData, aSize, aKeyFrame);
     break;
-  case OMX_QCOM_COLOR_FormatYVU420PackedSemiPlanar32m4ka:
-    SemiPlanarYVU420Packed32m4ka(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+  case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: // e.g. Galaxy Nexus
+    ToVideoFrame_YUV420PackedSemiPlanar(aFrame, aTimeUs, aData, aSize, aKeyFrame);
     break;
   default:
     LOG("Unknown video color format: %#x", mVideoColorFormat);
     return false;
   }
   return true;
 }
 
 bool OmxDecoder::ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize, int32_t aAudioChannels, int32_t aAudioSampleRate)
 {
   aFrame->Set(aTimeUs, reinterpret_cast<char *>(aData) + aDataOffset, aSize, aAudioChannels, aAudioSampleRate);
   return true;
 }
 
 bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aSeekTimeUs)
 {
+  MOZ_ASSERT(aSeekTimeUs >= -1);
+
   if (!mVideoSource.get())
     return false;
 
   ReleaseVideoBuffer();
 
   status_t err;
 
   if (aSeekTimeUs != -1) {
@@ -561,32 +643,32 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
     options.setSeekTo(aSeekTimeUs);
     err = mVideoSource->read(&mVideoBuffer, &options);
   } else {
     err = mVideoSource->read(&mVideoBuffer);
   }
 
   if (err == OK && mVideoBuffer->range_length() > 0) {
     int64_t timeUs;
-    int32_t unreadable;
     int32_t keyFrame;
 
     if (!mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs) ) {
-      LOG("no key time");
+      LOG("no frame time");
+      return false;
+    }
+
+    if (timeUs < 0) {
+      LOG("frame time %lld must be nonnegative", timeUs);
       return false;
     }
 
     if (!mVideoBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
        keyFrame = 0;
     }
 
-    if (!mVideoBuffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable)) {
-      unreadable = 0;
-    }
-
     char *data = reinterpret_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
     size_t length = mVideoBuffer->range_length();
 
     if (!ToVideoFrame(aFrame, timeUs, data, length, keyFrame)) {
       return false;
     }
   }
   else if (err == INFO_FORMAT_CHANGED) {
@@ -604,16 +686,18 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
     LOG("mVideoSource ERROR %#x", err);
   }
 
   return err == OK;
 }
 
 bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
 {
+  MOZ_ASSERT(aSeekTimeUs >= -1);
+
   status_t err;
   if (mAudioMetadataRead && aSeekTimeUs == -1) {
     // Use the data read into the buffer during metadata time
     err = OK;
   }
   else {
     ReleaseAudioBuffer();
     if (aSeekTimeUs != -1) {
@@ -625,18 +709,25 @@ bool OmxDecoder::ReadAudio(AudioFrame *a
     }
   }
   mAudioMetadataRead = false;
 
   aSeekTimeUs = -1;
 
   if (err == OK && mAudioBuffer->range_length() != 0) {
     int64_t timeUs;
-    if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs))
+    if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+      LOG("no frame time");
       return false;
+    }
+
+    if (timeUs < 0) {
+      LOG("frame time %lld must be nonnegative", timeUs);
+      return false;
+    }
 
     return ToAudioFrame(aFrame, timeUs,
                         mAudioBuffer->data(),
                         mAudioBuffer->range_offset(),
                         mAudioBuffer->range_length(),
                         mAudioChannels, mAudioSampleRate);
   }
   else if (err == INFO_FORMAT_CHANGED) {
--- a/media/omx-plugin/lib/ics/libstagefright/libstagefright.cpp
+++ b/media/omx-plugin/lib/ics/libstagefright/libstagefright.cpp
@@ -72,17 +72,24 @@ MetaData::findPointer(uint32_t key, void
   return false;
 }
 
 MOZ_EXPORT_API(bool)
 MetaData::findCString(uint32_t key, const char **value)
 {
   return false;
 }
- 
+
+MOZ_EXPORT_API(bool)
+MetaData::findRect(unsigned int key, int *cropLeft, int *cropTop,
+                   int *cropRight, int *cropBottom)
+{
+  abort();
+}
+
 MOZ_EXPORT_API(MediaSource::ReadOptions)::ReadOptions()
 {
 }
 
 MOZ_EXPORT_API(void)
 MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode)
 {
 }
--- a/mfbt/Likely.h
+++ b/mfbt/Likely.h
@@ -7,16 +7,16 @@
  * MOZ_LIKELY and MOZ_UNLIKELY macros to hint to the compiler how a
  * boolean predicate should be branch-predicted.
  */
 
 #ifndef mozilla_Likely_h_
 #define mozilla_Likely_h_
 
 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
-#  define MOZ_LIKELY(x)   (__builtin_expect(!!(x), 1))
-#  define MOZ_UNLIKELY(x) (__builtin_expect(!!(x), 0))
+#  define MOZ_LIKELY(x)   (__builtin_expect((x), 1))
+#  define MOZ_UNLIKELY(x) (__builtin_expect((x), 0))
 #else
-#  define MOZ_LIKELY(x)   (!!(x))
-#  define MOZ_UNLIKELY(x) (!!(x))
+#  define MOZ_LIKELY(x)   (x)
+#  define MOZ_UNLIKELY(x) (x)
 #endif
 
 #endif /* mozilla_Likely_h_ */
--- a/mobile/android/base/GeckoMenuInflater.java
+++ b/mobile/android/base/GeckoMenuInflater.java
@@ -36,17 +36,17 @@ public class GeckoMenuInflater extends M
         public int id;
         public int order;
         public CharSequence title;
         public int iconRes;
         public boolean checkable;
         public boolean checked;
         public boolean visible;
         public boolean enabled;
-        public boolean showAsAction;
+        public int showAsAction;
     }
 
     public GeckoMenuInflater(Context context) {
         super(context);
         mContext = context;
 
         isSubMenu = false;
     }
@@ -121,31 +121,30 @@ public class GeckoMenuInflater extends M
             if (parser != null)
                 parser.close();
         }
     }
 
     public void parseItem(ParsedItem item, AttributeSet attrs) {
         TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.MenuItem);
 
-        item.id = a.getResourceId(R.styleable.MenuItem_id, NO_ID);
-        item.order = a.getInt(R.styleable.MenuItem_orderInCategory, 0);
-        item.title = a.getText(R.styleable.MenuItem_title);
-        item.iconRes = a.getResourceId(R.styleable.MenuItem_icon, 0);
-        item.checkable = a.getBoolean(R.styleable.MenuItem_checkable, false);
-        item.checked = a.getBoolean(R.styleable.MenuItem_checked, false);
-        item.visible = a.getBoolean(R.styleable.MenuItem_visible, true);
-        item.enabled = a.getBoolean(R.styleable.MenuItem_enabled, true);
-        item.showAsAction = a.getBoolean(R.styleable.MenuItem_showAsAction, false);
+        item.id = a.getResourceId(R.styleable.MenuItem_android_id, NO_ID);
+        item.order = a.getInt(R.styleable.MenuItem_android_orderInCategory, 0);
+        item.title = a.getText(R.styleable.MenuItem_android_title);
+        item.iconRes = a.getResourceId(R.styleable.MenuItem_android_icon, 0);
+        item.checkable = a.getBoolean(R.styleable.MenuItem_android_checkable, false);
+        item.checked = a.getBoolean(R.styleable.MenuItem_android_checked, false);
+        item.visible = a.getBoolean(R.styleable.MenuItem_android_visible, true);
+        item.enabled = a.getBoolean(R.styleable.MenuItem_android_enabled, true);
+        item.showAsAction = a.getInt(R.styleable.MenuItem_android_showAsAction, 0);
 
         a.recycle();
     }
         
     public void setValues(ParsedItem item, MenuItem menuItem) {
         menuItem.setChecked(item.checked)
                 .setVisible(item.visible)
                 .setEnabled(item.enabled)
                 .setCheckable(item.checkable)
-                .setCheckable(item.checked)
                 .setIcon(item.iconRes)
-                .setShowAsAction(item.showAsAction ? 1 : 0);
+                .setShowAsAction(item.showAsAction);
     }
 }
--- a/mobile/android/base/GeckoMenuItem.java
+++ b/mobile/android/base/GeckoMenuItem.java
@@ -271,31 +271,31 @@ public class GeckoMenuItem implements Me
         return this;
     }
 
     @Override
     public void setShowAsAction(int actionEnum) {
         if (mShowAsActionChangedListener == null)
             return;
 
-        if (mActionItem == (actionEnum == 1))
+        if (mActionItem == (actionEnum > 0))
             return;
 
-        if (actionEnum == 1) {
+        if (actionEnum > 0) {
             if (!mShowAsActionChangedListener.hasActionItemBar())
                 return;
 
             // Change the type to just an icon
             mLayout = new MenuItemActionBar(mContext, null);
         } else {
             // Change the type to default
             mLayout = new MenuItemDefault(mContext, null);
         }
 
-        mActionItem = (actionEnum == 1);         
+        mActionItem = (actionEnum > 0);         
 
         mLayout.setId(mId);
         mLayout.setOnClickListener(this);
 
         setTitle(mTitle);        
         setVisible(mVisible);
         setEnabled(mEnabled);
         setCheckable(mCheckable);
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -209,18 +209,16 @@ FENNEC_PP_XML_FILES = \
   res/layout/gecko_app.xml \
   res/layout/text_selection_handles.xml \
   res/layout-xlarge-land-v11/abouthome_content.xml \
   res/layout-xlarge-v11/awesomebar_search.xml \
   res/layout-xlarge-v11/gecko_app.xml \
   res/xml/preferences.xml \
   res/menu/browser_app_menu.xml \
   res/menu-v11/browser_app_menu.xml \
-  res/menu-v11/gecko_app_menu.xml \
-  res/menu-v11/titlebar_contextmenu.xml \
   res/menu-large-v11/browser_app_menu.xml \
   res/menu-xlarge-v11/browser_app_menu.xml \
   $(NULL)
 
 
 ifneq (,$(findstring -march=armv7,$(OS_CFLAGS)))
 MIN_CPU_VERSION=7
 DEFINES += -DARMV7_ONLY=1
@@ -649,16 +647,17 @@ RES_DRAWABLE_MDPI_V11 = \
   res/drawable-mdpi-v11/ic_menu_reload.png \
   res/drawable-mdpi-v11/ic_menu_save_as_pdf.png \
   res/drawable-mdpi-v11/ic_menu_share.png \
   res/drawable-mdpi-v11/menu.png \
   res/drawable-mdpi-v11/menu_panel_bg.9.png \
   res/drawable-mdpi-v11/menu_popup_bg.9.png \
   res/drawable-mdpi-v11/menu_popup_arrow.png \
   res/drawable-mdpi-v11/menu_item_check.png \
+  res/drawable-mdpi-v11/menu_item_uncheck.png \
   $(NULL)
 
 RES_DRAWABLE_HDPI_V11 = \
   res/drawable-hdpi-v11/alert_addon.png \
   res/drawable-hdpi-v11/alert_app.png \
   res/drawable-hdpi-v11/alert_download.png \
   res/drawable-hdpi-v11/ic_menu_back.png \
   res/drawable-hdpi-v11/ic_menu_bookmark_add.png \
@@ -669,16 +668,17 @@ RES_DRAWABLE_HDPI_V11 = \
   res/drawable-hdpi-v11/ic_menu_reload.png \
   res/drawable-hdpi-v11/ic_menu_save_as_pdf.png \
   res/drawable-hdpi-v11/ic_menu_share.png \
   res/drawable-hdpi-v11/menu.png \
   res/drawable-hdpi-v11/menu_panel_bg.9.png \
   res/drawable-hdpi-v11/menu_popup_bg.9.png \
   res/drawable-hdpi-v11/menu_popup_arrow.png \
   res/drawable-hdpi-v11/menu_item_check.png \
+  res/drawable-hdpi-v11/menu_item_uncheck.png \
   $(NULL)
 
 RES_DRAWABLE_XHDPI_V11 = \
   res/drawable-xhdpi-v11/alert_addon.png \
   res/drawable-xhdpi-v11/alert_app.png \
   res/drawable-xhdpi-v11/alert_download.png \
   res/drawable-xhdpi-v11/ic_menu_back.png \
   res/drawable-xhdpi-v11/ic_menu_bookmark_add.png \
@@ -689,16 +689,17 @@ RES_DRAWABLE_XHDPI_V11 = \
   res/drawable-xhdpi-v11/ic_menu_reload.png \
   res/drawable-xhdpi-v11/ic_menu_save_as_pdf.png \
   res/drawable-xhdpi-v11/ic_menu_share.png \
   res/drawable-xhdpi-v11/menu.png \
   res/drawable-xhdpi-v11/menu_panel_bg.9.png \
   res/drawable-xhdpi-v11/menu_popup_bg.9.png \
   res/drawable-xhdpi-v11/menu_popup_arrow.png \
   res/drawable-xhdpi-v11/menu_item_check.png \
+  res/drawable-xhdpi-v11/menu_item_uncheck.png \
   $(NULL)
 
 RES_DRAWABLE_LAND_V14 = \
   res/drawable-land-v14/address_bar_bg.xml \
   $(NULL)
 
 RES_DRAWABLE_LAND_MDPI_V14 = \
   res/drawable-land-mdpi-v14/ic_awesomebar_go.png \
@@ -878,16 +879,17 @@ MOZ_ANDROID_DRAWABLES += \
   mobile/android/base/resources/drawable/address_bar_bg_shadow_repeat.xml       \
   mobile/android/base/resources/drawable/autocomplete_list_bg.9.png             \
   mobile/android/base/resources/drawable/awesomebar_tab_indicator.xml           \
   mobile/android/base/resources/drawable/awesomebar_tab_selected.xml            \
   mobile/android/base/resources/drawable/awesomebar_tab_unselected.xml          \
   mobile/android/base/resources/drawable/desktop_notification.png               \
   mobile/android/base/resources/drawable/highlight.xml                          \
   mobile/android/base/resources/drawable/menu_button.xml                        \
+  mobile/android/base/resources/drawable/menu_item_checkmark.xml                \
   mobile/android/base/resources/drawable/menu_level.xml                         \
   mobile/android/base/resources/drawable/progress_spinner.xml                   \
   mobile/android/base/resources/drawable/progress_spinner_1.png                 \
   mobile/android/base/resources/drawable/progress_spinner_2.png                 \
   mobile/android/base/resources/drawable/progress_spinner_3.png                 \
   mobile/android/base/resources/drawable/progress_spinner_4.png                 \
   mobile/android/base/resources/drawable/progress_spinner_5.png                 \
   mobile/android/base/resources/drawable/progress_spinner_6.png                 \
@@ -971,35 +973,35 @@ include $(topsrcdir)/config/android-comm
 classes.dex: jars/gecko-browser.jar
 	@echo "DX classes.dex"
 	$(DX) --dex --output=classes.dex jars
 
 jars/gecko-browser.jar: jars/gecko-mozglue.jar jars/gecko-util.jar jars/sync-thirdparty.jar $(addprefix $(srcdir)/,$(FENNEC_JAVA_FILES)) $(FENNEC_PP_JAVA_FILES) $(addprefix $(srcdir)/,$(SYNC_JAVA_FILES)) $(SYNC_PP_JAVA_FILES) R.java
 	@echo "JAR gecko-browser.jar"
 	$(NSINSTALL) -D classes/gecko-browser
 	$(JAVAC) $(JAVAC_FLAGS) -Xlint:all,-deprecation,-fallthrough -d classes/gecko-browser -classpath "jars/gecko-mozglue.jar:jars/gecko-util.jar:jars/sync-thirdparty.jar" $(addprefix $(srcdir)/,$(FENNEC_JAVA_FILES)) $(FENNEC_PP_JAVA_FILES) $(addprefix $(srcdir)/,$(SYNC_JAVA_FILES)) $(SYNC_PP_JAVA_FILES) R.java
-	jar cMf jars/gecko-browser.jar -C classes/gecko-browser .
+	$(JAR) cMf jars/gecko-browser.jar -C classes/gecko-browser .
 
 jars/gecko-mozglue.jar: $(addprefix $(srcdir)/,$(MOZGLUE_JAVA_FILES)) jars
 	@echo "JAR gecko-mozglue.jar"
 	$(NSINSTALL) -D classes/gecko-mozglue
 	$(JAVAC) $(JAVAC_FLAGS) -Xlint:all -d classes/gecko-mozglue $(addprefix $(srcdir)/,$(MOZGLUE_JAVA_FILES))
-	jar cMf jars/gecko-mozglue.jar -C classes/gecko-mozglue .
+	$(JAR) cMf jars/gecko-mozglue.jar -C classes/gecko-mozglue .
 
 jars/gecko-util.jar: $(addprefix $(srcdir)/,$(UTIL_JAVA_FILES)) jars
 	@echo "JAR gecko-util.jar"
 	$(NSINSTALL) -D classes/gecko-util
 	$(JAVAC) $(JAVAC_FLAGS) -Xlint:all,-deprecation -d classes/gecko-util $(addprefix $(srcdir)/,$(UTIL_JAVA_FILES))
-	jar cMf jars/gecko-util.jar -C classes/gecko-util .
+	$(JAR) cMf jars/gecko-util.jar -C classes/gecko-util .
 
 jars/sync-thirdparty.jar: $(addprefix $(srcdir)/,$(SYNC_THIRDPARTY_JAVA_FILES)) jars
 	@echo "JAR sync-thirdparty.jar"
 	$(NSINSTALL) -D classes/sync-thirdparty
 	$(JAVAC) $(JAVAC_FLAGS) -d classes/sync-thirdparty $(addprefix $(srcdir)/,$(SYNC_THIRDPARTY_JAVA_FILES))
-	jar cMf jars/sync-thirdparty.jar -C classes/sync-thirdparty .
+	$(JAR) cMf jars/sync-thirdparty.jar -C classes/sync-thirdparty .
 
 jars:
 	@echo "MKDIR jars"
 	$(NSINSTALL) -D jars
 
 PP_RES_XML= \
   $(SYNC_PP_RES_XML) \
   $(FENNEC_PP_XML_FILES) \
--- a/mobile/android/base/MemoryMonitor.java
+++ b/mobile/android/base/MemoryMonitor.java
@@ -28,16 +28,17 @@ import android.util.Log;
   *
   * Synchronization note: MemoryMonitor contains an inner class PressureDecrementer. Both
   * of these classes may be accessed from various threads, and have both been designed to
   * be thread-safe. In terms of lock ordering, code holding the PressureDecrementer lock
   * is allowed to pick up the MemoryMonitor lock, but not vice-versa.
   */
 class MemoryMonitor extends BroadcastReceiver {
     private static final String LOGTAG = "GeckoMemoryMonitor";
+    private static final String ACTION_MEMORY_DUMP = "org.mozilla.gecko.MEMORY_DUMP";
 
     private static final int MEMORY_PRESSURE_NONE = 0;
     private static final int MEMORY_PRESSURE_CLEANUP = 1;
     private static final int MEMORY_PRESSURE_LOW = 2;
     private static final int MEMORY_PRESSURE_MEDIUM = 3;
     private static final int MEMORY_PRESSURE_HIGH = 4;
 
     private static MemoryMonitor sInstance = new MemoryMonitor();
@@ -55,16 +56,17 @@ class MemoryMonitor extends BroadcastRec
         mMemoryPressure = MEMORY_PRESSURE_NONE;
         mStoragePressure = false;
     }
 
     public void init(Context context) {
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
+        filter.addAction(ACTION_MEMORY_DUMP);
         context.getApplicationContext().registerReceiver(this, filter);
     }
 
     public void onLowMemory() {
         Log.d(LOGTAG, "onLowMemory() notification received");
         increaseMemoryPressure(MEMORY_PRESSURE_HIGH);
     }
 
@@ -102,16 +104,22 @@ class MemoryMonitor extends BroadcastRec
         if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction())) {
             Log.d(LOGTAG, "Device storage is low");
             mStoragePressure = true;
             // TODO: drop or shrink disk caches
             // TODO: drop stuff from browser.db
         } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction())) {
             Log.d(LOGTAG, "Device storage is ok");
             mStoragePressure = false;
+        } else if (ACTION_MEMORY_DUMP.equals(intent.getAction())) {
+            String label = intent.getStringExtra("label");
+            if (label == null) {
+                label = "default";
+            }
+            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Memory:Dump", label));
         }
     }
 
     private void increaseMemoryPressure(int level) {
         int oldLevel;
         synchronized (this) {
             // bump up our level if we're not already higher
             if (mMemoryPressure > level) {
--- a/mobile/android/base/MenuItemDefault.java
+++ b/mobile/android/base/MenuItemDefault.java
@@ -4,40 +4,47 @@
 
 package org.mozilla.gecko;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
+import android.widget.AbsListView;
+import android.widget.CheckBox;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.AbsListView;
 import android.widget.TextView;
 
 public class MenuItemDefault extends LinearLayout
                              implements GeckoMenuItem.Layout {
     private static final String LOGTAG = "GeckoMenuItemDefault";
 
     private ImageView mIcon;
     private TextView mTitle;
-    private ImageView mCheck;
+    private CheckBox mCheck;
+
+    private boolean mCheckable;
+    private boolean mChecked;
 
     public MenuItemDefault(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         Resources res = context.getResources();
         setLayoutParams(new AbsListView.LayoutParams((int) (res.getDimension(R.dimen.menu_item_row_width)),
                                                      (int) (res.getDimension(R.dimen.menu_item_row_height))));
 
         inflate(context, R.layout.menu_item, this);
         mIcon = (ImageView) findViewById(R.id.icon);
         mTitle = (TextView) findViewById(R.id.title);
-        mCheck = (ImageView) findViewById(R.id.check);
+        mCheck = (CheckBox) findViewById(R.id.check);
+
+        mCheckable = false;
+        mChecked = false;
     }
 
     @Override
     public View getLayout() {
         return this;
     }
 
     @Override
@@ -70,16 +77,18 @@ public class MenuItemDefault extends Lin
         super.setEnabled(enabled);
         mTitle.setEnabled(enabled);
         mCheck.setEnabled(enabled);
         mIcon.setColorFilter(enabled ? 0 : 0xFF999999);
     }
 
     @Override
     public void setCheckable(boolean checkable) {
-        mCheck.setVisibility(checkable ? VISIBLE : GONE);
+        mCheckable = checkable;
+        mCheck.setVisibility(mCheckable ? VISIBLE : GONE);
     }
 
     @Override
     public void setChecked(boolean checked) {
-        mCheck.setVisibility(checked ? VISIBLE : GONE);
+        mChecked = checked;
+        mCheck.setChecked(mChecked);
     }
 }
index 5fa52a90f090b454d46d0daad6dfc61bd95280b4..958251d6b48ff5844854e22f41528f90209df545
GIT binary patch
literal 3149
zc$}S9X;f2L5)O;VCJ>NSmKan(fh<6PG>Cx&MMywEje^FIL<kU)PJ&^Ti0mM^Ae#s(
zib|`9wjhg=MWGP|byQ?e8X>fetjfMj=#ic|GkyBU-1FYMx9WahRo%K(=e%?u-0ls^
z2Fd^cV1vgVw6AoAuD*&2((ggpxm4+-&&J@{e)QvP4v|R#pvd$f3dn;-45s)}h~(%W
zTPRKdfLsXGAJ4{Py^th2&6>E1v5ulK0IS2vC5k~Lg;Cg`AWASb!WleP-v|a#$<E+|
zc33Eu;YJCe?ulVi{9<taq?j<0BN^<n6XX<ylp3H>*hEkiEj)sSjB*D5VHYV~uc{$n
z&>s+Xm^1iaLE*7JAU8Ub0<yEVu_8fXFc1P^4YRdFAYhgtI1~nlK&21D3TBJ6Lm=Vy
zpzi}L^~NM0NBW}Ozx$F(&fpL>n}LKtI2?{O$Htn@42HlQ9UWI~z~NR>gcU0~f=!IF
zieQ<pSwK@*Bqo)?rqUxot1>Z&9?5nFgV&BgV_>m=8jfInPn0xekSHPp0<(rfXf((g
zn#J~|9RGVX%Ribyf%sBb^hhR2dLPG4|HIYaQ&)k~Xpr7as`OHb;b=N3l17POd!U`c
z(j99um5hX<9Hd#aw}slnp$G>U%mM0P<L2t_hDO`K-CgaVYc~Fh>u%!!w{^6KV{Fi_
zFc=2rXpeG4JHYLsj!+B~WrJDcdPK0;#0U~)jZ6JE7xuSYq#Kh$WYd}cbb9z&1^9%}
z*>qM2odI(5Lx9Y&L=rV(RbjDuLEmGgFsUafWOpW=2KpnzNa|li0EPYU$sN&la7TnI
z8jiMe1Apg||DUWuq`^S`t6bJp(i&V{{#pD|;m`J=L`ZvvDQ%9zZNlvUfMTo%8s#6=
zHBuPsqupWD+!$M{t6>tN8Of_i>k7FK<EB@8Wn85mj`Ui$1r5x-UWg+k93uHq&8{NS
zkB49KA_W<FzSDdCF^!4h2ghf<;o1(EP9$Hs4IY!7;m6Ywg2zT*)y8rl`SQc$rpt3x
z`GcdQlGwJH#kMg+`F$JtYA6jTK6TdK95O(th{XC|jxS9nv`F|mAmP;gIC(8zD*H^j
zp1+J?gQmj!U`DWUPubKVTeSzYDEwUwe_1C3nbDD%L4K0@h0}Id(!s^xMDY2`2fy%Z
z9*2o1IaxjN86TJR<>d876cy;7cv*Bqfn4Q&;?a6-Eq9D~D5reD|Hqy8-u4GpFj~d>
z!^W=@J3_y09xL88QUw15pM5u$W&FHts~!IQlyP}#k6cSj%aZ%i%Y?G^^jvX#)u3(D
zBGU{W6R7t9&I(<uBfP{eT$vO!PJJl7cf9=tPT=BMBHTJZd{%h-Yf>Kf^U3g&^c_ks
z4w2opRb^GR+&^+ITGsj3Em<}#-qCZZas<{g-#nX*oKvC_%lF7Rsl_pVzKRGI&Ut@)
z@|#W7LYXcDWhH=e``#qyWL78a8DBV2;%3Q*_=-9t*u5$b?G0YfTfBbHy<uUh<#_-X
zo7LMW@v|&x-1p!DVY^zMdoUFb-q?P6>Q)!xT!tj`C*Z=O+Do(9wEpXUtrFZ`8waH7
z@N!~T^@WmM1p5t`X|}{vpaOKA9xAcvD1x0EeZupOYdY$rdZzQ-%8_>#>v9|JtvAt9
z?8l9-Y-X`{vFk-ZBL==+yya$x9baH<=q!IE6h~6Ld)w|+7<OinbJ2@<UbwzJ+*Fv_
zI_?6BI+e=#ht`)*j7^U510KaOwT8N#Lcd?%T(P#u+FZU1bu&VY8J~vTdT>U4XF|R1
zNo{_kv3%d&ak@!!i(tujnm;BX28d;Q4&-YpSamDT*LGjWok9ZnHAsv<LEP_@qNTjJ
z={NH{aqo5+R4k8o2o;aO8)~GaEF9YNn+)Z_zGv>E$W*<=(q<9iWr4%oBg%QnIx25k
zqoMiB`jvcBhvj)xTwBQ#*rxh~<;U`4zVFe?&x?I46_*bv`gt#T(*-|I)l7VuKd_~#
zH>Yb;rHC6EZr-0CGax*ibwr$OpA3LRIAjg{t}ce(2xxc7BeqX=J{DpFt@lH|cFDzU
zgHdRFH;Uw(#nQR!A8InvmBNU1cy5`&Oo2Hkr=>T;jGAJ1w=L_^VkoZIx&f1NGiI2n
zhb0BDsvwemwr^Q6WEtFkh<vt8|FE{~QoD%L5hM0g_6^S0DZc>)<{Q9BA7Y#^`Khh2
z#LKUAq1m4cOf=(W={5u9!~BO{LXpxU0p1YXtgKYh*<`K4xRv41uLm8zj&o6=gg2?K
zJ1P16tg|zxxh-(^V?ol}M6w6^71pU>{^0fP;}=Ue4;5M!w1x{sE4f-TNyZKDm456+
z8J2x$3{t)zYP~g097h<*JedK|Q`e1wPTe`%W<7G)j?`wux)ywG3W>M$GRX6(8zOo<
zn+PlTI#4q)T=i3$$I1`BuE`0HG<Q>9AKe<&F+Er`9<!XEmz#2QNJdx~v!#k~VkKsz
z_zrr4sC0cG!~V{hE#NM*#KR{Im2lgl20SxQ3vId=e{{)ih*a$WXE8Jz4#}11Y5*#$
zeR%Si%*=(uR%zY_Ib!O-7>;F2NUC2lK*z3+-2Q%tPE6_DmL1nX9-64aXZN?oe$IX5
zd0G%_-fU8y{&`+Q%P?Tdr%jYU8b3_cKME8nD^%8Sr;Q-a$<+&~*G7A+*v<h-lTA2>
z;X%gRGPL><<3xf5IGXHAC5FBzDlYU>VQu?ez?tDq?Om7sTDCk}6q~`^ca_(%Vh{IB
z;UvlScNgL7h`r$4e%<8y{iRn6L-kmfw4D)FK>2zo$_sz#8&6B2mF5za->lOATy%S|
z-#NYR7UQc=>p}Bs;<)iX*$w(fJ-N5~fKki!!%-ZiX<u(!qj^Ism)=uMEU?#p^ZN;_
zM{fZV@u8C7amYc@>+%baH}fTe;)~{3-}4gvhT-^xU&fz&<L+*$|9Wkj77fiY${rHt
z$Ad>sf&&ps2GfYT5G5|eT*!ZQ)5m)-^>WGnrw%|)txQ<(_%-vi_){I)yMFRIr^_=&
zy2u!fRq{?1gxH$YCh9!!i{1fo{aW9zzRX$h+5Z)0kb>d82){6wRyn9Gqo!{he`-eS
z$^-_(^~6!K%}me%9y=?V&Y)Z0><BqhwP8pnvr%zf-%v8AvM=++-Cza_z2(l>;ICX&
zdcJthBZL0<tjMmJJ3Hv$bKI#EFfADKMs?ql_&A>2SmYhJyL*ymZVE(f6Nsmk&xyV;
z8u1wwGwr|X@B^wp9c!!@jGcX6tD5tamx@$al)s;!05PULpF5vc?iU$yGx1f=yA7Le
z>`}<Z{SbI(kP`>ybF`eM7LCqK@>)7K2APQE<X>*zt24L$HriZPk9#qXV@1B1@iC;w
zF<$OV^c}N0;#Q#bhe`RB=i__Ww8M#T{l1DflTVEhHze9AKI$aM6n8f%r_U@qMu2&q
zAMF9uiHno_rCV((X<ynk!5D(ic^gD-f7lWt<{AZ3M-FsM69$JP!57@33rjEJUtZ48
zsUYn%a8|8p`%re8?^hANz*5+o7ws9e<DjtvTh#b~d+Z0+L;vp6iJ{3l<$aZlZjSB*
zn&AEh{SZ*t#JBoO4}*4jSavtf^c58qovb?hX}2byz%*sV%_0J*;&{(sdjH+3_I4o&
zWcf@z9M~mysU{aGiwJsOJy$ordF8a*RzVq2Mc3??+lPf}dU14}iUaA2b?KR+&MSmt
z3r-5I^J6aof^QZo@qX%ZPsPp7GBff$S`2UA%FJvjKn|dhd;(No{e`>wgYSXCq3^jK
GOZ+Fv9c{e;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..19f04294bedb7e7c7211b3b77ac4d183b0839e22
GIT binary patch
literal 1083
zc$}S6PiWIn7|)yx8Qa053geMo6m9Ze+NMpmy0uNa71mkW!g}yvmb|WEOI}Rg)^y-O
z4?4k<2p&8riU&O?vXcsK2OS79@Tf-*o(AGchM>O8W{Mj-_(<~J_vQEdzVCg1u2-ff
z2K$fqa~wBVn$)Unhv9pqk9}tjZC_*CF<NNQ8fntD?qM!#l35H&wmyfeST{Qt-{Mh@
z>up)}25pq5RD;-p9%6*RcDZnkjs>o6%wq~>@toyk_%AQlcwm_sekNIlWjBvo*5tB>
zYs=GhV|m_COn&Sv7!6crz{XSufxY1PYLMY~?5gY>szn~`K<Ipi{~c7LTmgCFVUQH!
zF#{q5WLZFoq%5N|K!QjTA$#N)N~lR$l~SO)c;?MBn`%`nc6~7^!?!4PRZ(oW+d?}o
z5N}RIilT%zBq_!aF~8$bJ%~B}aAZNlzTsIewTJ^kS)V0~G{f`J6>PU$-Zkv_-9)jJ
ziGl8lNPwbkixJwVRopxn?bkal7OU7Ni=M&i(H#EE)xp#d$f8ltc@`^*zMv6f(Z&uf
zX&IjV5lqWeVK&XOm`cEu1m!eBX_$`ZbH%)-#ie2{2_qZ(af|U(E`hXSA+F^RDj+45
zRkXB}f(k6aY`hS0OO8)<$G{QS`ok?8$W`+m)+zDoge*iIP-ziL{1$ORz9xf{W!<ox
zP;n|OP&ZcWSxeX~dc+1h8CI=*B7kV`%@r*vDRNGev}B&|a?StAn#h6?|7n*<#d<J2
z?lwOYcE<-hY-T(*9KDrIi4B%j(z5m7<JN~~gX>`6@c4>!^V{9^5yig6KRo*B6@Byd
zK3aXevH5)Ca}R?z?tC9vSvlXi_wL5(iQxA8OWQ+;+q1@NKb9Umx_ou&=j%|M=pE|m
X<JOx4r@`9O7onz9nAV=;E?oHq2P#jt
index ef5ce22ed0aa3bece5580813031ad315c9f37e0b..48d2e1e322a2a88222e18f5345c7f0272bdd1faa
GIT binary patch
literal 1938
zc$}S8X;c$e6pm$a0~7%lP#6+%CCg+bBS9b&G}s^w0aKttNCq-OGBFt?EQ+92u~HXM
zL~%bTYC%M?K@=5_p`u5nqKKlPazrUAifAo}omj9vt;ZjIXJ+2J_kG{J_uY5zne5Pz
zIrbx5N03M)d+}UYO3dRe?=V~9+nOx+otP%zA~_z0#pB5eJwgglVQ~l`)+iDXDWXuN
zEWU*Jl1Nr+R3^velCL2prlBb;7@AR|BUy&;Y@<%0Ohj-X4oN_@0`iNhvt$5O3CIgL
z5{5)4MAYcqR6P=w8X{AsCMx+V@@zlA*9Z{?GzhK$jG82^0Wu26AMHZK+M=eDfsYV8
zQ9%AHD7hpQ5Mp`+;Luo9B?ANjE|&(fIb1I24KNuXlg=O>E)`@$94^G<0Rw|fc+;!m
zAt@X*;ERw1WHpZKAUZucIhmHsqG9?3I>_hqEjE};DuJLHQna|jNYxrBgBD=Kpwy!}
z9L2PNMOMUNOK<_1Ja`0+P9phaSZf$a6p=EzQK6%QGzMLxp%0=BxD<*1GTI<Z(IIpx
zV!)Q@mBf9-Q~u%V%Tx=Hhz6RkM~O>OB*B<+i3ZW)Vpu>Xc4#V81u+7Ah%EBh3?7rg
z^#MU2h7U^^7$k&Y7BeW2!x*&jIc^Y(7sv)hED;M11VItV=LPU#A105%XNVX9EYToW
ztTo^Ytr8jJqJMLlU*tkUJ)*!dy$r*W1}h*`jp3L<jp+bk7#El(Q7BQZMKRrSK?AWO
zdUPqG3esa5;A4g%^fM7K!2h0{4|AA&ZXnErIYROPSM`6gMkj)y|EpXERYVP1mY<5B
z5I(gJq9uApPc+A(c`_HG=gx`Y0GaX5i7kn0=LOESA6QidrtRv0O~ur8w{L~=MkVl$
z)JGiK_r{SkO5%*zH<UNj4i!Znb2%?vH8$X`biYU69*z1N^hjb-TyK$Igt9qj%H-Wy
zGN<k_Ic~X~omZQ86*PmnO>7rWtBmK*uQa!OXf|A{q_ld`-b{jBtv4@IMZ1o3S~#Zk
za)AC-{po|k@X}TNF&RV3z0Z#Bi%8iy{MUAI^z;qA8_Qp%8LRt7KX55{Qk1sX&x=;A
zZsQtfpuW?etvL%C>JHXamxsU7ewcr#H-D1Iop-CnX=j94ZF@hr92f?GnbEMTh_Q9d
zi?y=CruHbg2`{YzYB}vY&v;J!DY&ouVwy3QcYXhrM>~+`IsEPX{42j)6EPm`nC+Qy
z((}ma(5032jx~jFcLPPV@om2YeZq;S-6Dqrt#;ckY;KX!#x+_?A@t$9Dq~MqOjl>*
z?uyFWJA%60*7_xxw~RfpEIRwnxwvNT%sTXkhD%%G9$!Cs=uy8q(A=00W+WU-Q)ct1
zBkwuBhI>aZUvaX+#q_%0x9?N}A4>5;LuSmPc%?4q%ORcPjhWc_x9djMJ&0q|wrlbV
z@d}&VQQ?%ds7+P)8M@%E1HF4shkSx-O7>w&X=|*@0mt;0d*^SpcAxX;n4rD%eR|yn
z^RDG42kT9h6|E(kr7@{LPO5HN(}6Ya%^Ytv8IgO)?L!)C-iAMI@K=<!nN4=Z!47v{
z&TGpOu6ptTNb5284d)wWv+bV8tk_QRG6}nT+@G}D9==IReRt0^^bl*^_XW8SD=&?+
zamtz1C6`-XAAb1N<INMVO5RCn5Vo)V>2XEZss83`nO!q#UT=y!UBBL0fU(Wik9XKy
zoaHp`zF=MJ&Invo^}_0zr}h1@uliCt(oe+9%L;4jadl!lc$C$Y*skA@-SMpW^6s2@
zHnpRZI{X)0yRmRuNuy(;{R1)PJv_v)&y{s`&ty}R|H_fEX8UEzyyG68r#tPV7lviV
zvI?$$yK-t?Q`h^w_M8W)ZRs{*-39;Kew{&u?PV`&sl`!$K#Oj<&nYW%`z~ixeWWqH
z%=u6xc}nz#!lC)rJhw!hjj=jw{LvXD<r6)Fw@C4<V2VS@xtx~bt8T_3yKQcDtIu6o
zzIuY~uH5o>{uRDAGG?}0nS$@R6>uFF-LkVPY(>WZ%+5Q%hccAnDnC1QYti9}59I~f
z34N9Ey~S#Z=>2Y6XAyNZgf$$U)a%hT*Vg^Fm64Ewnqd>gkGcVMcs=RiZ_Qr|R-2n!
bV}{t0Zg!W2gBovd%U@C~3V}-lW3&DQxqt*O
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f7f033cf5d7cdb9c4cfd97f404fe3f15467c217b
GIT binary patch
literal 1047
zc$}S6J#5oJ6m}GWpj9UZ3KDQ~5dw+WXFG9XtEMFWp^->i(nw^iV_y<0wa?gB;&!Uo
zIuup}%#5&rKw>~$kSYOUVt|E#ofQeBaxQU%pz6TM_T78_zW3g}pRJ{ZYf}@aCm4pA
zs?Qrux=*L?v7_|+WvG3p+bLqU$ujPep&cQn>f#Opb>HrxCbHf2Tf1nMVe);i)h6x6
zb=AQ>XQvo0@k1tEvvWykI|D>O2lc!_W52z6%>vKW*qfyWY=k=Md-EF+THaV_IU55<
zaoM>mU^Y>y0Ur??B>rj;tBJ<$+g0f~Rr4&^hme8B{tl|$SOPkZ5GZj{!GVGRWSJ9+
zC0Q0O0}%=$59uQpgrZuKRj~|4i>2Nox2rY{YvhYc8rvr%RC#_l9CAa6!%>eH6h%pG
zh+=^v3h{bC?4%IHGnoYg#ZKgf#KQqdWxIpdh{m$n75uQ#7#j}aQKD$d_{0u*frGs7
z^BFoOP1HRc9k<p)#5Yll*CL13qdW75tHY@&kVc~}MjkDSy=q`*%|`*L8yZXhaIWX7
zuv(#6EEi!}gmOg?DzGByHA^=PNwjJunAtdpYe{8ADO%8!jG7>rf>N$3Mnx<`1)8ub
znHjep#KaC9lySW=*R&4hs(OTMf}<A3t62vu^)bP5ABR9+mchk_?RY_|xRe%X6f26n
z+sL&d?1TLbtKI<-K;hq;D@I9F<eDKGC7m5{-T%oNPlMtAYL`q!doVqYo1Y5f@j(Hd
znTQU@)5YWW>0p_4quNS7b$;&c&E*TZ6Z!3(4=*;4yrJF|eXH7g|47&w<ldf*-ksb2
wdSlWmOg~?F_VU8x*7=k0?#JDHkh{8>V;(-3{IPrQ%;$7e>*j*-q_%SB7ut43VE_OC
index 464c4522f2f41966653f24f10f809365d88c3db7..3653e72cfebb342b593427ef299e52cd7d2e6576
GIT binary patch
literal 2572
zc$}S9X;f2L5{`gE2M|y|7#Cthz=h-`F)Kz0Sy&_(2m^?S3CRP3WFZM_YqJX|;DSRV
zL<JNY5K&Q-UFm>|q8$`B7L`^MkWGngE20w|apuhQ@yFcr-n+NzeqUAHx>e`AOqQpM
zA@pxh2n1s2=1TL{%+|B7-U7{c0Fs}tnJndWe>qzmB9GxpK?sE}4hCUvLT)JN4RZN$
zksaVh2t+$f;Nvg%XL^u$Vj+S%i$TN+C6L*%(J@xS<?RIJuwXD$AR@yj8ZX0P0zMh;
zhh+jx2^9<zxW-FCcD$z#FMcPF$cH;_f^Cc?X$%NKITscyj1b94v1IrcyClteR*i(i
zzCh$V$?$&#<<DfnsA4Gy!y+*DJOG7);cy7l1}qMTS`R}5C^Qn#JUDyQ1`-xWLgQgy
z2VCP#$`2uV(->cUX(Tc{OfHv@kjR*r7(@&PA(n<BQA8qf)&?4FuR++$;zV+8ti4FK
zYR&=;l<}kjiCiES!DeM{usBLihQsHMAe1nf-wcanUlXNC88VhDL81@<QYb{up=EM!
zFy#AanNOSqM0$fVag>y&xsQ-l|KaNU)LEb=8qyZ2KyxYF2%4A|B?LusHyRnP*+K9H
zd=fw*XtIdk0N~L8j(|cD00M^U%%IX}7&OBf3(VR0D=q_rciw=a<LMZhGYUmV5%Clv
zjey1jM1T%ZF!VXDn@A?-ig@50SMYBx?z>zPRSI(DVyTZ<95Gh`tT3@$EDIA$U{p2^
zX2<061fp5Rn%N8b8Y?IjM1y>WR4jyj$uLRq7ZCuc|2;X8hD8%`&NMU)OND>s^8cT#
zAvM7u|EpZ)RGJ!`U4AQmjqt5~K#`_rq?+bPj9%OXfh-`o(I`H#J)`+?5kB-~*DjxT
znb1mrF+>3khgD9SO-#ZkOnvMwsEm<1D@`)3UGGUOh&85#i6-SVC#Ni90~TFyDPkQN
zrlsX<pH`A_!8G8&sqyIj<F6I(NMeVk@x1%N$(gyI&=bwOF;hn-Cf*g|*>F9r$u&u5
zoF6lO-g`i|9`mbZT|j*HDe?pPdP<6mzlDK#Z9CQ!CaN~?rA{GRGg3~O)f(7pXS@i;
zavvD!E~;?winYLE3^DHubQkHypmWcZzN~bC<=`#su?gYxx|3;z_1ay#^Pax7Jie;n
zv2M+iT1B$A)rz#Mqgi9<j$vYGQ|q57eNM`UTfK%yUmuEgf4`?=af~G*$fEcRku@`K
zZ++~c?L)o|qjJB*HaFuua;nM^Zv47MoUvQ{Nj)N_tu`NXX-nF%A@_#t_)&tCCAr*(
zFFBTcH`(L^iB%524W4A9)W$n%Q--a=KgTD8yrp~~@P}hmV}uG%Vgn8*<nJi98o%fC
zEZl1_B#hm6-<U7NKNu_A=Y9skuKQhJ^(q}L@(BvI@xNd;KjWc)wdW=Vmtm+<r@tq0
zD$|t1$#)I!J?H8b%Ag0;{q8Ni9ncEXR`;gFj*2QT9m!;YGQ&THb~Nzd;zDzbs{`bg
z;gubJoG7Onc5Pk3IkQsPwP#h*VxKiyKG7+P$^e9G+>~F43ERf{k_A<kHS*khW~lpN
zYfqAUey*R_X0H3=Eaj!b8rHSo>*on?peA?9k^|2DG+FTja_j2k`9JN_q57Ivdb__x
zt>Gy@E>PZa<$g*$%{<aD+{<dR`(ckl9yoA+rR9wi#slRU&PNlceRVE3=zG;byPdc8
zr)(W6lcpkxuHNpx*R1z19dV>33mTlcI{tQ@M@ZdXVAe!wNowl_mJG1Fw8+)6>6p`Y
z#s0}nn>%WX9uGX~+W9(JnRZNFAJ**OFS{0L&~e+=%|(48*LFxt$*F%2>HICK4i~jg
zhkbE`9#|%<>K=u{kO<!J&12K{#0*N@;PcuNMO*4g6gBGAJDoHeVfh=!i~ctZI!dQ+
zm%RJf%x{YPyGO7B0W{rX3W3lw#hZ9bvnI+)6u$<R2-h!T?YjfE)Oa-4Yc)TZaSAcB
zx5_)PtfH&6Cu3CoQ)F~w`^?7|PqYp6CGS;n>i9u@bi<@_D79^XVsiFzM4BM-M-F;T
zr$dL`wtnc{&cq1C%|OM?jnLZ7!%fh(@gw#db3gF27iPchPAY~aZQ*Qvkr>-tWL|Ue
z^T_dp95t#cD|<^eROJR}LVG#lwMF}39Z<YHYfDty%z@wbzZ#7!@A2PL(9?Lfz$1j<
zVd#C;czXHz<Cf-DShP(whv~hmr+kHy)7;JpT;u_gt3&TVf{gd0XH2^@0L&W~kKGmq
zb<EtNr;(SB@9n*SYiU}X{%M0Uym&hy!Uh^;wpK>oiaPE0`$^YO>&^%Hg#p~k>SqgX
zl_{r=Q;D~1j69k<5^R=S58@W}wRiPbeN0ieo@o7X<8`Cb^DS+~y|>QB6^*lv`Zl>_
zU;Sg|3Fo}S>ij9Z%ISPX1|r_firG$oQ5Ist2wUFQdYU}Oc?xcGtI)fgBsE30Wv-Z4
zp5NGLSlK?1$Z6EQ)a(|Zrsao2b3a)cOxYB{V*-|D4cSl%s=CGLfIF<E?qLKib1Y4N
zl3nhYb7wcRb-R9qFO*I{=#g5lO1!E*4XDI-yP_=XoO<&?i*wC-%I*nch9%Ww<#kNt
z*{6#gYIiwW*_Kb!N}=PdQV-L6d>*iklaDnAUtuDT`7v@V5vHV6!7m3?=6#-?E7vW(
z5;$p|Q=#Yna*V>wHTz@pB^4oiZLV3$Awvv{{se`JI=t>&Urah+RMjniXDc!6m%8+I
zTI2K9(;of#R?_(%I$lr+Y+1HYnfJ3b7{Fh$u7!<=D>=<mP<}}~ESMM!%2_wI|B+qL
zPTHXD-7ZrHRzTEIMdiZwOy{8+i0&l^u25d5lWYr{!vzHwMxcs#1j3<z7bIrB>mY9m
zVdts6@b+q4i0|#uz2aP5#=^AmwekW-bCZeb@Ev!cLyWGExs=0+{b@sbVIH<d=`DSI
sGrY6viTrEj<&*jU_?+}f=9HihKr&S;2u0DTfZ6{uH@YXS+L@F5Pt{vA7XSbN
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0c13cae05868f2f497478f543a66394ae1d729c0
GIT binary patch
literal 1072
zc$}S6OK;Oa5OyD+s-g&Pg<iHU5>z67CQfW6gv3s0BvPUz5<x-;$KEuivDesJ;`TzR
zR3uKED#|}VRN@XCIKTzb1CI+rJj4+MEq?&Sy2J%R)dMTryEFd2nb~>Vs7#+489qEr
zQPfCjN~@CnNcaxzCEt(K>MGd|;X(t~Pz!f;4^lZ3H6bY3`V6c>-JHMt6s9R^pl#I~
zxKTc>7|3Sy5W@tvONA?)4P4!rg%~v9jOAqL&4-U@V3`^EY@*DST@|*isRa+#7N+aQ
z!mJ^iboK;D2MRG@L#%_q?l`^@Waurs3OR>rmIhl8Je#3^1=T25fQmc_5{wu#IGzWR
z#PIQiB=N_A!0`ghkw=R0aU~%sLK5^AO}u$#OQ~wbo-ZP0=r+c#!m{0Nm+6WO@@80G
zmgUffAjAkF=FdA=4`Pl#5n0fnZ+MoAE#!bu)|+S!XJ|UQg6)>e+lC##mnf1lHqc#`
zXE@fj*$D09Ds1hJ_UrR5WUJ6ebDlx!(VF<f)$Y^~NTN~Bcor#&-qDaTXF~^<v<yxD
zFs5ZHTrNejn2d8tfs;}^pW;%YnlGxFCJM!Tf{SeI#4U<RS&kRu1yRfMe1VsfIax~y
zNlxYpTuv-R+>+yC-7#RqwSIHOUAc<tK^-Hnj!-A+fJz%-<hPLv)S3j2m36~%Ld9fQ
zpkA!dv#vn1=ph?yWmvIxh=Ak&y}7I<1X;>!f|gL}9@qSztg$2*_OEt{RHO&P<972C
zVS9X_LuSS!!!hxo{e%qGg_4%52XDT-mWL^@PkS+%u5MgidOO*?^=8lcAB)Q?H^-On
z9vnX!TY20+^t^NF{p#(_^!mH68`r&aYtQsMeSQ6dLkGagMe6&v&!hJTvL7m+visMG
cX6)7AC^c5YYuEawUWPMVDoktl@)wtW0!s@}IsgCw
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/menu_item_checkmark.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_checked="true" android:drawable="@drawable/menu_item_check"/>
+
+    <item android:drawable="@drawable/menu_item_uncheck"/>
+
+</selector>
--- a/mobile/android/base/resources/layout/menu_item.xml
+++ b/mobile/android/base/resources/layout/menu_item.xml
@@ -17,21 +17,22 @@
                android:layout_height="wrap_content"
                android:layout_weight="1.0"
                android:textSize="16sp"
                android:textColor="@color/menu_item_title"
                android:singleLine="true"
                android:ellipsize="middle"
                android:layout_gravity="center_vertical"/>
 
-     <ImageView android:id="@+id/check"
-                android:layout_width="20dp"
-                android:layout_height="14dp"
-                android:paddingLeft="6dp"
-                android:layout_gravity="center_vertical"
-                android:src="@drawable/menu_item_check"
-                android:visibility="gone"/>
+     <CheckBox android:id="@+id/check"
+               android:layout_width="18dp"
+               android:layout_height="18dp"
+               android:layout_gravity="center_vertical"
+               android:button="@drawable/menu_item_checkmark"
+               android:focusable="false"
+               android:clickable="false"
+               android:visibility="gone"/>
 
      <View android:layout_width="14dp"
            android:layout_height="fill_parent"
            android:layout_gravity="center_vertical"/>
 
 </merge>
--- a/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml.in
@@ -1,68 +1,67 @@
-#filter substitution
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<menu xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@">
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item gecko:id="@+id/reload"
-          gecko:icon="@drawable/ic_menu_reload"
-          gecko:title="@string/reload"
-          gecko:showAsAction="true"/>
+    <item android:id="@+id/reload"
+          android:icon="@drawable/ic_menu_reload"
+          android:title="@string/reload"
+          android:showAsAction="always"/>
 
-    <item gecko:id="@+id/forward"
-          gecko:icon="@drawable/ic_menu_forward"
-          gecko:title="@string/forward"
-          gecko:visible="false"/>
+    <item android:id="@+id/forward"
+          android:icon="@drawable/ic_menu_forward"
+          android:title="@string/forward"
+          android:visible="false"/>
 
-    <item gecko:id="@+id/bookmark"
-          gecko:icon="@drawable/ic_menu_bookmark_add"
-          gecko:title="@string/bookmark"/>
+    <item android:id="@+id/bookmark"
+          android:icon="@drawable/ic_menu_bookmark_add"
+          android:title="@string/bookmark"/>
 
-    <item gecko:id="@+id/share"
-          gecko:icon="@drawable/ic_menu_share"
-          gecko:title="@string/share" /> 
+    <item android:id="@+id/share"
+          android:icon="@drawable/ic_menu_share"
+          android:title="@string/share" /> 
     
-    <item gecko:id="@+id/find_in_page"
-          gecko:icon="@drawable/ic_menu_find_in_page"
-          gecko:title="@string/find_in_page" />
+    <item android:id="@+id/find_in_page"
+          android:icon="@drawable/ic_menu_find_in_page"
+          android:title="@string/find_in_page" />
 
-    <item gecko:id="@+id/desktop_mode"
-          gecko:icon="@drawable/ic_menu_desktop_mode"
-          gecko:title="@string/desktop_mode"
-          gecko:checkable="true" />
+    <item android:id="@+id/desktop_mode"
+          android:icon="@drawable/ic_menu_desktop_mode"
+          android:title="@string/desktop_mode"
+          android:checkable="true" />
 
-    <item gecko:title="@string/tools">
+    <item android:title="@string/tools">
 
         <menu>
 
-            <item gecko:id="@+id/save_as_pdf"
-                  gecko:icon="@drawable/ic_menu_save_as_pdf"
-                  gecko:title="@string/save_as_pdf" />
+            <item android:id="@+id/save_as_pdf"
+                  android:icon="@drawable/ic_menu_save_as_pdf"
+                  android:title="@string/save_as_pdf" />
 
-            <item gecko:id="@+id/addons"
-                  gecko:title="@string/addons"/>
+            <item android:id="@+id/addons"
+                  android:title="@string/addons"/>
 
-            <item gecko:id="@+id/downloads"
-                  gecko:title="@string/downloads"/>
+            <item android:id="@+id/downloads"
+                  android:title="@string/downloads"/>
 
-            <item gecko:id="@+id/apps"
-                  gecko:title="@string/apps"/>
+            <item android:id="@+id/apps"
+                  android:title="@string/apps"/>
 
         </menu>
 
     </item>
 
-    <item gecko:id="@+id/char_encoding"
-          gecko:visible="false"
-          gecko:title="@string/char_encoding"/>
+    <item android:id="@+id/char_encoding"
+          android:visible="false"
+          android:title="@string/char_encoding"/>
 
-    <item gecko:id="@+id/settings"
-          gecko:title="@string/settings" />
+    <item android:id="@+id/settings"
+          android:title="@string/settings" />
 
 #ifdef MOZ_PROFILING
-    <item gecko:id="@+id/toggle_profiling"
-          gecko:title="@string/toggle_profiling" />
+    <item android:id="@+id/toggle_profiling"
+          android:title="@string/toggle_profiling" />
 #endif
 </menu>
--- a/mobile/android/base/resources/menu-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-v11/browser_app_menu.xml.in
@@ -1,69 +1,68 @@
-#filter substitution
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<menu xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@">
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item gecko:id="@+id/forward"
-          gecko:icon="@drawable/ic_menu_forward"
-          gecko:title="@string/forward"
-          gecko:showAsAction="true"/>
+    <item android:id="@+id/forward"
+          android:icon="@drawable/ic_menu_forward"
+          android:title="@string/forward"
+          android:showAsAction="always"/>
 
-    <item gecko:id="@+id/reload"
-          gecko:icon="@drawable/ic_menu_reload"
-          gecko:title="@string/reload"
-          gecko:showAsAction="true"/>
+    <item android:id="@+id/reload"
+          android:icon="@drawable/ic_menu_reload"
+          android:title="@string/reload"
+          android:showAsAction="always"/>
 
-    <item gecko:id="@+id/bookmark"
-          gecko:icon="@drawable/ic_menu_bookmark_add"
-          gecko:title="@string/bookmark"
-          gecko:showAsAction="true"/>
+    <item android:id="@+id/bookmark"
+          android:icon="@drawable/ic_menu_bookmark_add"
+          android:title="@string/bookmark"
+          android:showAsAction="always"/>
 
-    <item gecko:id="@+id/share"
-          gecko:icon="@drawable/ic_menu_share"
-          gecko:title="@string/share" /> 
+    <item android:id="@+id/share"
+          android:icon="@drawable/ic_menu_share"
+          android:title="@string/share" /> 
     
-    <item gecko:id="@+id/find_in_page"
-          gecko:icon="@drawable/ic_menu_find_in_page"
-          gecko:title="@string/find_in_page" />
+    <item android:id="@+id/find_in_page"
+          android:icon="@drawable/ic_menu_find_in_page"
+          android:title="@string/find_in_page" />
 
-    <item gecko:id="@+id/desktop_mode"
-          gecko:icon="@drawable/ic_menu_desktop_mode"
-          gecko:title="@string/desktop_mode"
-          gecko:checkable="true" />
+    <item android:id="@+id/desktop_mode"
+          android:icon="@drawable/ic_menu_desktop_mode"
+          android:title="@string/desktop_mode"
+          android:checkable="true" />
 
-    <item gecko:title="@string/tools">
+    <item android:title="@string/tools">
 
         <menu>
 
-            <item gecko:id="@+id/save_as_pdf"
-                  gecko:icon="@drawable/ic_menu_save_as_pdf"
-                  gecko:title="@string/save_as_pdf" />
+            <item android:id="@+id/save_as_pdf"
+                  android:icon="@drawable/ic_menu_save_as_pdf"
+                  android:title="@string/save_as_pdf" />
 
-            <item gecko:id="@+id/addons"
-                  gecko:title="@string/addons"/>
+            <item android:id="@+id/addons"
+                  android:title="@string/addons"/>
 
-            <item gecko:id="@+id/downloads"
-                  gecko:title="@string/downloads"/>
+            <item android:id="@+id/downloads"
+                  android:title="@string/downloads"/>
 
-            <item gecko:id="@+id/apps"
-                  gecko:title="@string/apps"/>
+            <item android:id="@+id/apps"
+                  android:title="@string/apps"/>
 
         </menu>
 
     </item>
 
-    <item gecko:id="@+id/char_encoding"
-          gecko:visible="false"
-          gecko:title="@string/char_encoding"/>
+    <item android:id="@+id/char_encoding"
+          android:visible="false"
+          android:title="@string/char_encoding"/>
 
-    <item gecko:id="@+id/settings"
-          gecko:title="@string/settings" />
+    <item android:id="@+id/settings"
+          android:title="@string/settings" />
 
 #ifdef MOZ_PROFILING
-    <item gecko:id="@+id/toggle_profiling"
-          gecko:title="@string/toggle_profiling" />
+    <item android:id="@+id/toggle_profiling"
+          android:title="@string/toggle_profiling" />
 #endif
 </menu>
deleted file mode 100644
--- a/mobile/android/base/resources/menu-v11/gecko_app_menu.xml.in
+++ /dev/null
@@ -1,11 +0,0 @@
-#filter substitution
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<menu xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@">
-    <item gecko:id="@+id/quit"
-          gecko:title="@string/quit"
-          gecko:orderInCategory="10" />
-</menu>
deleted file mode 100644
--- a/mobile/android/base/resources/menu-v11/titlebar_contextmenu.xml.in
+++ /dev/null
@@ -1,27 +0,0 @@
-#filter substitution
-<?xml version="1.0" encoding="utf-8"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<menu xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@">
-
-    <item gecko:id="@+id/pasteandgo"
-          gecko:title="@string/contextmenu_pasteandgo"/>
-
-    <item gecko:id="@+id/paste"
-          gecko:title="@string/contextmenu_paste"/>
-
-    <item gecko:id="@+id/share"
-          gecko:title="@string/contextmenu_share"/>
-
-    <item gecko:id="@+id/copyurl"
-          gecko:title="@string/contextmenu_copyurl"/>
-
-    <item gecko:id="@+id/site_settings"
-          gecko:title="@string/site_settings_title" />
-
-    <item gecko:id="@+id/add_to_launcher"
-          gecko:title="@string/contextmenu_add_to_launcher"/>
-
-</menu>
--- a/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml.in
@@ -1,69 +1,68 @@
-#filter substitution
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<menu xmlns:gecko="http://schemas.android.com/apk/res/@ANDROID_PACKAGE_NAME@">
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item gecko:id="@+id/reload"
-          gecko:icon="@drawable/ic_menu_reload"
-          gecko:title="@string/reload"
-          gecko:showAsAction="true"/>
+    <item android:id="@+id/reload"
+          android:icon="@drawable/ic_menu_reload"
+          android:title="@string/reload"
+          android:showAsAction="always"/>
 
-    <item gecko:id="@+id/forward"
-          gecko:icon="@drawable/ic_menu_forward"
-          gecko:title="@string/forward"
-          gecko:visible="false"/>
+    <item android:id="@+id/forward"
+          android:icon="@drawable/ic_menu_forward"
+          android:title="@string/forward"
+          android:visible="false"/>
 
-    <item gecko:id="@+id/bookmark"
-          gecko:icon="@drawable/ic_menu_bookmark_add"
-          gecko:title="@string/bookmark"
-          gecko:showAsAction="true"/>
+    <item android:id="@+id/bookmark"
+          android:icon="@drawable/ic_menu_bookmark_add"
+          android:title="@string/bookmark"
+          android:showAsAction="always"/>
 
-    <item gecko:id="@+id/share"
-          gecko:icon="@drawable/ic_menu_share"
-          gecko:title="@string/share" /> 
+    <item android:id="@+id/share"
+          android:icon="@drawable/ic_menu_share"
+          android:title="@string/share" /> 
     
-    <item gecko:id="@+id/find_in_page"
-          gecko:icon="@drawable/ic_menu_find_in_page"
-          gecko:title="@string/find_in_page" />
+    <item android:id="@+id/find_in_page"
+          android:icon="@drawable/ic_menu_find_in_page"
+          android:title="@string/find_in_page" />
 
-    <item gecko:id="@+id/desktop_mode"
-          gecko:icon="@drawable/ic_menu_desktop_mode"
-          gecko:title="@string/desktop_mode"
-          gecko:checkable="true" />
+    <item android:id="@+id/desktop_mode"
+          android:icon="@drawable/ic_menu_desktop_mode"
+          android:title="@string/desktop_mode"
+          android:checkable="true" />
 
-    <item gecko:title="@string/tools">
+    <item android:title="@string/tools">
 
         <menu>
 
-            <item gecko:id="@+id/save_as_pdf"
-                  gecko:icon="@drawable/ic_menu_save_as_pdf"
-                  gecko:title="@string/save_as_pdf" />
+            <item android:id="@+id/save_as_pdf"
+                  android:icon="@drawable/ic_menu_save_as_pdf"
+                  android:title="@string/save_as_pdf" />
 
-            <item gecko:id="@+id/addons"
-                  gecko:title="@string/addons"/>
+            <item android:id="@+id/addons"
+                  android:title="@string/addons"/>
 
-            <item gecko:id="@+id/downloads"
-                  gecko:title="@string/downloads"/>
+            <item android:id="@+id/downloads"
+                  android:title="@string/downloads"/>
 
-            <item gecko:id="@+id/apps"
-                  gecko:title="@string/apps"/>
+            <item android:id="@+id/apps"
+                  android:title="@string/apps"/>
 
         </menu>
 
     </item>
 
-    <item gecko:id="@+id/char_encoding"
-          gecko:visible="false"
-          gecko:title="@string/char_encoding"/>
+    <item android:id="@+id/char_encoding"
+          android:visible="false"
+          android:title="@string/char_encoding"/>
 
-    <item gecko:id="@+id/settings"
-          gecko:title="@string/settings" />
+    <item android:id="@+id/settings"
+          android:title="@string/settings" />
 
 #ifdef MOZ_PROFILING
-    <item gecko:id="@+id/toggle_profiling"
-          gecko:title="@string/toggle_profiling" />
+    <item android:id="@+id/toggle_profiling"
+          android:title="@string/toggle_profiling" />
 #endif
 </menu>
--- a/mobile/android/base/resources/values/attrs.xml
+++ b/mobile/android/base/resources/values/attrs.xml
@@ -7,25 +7,25 @@
 
     <declare-styleable name="AboutHomeSection">
         <attr name="title" format="string"/>
         <attr name="subtitle" format="string"/>
         <attr name="more_text" format="string"/>
     </declare-styleable>
 
     <declare-styleable name="MenuItem">
-        <attr name="id" format="string"/>
-        <attr name="orderInCategory" format="string"/>
-        <attr name="title"/>
-        <attr name="icon" format="string"/>
-        <attr name="checkable" format="boolean"/>
-        <attr name="checked" format="boolean"/>
-        <attr name="visible" format="string"/>
-        <attr name="enabled" format="string"/>
-        <attr name="showAsAction" format="boolean"/>
+        <attr name="android:id"/>
+        <attr name="android:orderInCategory"/>
+        <attr name="android:title"/>
+        <attr name="android:icon"/>
+        <attr name="android:checkable"/>
+        <attr name="android:checked"/>
+        <attr name="android:visible"/>
+        <attr name="android:enabled"/>
+        <attr name="android:showAsAction"/>
     </declare-styleable>
 
     <declare-styleable name="FlowLayout">
         <attr name="spacing" format="dimension"/>
     </declare-styleable>
 
     <declare-styleable name="MultiChoicePreference">
         <attr name="entries" format="string"/>
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -168,16 +168,17 @@ var BrowserApp = {
     Services.obs.addObserver(this, "ScrollTo:FocusedInput", false);
     Services.obs.addObserver(this, "Sanitize:ClearData", false);
     Services.obs.addObserver(this, "FullScreen:Exit", false);
     Services.obs.addObserver(this, "Viewport:Change", false);
     Services.obs.addObserver(this, "Viewport:Flush", false);
     Services.obs.addObserver(this, "Passwords:Init", false);
     Services.obs.addObserver(this, "FormHistory:Init", false);
     Services.obs.addObserver(this, "ToggleProfiling", false);
+    Services.obs.addObserver(this, "Memory:Dump", false);
 
     Services.obs.addObserver(this, "sessionstore-state-purge-complete", false);
 
     function showFullScreenWarning() {
       NativeWindow.toast.show(Strings.browser.GetStringFromName("alertFullScreenToast"), "short");
     }
 
     window.addEventListener("fullscreen", function() {
@@ -1115,29 +1116,107 @@ var BrowserApp = {
     } else if (aTopic == "ToggleProfiling") {
       let profiler = Cc["@mozilla.org/tools/profiler;1"].
                        getService(Ci.nsIProfiler);
       if (profiler.IsActive()) {
         profiler.StopProfiler();
       } else {
         profiler.StartProfiler(100000, 25, ["stackwalk"], 1);
       }
+    } else if (aTopic == "Memory:Dump") {
+      this.dumpMemoryStats(aData);
     }
   },
 
   get defaultBrowserWidth() {
     delete this.defaultBrowserWidth;
     let width = Services.prefs.getIntPref("browser.viewport.desktopWidth");
     return this.defaultBrowserWidth = width;
   },
 
   // nsIAndroidBrowserApp
   getBrowserTab: function(tabId) {
     return this.getTabForId(tabId);
-  }
+  },
+
+  dumpMemoryStats: function(aLabel) {
+    // TODO once bug 788021 has landed, replace this code and just invoke that instead
+    // currently this code is hijacked from areweslimyet.com, original code can be found at:
+    // https://github.com/Nephyrin/MozAreWeSlimYet/blob/master/mozmill_endurance_test/performance.js
+    var memMgr = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager);
+
+    var timestamp = new Date();
+    var memory = {};
+
+    // These *should* be identical to the explicit/resident root node
+    // sum, AND the explicit/resident node explicit value (on newer builds),
+    // but we record all three so we can make sure the data is consistent
+    memory['manager_explicit'] = memMgr.explicit;
+    memory['manager_resident'] = memMgr.resident;
+
+    var knownHeap = 0;
+
+    function addReport(path, amount, kind, units) {
+      if (units !== undefined && units != Ci.nsIMemoryReporter.UNITS_BYTES)
+        // Unhandled. (old builds don't specify units, but use only bytes)
+        return;
+
+      if (memory[path])
+        memory[path] += amount;
+      else
+        memory[path] = amount;
+      if (kind !== undefined && kind == Ci.nsIMemoryReporter.KIND_HEAP
+          && path.indexOf('explicit/') == 0)
+        knownHeap += amount;
+    }
+
+    // Normal reporters
+    var reporters = memMgr.enumerateReporters();
+    while (reporters.hasMoreElements()) {
+      var r = reporters.getNext();
+      r instanceof Ci.nsIMemoryReporter;
+      if (r.path.length) {
+        addReport(r.path, r.amount, r.kind, r.units);
+      }
+    }
+
+    // Multireporters
+    if (memMgr.enumerateMultiReporters) {
+      var multireporters = memMgr.enumerateMultiReporters();
+
+      while (multireporters.hasMoreElements()) {
+        var mr = multireporters.getNext();
+        mr instanceof Ci.nsIMemoryMultiReporter;
+        mr.collectReports(function (proc, path, kind, units, amount, description, closure) {
+          addReport(path, amount, kind, units);
+        }, null);
+      }
+    }
+
+    var heapAllocated = memory['heap-allocated'];
+    // Called heap-used in older builds
+    if (!heapAllocated) heapAllocated = memory['heap-used'];
+    // This is how about:memory calculates derived value heap-unclassified, which
+    // is necessary to get a proper explicit value.
+    if (knownHeap && heapAllocated)
+      memory['explicit/heap-unclassified'] = memory['heap-allocated'] - knownHeap;
+
+    // If the build doesn't have a resident/explicit reporter, but does have
+    // the memMgr.explicit/resident field, use that
+    if (!memory['resident'])
+      memory['resident'] = memory['manager_resident']
+    if (!memory['explicit'])
+      memory['explicit'] = memory['manager_explicit']
+
+    var label = "[AboutMemoryDump|" + aLabel + "] ";
+    dump(label + timestamp);
+    for (var type in memory) {
+      dump(label + type + " = " + memory[type]);
+    }
+  },
 };
 
 var NativeWindow = {
   init: function() {
     Services.obs.addObserver(this, "Menu:Clicked", false);
     Services.obs.addObserver(this, "Doorhanger:Reply", false);
     this.contextmenus.init();
   },
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -100,30 +100,32 @@
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
 @BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
 @BINPATH@/components/dom_battery.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
+@BINPATH@/components/dom_contacts.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_file.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_media.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_browserelement.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
+@BINPATH@/components/dom_settings.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_threads.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_views.xpt
 @BINPATH@/components/dom_xbl.xpt
@@ -233,16 +235,22 @@
 @BINPATH@/components/xul.xpt
 @BINPATH@/components/xuldoc.xpt
 @BINPATH@/components/xultmpl.xpt
 @BINPATH@/components/zipwriter.xpt
 
 ; JavaScript components
 @BINPATH@/components/ConsoleAPI.manifest
 @BINPATH@/components/ConsoleAPI.js
+@BINPATH@/components/ContactManager.js
+@BINPATH@/components/ContactManager.manifest
+@BINPATH@/components/SettingsManager.js
+@BINPATH@/components/SettingsManager.manifest
+@BINPATH@/components/SettingsService.js
+@BINPATH@/components/SettingsService.manifest
 @BINPATH@/components/BrowserElementParent.manifest
 @BINPATH@/components/BrowserElementParent.js
 @BINPATH@/components/FeedProcessor.manifest
 @BINPATH@/components/FeedProcessor.js
 @BINPATH@/components/BrowserFeeds.manifest
 @BINPATH@/components/FeedConverter.js
 @BINPATH@/components/FeedWriter.js
 @BINPATH@/components/fuelApplication.manifest
--- a/startupcache/StartupCacheUtils.cpp
+++ b/startupcache/StartupCacheUtils.cpp
@@ -99,31 +99,50 @@ NewBufferFromStorageStream(nsIStorageStr
   *buffer = temp.forget();
   return NS_OK;
 }
 
 static const char baseName[2][5] = { "gre/", "app/" };
 
 static inline bool
 canonicalizeBase(nsAutoCString &spec,
-                 nsACString &out,
-                 mozilla::Omnijar::Type aType)
+                 nsACString &out)
 {
-    nsAutoCString base;
-    nsresult rv = mozilla::Omnijar::GetURIString(aType, base);
+    nsAutoCString greBase, appBase;
+    nsresult rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::GRE, greBase);
+    if (NS_FAILED(rv) || !greBase.Length())
+        return false;
 
-    if (NS_FAILED(rv) || !base.Length())
+    rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, appBase);
+    if (NS_FAILED(rv))
         return false;
 
-    if (base.Compare(spec.get(), false, base.Length()))
+    bool underGre = !greBase.Compare(spec.get(), false, greBase.Length());
+    bool underApp = appBase.Length() &&
+                    !appBase.Compare(spec.get(), false, appBase.Length());
+
+    if (!underGre && !underApp)
         return false;
 
+    /**
+     * At this point, if both underGre and underApp are true, it can be one
+     * of the two following cases:
+     * - the GRE directory points to a subdirectory of the APP directory,
+     *   meaning spec points under GRE.
+     * - the APP directory points to a subdirectory of the GRE directory,
+     *   meaning spec points under APP.
+     * Checking the GRE and APP path length is enough to know in which case
+     * we are.
+     */
+    if (underGre && underApp && greBase.Length() < appBase.Length())
+        underGre = false;
+
     out.Append("/resource/");
-    out.Append(baseName[aType]);
-    out.Append(Substring(spec, base.Length()));
+    out.Append(baseName[underGre ? mozilla::Omnijar::GRE : mozilla::Omnijar::APP]);
+    out.Append(Substring(spec, underGre ? greBase.Length() : appBase.Length()));
     return true;
 }
 
 /**
  * PathifyURI transforms uris into useful zip paths
  * to make it easier to manipulate startup cache entries
  * using standard zip tools.
  * Transformations applied:
@@ -183,18 +202,17 @@ PathifyURI(nsIURI *in, nsACString &out)
             rv = chromeReg->ConvertChromeURL(in, getter_AddRefs(uri));
             NS_ENSURE_SUCCESS(rv, rv);
         }
 
         rv = uri->GetSpec(spec);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    if (!canonicalizeBase(spec, out, mozilla::Omnijar::GRE) &&
-        !canonicalizeBase(spec, out, mozilla::Omnijar::APP)) {
+    if (!canonicalizeBase(spec, out)) {
         if (NS_SUCCEEDED(uri->SchemeIs("file", &equals)) && equals) {
             nsCOMPtr<nsIFileURL> baseFileURL;
             baseFileURL = do_QueryInterface(uri, &rv);
             NS_ENSURE_SUCCESS(rv, rv);
 
             nsAutoCString path;
             rv = baseFileURL->GetPath(path);
             NS_ENSURE_SUCCESS(rv, rv);
--- a/storage/src/mozStorageService.cpp
+++ b/storage/src/mozStorageService.cpp
@@ -889,20 +889,20 @@ Service::SetQuotaForFilenamePattern(cons
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Service::UpdateQuotaInformationForFile(nsIFile *aFile)
 {
   NS_ENSURE_ARG_POINTER(aFile);
 
-  nsCString path;
-  nsresult rv = aFile->GetNativePath(path);
+  nsString path;
+  nsresult rv = aFile->GetPath(path);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  int rc = ::sqlite3_quota_file(PromiseFlatCString(path).get());
+  int rc = ::sqlite3_quota_file(NS_ConvertUTF16toUTF8(path).get());
   NS_ENSURE_TRUE(rc == SQLITE_OK, convertResultCode(rc));
 
   return NS_OK;
 }
 
 } // namespace storage
 } // namespace mozilla
--- a/testing/marionette/jar.mn
+++ b/testing/marionette/jar.mn
@@ -15,17 +15,17 @@ marionette.jar:
   content/ChromeUtils.js  (ChromeUtils.js)
 #ifdef ENABLE_TESTS
   content/test.xul  (client/marionette/chrome/test.xul)
   content/test2.xul  (client/marionette/chrome/test2.xul)
   content/test_nested_iframe.xul  (client/marionette/chrome/test_nested_iframe.xul)
 #endif
 
 % content specialpowers %content/
-  content/specialpowers.js (../mochitest/specialpowers/content/specialpowers.js)
-  content/SpecialPowersObserver.js (../mochitest/specialpowers/components/SpecialPowersObserver.js)
-  content/specialpowersAPI.js (../mochitest/tests/SimpleTest/specialpowersAPI.js)
-  content/SpecialPowersObserverAPI.js (../mochitest/tests/SimpleTest/SpecialPowersObserverAPI.js)
+  content/specialpowers.js (../specialpowers/content/specialpowers.js)
+  content/SpecialPowersObserver.js (../specialpowers/components/SpecialPowersObserver.js)
+  content/specialpowersAPI.js (../specialpowers/content/specialpowersAPI.js)
+  content/SpecialPowersObserverAPI.js (../specialpowers/content/SpecialPowersObserverAPI.js)
   content/ChromePowers.js (../mochitest/tests/SimpleTest/ChromePowers.js)
-  content/MozillaLogger.js (../mochitest/tests/SimpleTest/MozillaLogger.js)
+  content/MozillaLogger.js (../specialpowers/content/MozillaLogger.js)
 
-% resource mochikit %modules/
-  modules/MockFilePicker.jsm (../mochitest/MockFilePicker.jsm)
+% resource specialpowers %modules/
+  modules/MockFilePicker.jsm (../specialpowers/content/MockFilePicker.jsm)
--- a/testing/marionette/marionette-listener.js
+++ b/testing/marionette/marionette-listener.js
@@ -52,16 +52,18 @@ let asyncTestCommandId;
 let asyncTestTimeoutId;
 
 /**
  * Called when listener is first started up. 
  * The listener sends its unique window ID and its current URI to the actor.
  * If the actor returns an ID, we start the listeners. Otherwise, nothing happens.
  */
 function registerSelf() {
+  Services.io.manageOfflineStatus = false;
+  Services.io.offline = false;
   let register = sendSyncMessage("Marionette:register", {value: winUtil.outerWindowID, href: content.location.href});
   
   if (register[0]) {
     listenerId = register[0];
     startListeners();
   }
 }
 
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -13,17 +13,16 @@ include $(DEPTH)/config/autoconf.mk
 
 DIRS = \
   MochiKit \
   static \
   dynamic \
   tests \
   chrome \
   ssltunnel \
-  specialpowers \
   $(NULL)
 
 ifeq ($(MOZ_BUILD_APP),mobile/android)
 DIRS += roboextender
 endif
 
 NO_JS_MANIFEST = 1
 MOZ_CHROME_FILE_FORMAT = jar
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -146,21 +146,16 @@
  "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227",
  "dom/imptests/webapps/WebStorage/tests/submissions/Infraware/test_storage_local_key.html": "bug 775227",
  "dom/indexedDB/ipc/test_ipc.html": "bug 783513",
  "dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
  "dom/indexedDB/test/test_event_propagation.html": "TIMED_OUT, bug 780855",
  "dom/indexedDB/test/test_app_isolation_inproc.html": "TIMED_OUT",
  "dom/indexedDB/test/test_app_isolation_oop.html": "TIMED_OUT",
  "dom/network/tests/test_network_basics.html": "",
- "dom/settings/tests/test_settings_events.html": "",
- "dom/settings/tests/test_settings_basics.html": "",
- "dom/contacts/tests/test_contacts_blobs.html": "",
- "dom/contacts/tests/test_contacts_basics.html": "",
- "dom/contacts/tests/test_contacts_events.html": "",
  "dom/permission/tests/test_permission_basics.html": "",
  "dom/sms/tests/test_sms_basics.html": "",
  "dom/tests/mochitest/ajax/jquery/test_jQuery.html": "bug 775227",
  "dom/tests/mochitest/ajax/offline/test_simpleManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_updatingManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml": "TIMED_OUT",
  "dom/tests/mochitest/ajax/prototype/test_Prototype.html": "",
  "dom/tests/mochitest/ajax/scriptaculous/test_Scriptaculous.html": "",
--- a/testing/mochitest/jar.mn
+++ b/testing/mochitest/jar.mn
@@ -7,25 +7,23 @@ mochikit.jar:
   content/chrome-harness.js (chrome-harness.js)
   content/harness-overlay.xul (harness-overlay.xul)
   content/harness.xul (harness.xul)
   content/redirect.html (redirect.html)
   content/server.js (server.js)
   content/dynamic/getMyDirectory.sjs (dynamic/getMyDirectory.sjs)
   content/static/harness.css (static/harness.css)
   content/tests/SimpleTest/ChromePowers.js (tests/SimpleTest/ChromePowers.js)
-  content/tests/SimpleTest/specialpowersAPI.js (tests/SimpleTest/specialpowersAPI.js)
-  content/tests/SimpleTest/SpecialPowersObserverAPI.js (tests/SimpleTest/SpecialPowersObserverAPI.js)
   content/tests/SimpleTest/EventUtils.js (tests/SimpleTest/EventUtils.js)
   content/tests/SimpleTest/ChromeUtils.js (tests/SimpleTest/ChromeUtils.js)
-  content/tests/SimpleTest/MozillaLogger.js (tests/SimpleTest/MozillaLogger.js)
   content/tests/SimpleTest/LogController.js (tests/SimpleTest/LogController.js)
+  content/tests/SimpleTest/MozillaLogger.js (../specialpowers/content/MozillaLogger.js)
+  content/tests/SimpleTest/SpecialPowersObserverAPI.js (../specialpowers/content/SpecialPowersObserverAPI.js)
+  content/tests/SimpleTest/specialpowersAPI.js (../specialpowers/content/specialpowersAPI.js)
   content/tests/SimpleTest/setup.js (tests/SimpleTest/setup.js)
   content/tests/SimpleTest/SimpleTest.js (tests/SimpleTest/SimpleTest.js)
   content/tests/SimpleTest/test.css (tests/SimpleTest/test.css)
   content/tests/SimpleTest/TestRunner.js (tests/SimpleTest/TestRunner.js)
   content/tests/SimpleTest/WindowSnapshot.js (tests/SimpleTest/WindowSnapshot.js)
   content/tests/SimpleTest/MockObjects.js (tests/SimpleTest/MockObjects.js)
   content/tests/SimpleTest/NativeKeyCodes.js (tests/SimpleTest/NativeKeyCodes.js)
   content/tests/SimpleTest/docshell_helpers.js (../../docshell/test/chrome/docshell_helpers.js)
 
-% resource mochikit %modules/
-  modules/MockFilePicker.jsm (MockFilePicker.jsm)
--- a/testing/mochitest/tests/SimpleTest/Makefile.in
+++ b/testing/mochitest/tests/SimpleTest/Makefile.in
@@ -5,27 +5,25 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 include $(DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/rules.mk
-_SIMPLETEST_FILES =	MozillaLogger.js \
-			LogController.js \
+_SIMPLETEST_FILES =	LogController.js \
 			SimpleTest.js \
 			test.css \
 			TestRunner.js \
 			setup.js \
 			EventUtils.js \
 			ChromeUtils.js \
 			WindowSnapshot.js \
-			specialpowersAPI.js \
-			SpecialPowersObserverAPI.js \
 			MockObjects.js \
 			NativeKeyCodes.js \
+			$(DEPTH)/testing/specialpowers/content/MozillaLogger.js \
 			$(DEPTH)/docshell/test/chrome/docshell_helpers.js \
 			$(NULL)
 
 libs:: $(_SIMPLETEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/$(relativesrcdir)
 
rename from testing/mochitest/specialpowers/Makefile.in
rename to testing/specialpowers/Makefile.in
--- a/testing/mochitest/specialpowers/Makefile.in
+++ b/testing/specialpowers/Makefile.in
@@ -20,22 +20,27 @@ DIST_FILES = \
 
 EXTRA_COMPONENTS = components/SpecialPowersObserver.js
 
 XPI_NAME=specialpowers
 
 # Used in install.rdf
 USE_EXTENSION_MANIFEST=1
 
-TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
+TEST_EXTENSIONS_DIR = $(DEPTH)/testing/specialpowers
 
 include $(topsrcdir)/config/rules.mk
 
 # JarMaker creates a chrome.manifest already, so the one from the source
 # directory is not copied if it's not forced to be.
 $(FINAL_TARGET)/chrome.manifest: FORCE
 
 libs-preqs = \
   $(call mkdir_deps,$(TEST_EXTENSIONS_DIR)) \
   $(NULL)
 
 libs:: $(libs-preqs)
 	(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - $(XPI_NAME)) | (cd $(TEST_EXTENSIONS_DIR) && tar -xf -)
+	$(NSINSTALL) -D $(DEPTH)/_tests/testing/mochitest/extensions/specialpowers
+	cp -RL $(DEPTH)/testing/specialpowers/specialpowers $(DEPTH)/_tests/testing/mochitest/extensions
+	$(NSINSTALL) -D $(DEPTH)/_tests/reftest/specialpowers
+	cp -RL $(DEPTH)/testing/specialpowers/specialpowers $(DEPTH)/_tests/reftest
+
rename from testing/mochitest/specialpowers/chrome.manifest
rename to testing/specialpowers/chrome.manifest
--- a/testing/mochitest/specialpowers/chrome.manifest
+++ b/testing/specialpowers/chrome.manifest
@@ -1,4 +1,5 @@
 content specialpowers chrome/specialpowers/content/
+resource specialpowers chrome/specialpowers/modules/
 component {59a52458-13e0-4d93-9d85-a637344f29a1} components/SpecialPowersObserver.js
 contract @mozilla.org/special-powers-observer;1 {59a52458-13e0-4d93-9d85-a637344f29a1}
 category profile-after-change @mozilla.org/special-powers-observer;1 @mozilla.org/special-powers-observer;1
rename from testing/mochitest/specialpowers/components/SpecialPowersObserver.js
rename to testing/specialpowers/components/SpecialPowersObserver.js
rename from testing/mochitest/MockFilePicker.jsm
rename to testing/specialpowers/content/MockFilePicker.jsm
rename from testing/mochitest/tests/SimpleTest/MozillaLogger.js
rename to testing/specialpowers/content/MozillaLogger.js
rename from testing/mochitest/tests/SimpleTest/SpecialPowersObserverAPI.js
rename to testing/specialpowers/content/SpecialPowersObserverAPI.js
rename from testing/mochitest/specialpowers/content/specialpowers.js
rename to testing/specialpowers/content/specialpowers.js
rename from testing/mochitest/tests/SimpleTest/specialpowersAPI.js
rename to testing/specialpowers/content/specialpowersAPI.js
--- a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -4,17 +4,17 @@
 /* This code is loaded in every child process that is started by mochitest in
  * order to be used as a replacement for UniversalXPConnect
  */
 
 var Ci = Components.interfaces;
 var Cc = Components.classes;
 var Cu = Components.utils;
 
-Components.utils.import("resource://mochikit/MockFilePicker.jsm");
+Components.utils.import("resource://specialpowers/MockFilePicker.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 function SpecialPowersAPI() { 
   this._consoleListeners = [];
   this._encounteredCrashDumpFiles = [];
   this._unexpectedCrashDumpFiles = { };
   this._crashDumpDir = null;
   this._mfl = null;
@@ -878,16 +878,20 @@ SpecialPowersAPI.prototype = {
       }
 
       Components.utils.schedulePreciseGC(scheduledGCCallback);
     }
 
     doPreciseGCandCC();
   },
 
+  setGCZeal: function(zeal) {
+    Components.utils.setGCZeal(zeal);
+  },
+
   isMainProcess: function() {
     try {
       return Cc["@mozilla.org/xre/app-info;1"].
                getService(Ci.nsIXULRuntime).
                processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
     } catch (e) { }
     return true;
   },
@@ -1194,10 +1198,10 @@ SpecialPowersAPI.prototype = {
       'isInBrowserElement': isInBrowserElement
     };
 
     this._sendSyncMessage('SPPermissionManager', msg);
   },
 
   getMozFullPath: function(file) {
     return file.mozFullPath;
-  }
+  },
 };
rename from testing/mochitest/specialpowers/install.rdf
rename to testing/specialpowers/install.rdf
rename from testing/mochitest/specialpowers/jar.mn
rename to testing/specialpowers/jar.mn
--- a/testing/mochitest/specialpowers/jar.mn
+++ b/testing/specialpowers/jar.mn
@@ -1,6 +1,9 @@
 specialpowers.jar:
 % content specialpowers %content/
   content/specialpowers.js (content/specialpowers.js)
-  content/specialpowersAPI.js (../tests/SimpleTest/specialpowersAPI.js)
-  content/SpecialPowersObserverAPI.js (../tests/SimpleTest/SpecialPowersObserverAPI.js)
-  content/MozillaLogger.js (../tests/SimpleTest/MozillaLogger.js)
+  content/specialpowersAPI.js (content/specialpowersAPI.js)
+  content/SpecialPowersObserverAPI.js (content/SpecialPowersObserverAPI.js)
+  content/MozillaLogger.js (content/MozillaLogger.js)
+
+% resource specialpowers %modules/
+  modules/MockFilePicker.jsm (content/MockFilePicker.jsm)
--- a/toolkit/components/osfile/osfile_win_back.jsm
+++ b/toolkit/components/osfile/osfile_win_back.jsm
@@ -85,24 +85,34 @@
          function maybe_HANDLE_importFromC(maybe) {
            if (Types.int.cast(maybe).value == INVALID_HANDLE) {
              // Ensure that API clients can effectively compare against
              // Const.INVALID_HANDLE_VALUE. Without this cast,
              // == would always return |false|.
              return INVALID_HANDLE;
            }
          return ctypes.CDataFinalizer(maybe, _CloseHandle);
-         };
+       };
 
        /**
         * A C integer holding INVALID_HANDLE_VALUE in case of error or
         * a file descriptor in case of success.
         */
        Types.maybe_find_HANDLE =
-         Types.maybe_HANDLE.withName("maybe_find_HANDLE");
+         Types.HANDLE.withName("maybe_find_HANDLE");
+       Types.maybe_find_HANDLE.importFromC =
+         function maybe_find_HANDLE_importFromC(maybe) {
+           if (Types.int.cast(maybe).value == INVALID_HANDLE) {
+             // Ensure that API clients can effectively compare against
+             // Const.INVALID_HANDLE_VALUE. Without this cast,
+             // == would always return |false|.
+             return INVALID_HANDLE;
+           }
+         return ctypes.CDataFinalizer(maybe, _FindClose);
+       };
 
        let INVALID_HANDLE = exports.OS.Constants.Win.INVALID_HANDLE_VALUE;
 
        Types.DWORD = Types.int32_t.withName("DWORD");
 
        /**
         * A C integer holding -1 in case of error or a positive integer
         * in case of success.
@@ -182,22 +192,22 @@
                         /*return */ctypes.bool,
                         /*handle*/ ctypes.voidptr_t);
 
        WinFile.CloseHandle = function(fd) {
          return fd.dispose(); // Returns the value of |CloseHandle|.
        };
 
        let _FindClose =
-         libc.declare("CloseHandle", ctypes.winapi_abi,
+         libc.declare("FindClose", ctypes.winapi_abi,
                         /*return */ctypes.bool,
                         /*handle*/ ctypes.voidptr_t);
 
        WinFile.FindClose = function(handle) {
-         return handle.dispose(); // Returns the value of |CloseHandle|.
+         return handle.dispose(); // Returns the value of |FindClose|.
        };
 
        // Declare libc functions as functions of |OS.Win.File|
 
        WinFile.CopyFile =
          declareFFI("CopyFileW", ctypes.winapi_abi,
                     /*return*/ Types.zero_or_nothing,
                     /*sourcePath*/ Types.path,
--- a/toolkit/identity/Sandbox.jsm
+++ b/toolkit/identity/Sandbox.jsm
@@ -77,29 +77,26 @@ Sandbox.prototype = {
    * property of this object.
    */
   _createFrame: function Sandbox__createFrame() {
     let hiddenWindow = Services.appShell.hiddenDOMWindow;
     let doc = hiddenWindow.document;
 
     // Insert iframe in to create docshell.
     let frame = doc.createElementNS(XHTML_NS, "iframe");
-    frame.setAttribute("mozbrowser", true);
     frame.setAttribute("mozframetype", "content");
+    frame.sandbox = "allow-forms allow-scripts allow-same-origin";
     frame.style.visibility = "collapse";
     doc.documentElement.appendChild(frame);
 
     let docShell = frame.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                                       .getInterface(Ci.nsIWebNavigation)
                                       .QueryInterface(Ci.nsIInterfaceRequestor)
                                       .getInterface(Ci.nsIDocShell);
 
-    // Mark this docShell as a "browserFrame", to break script access to e.g. window.top
-    docShell.setIsBrowserElement();
-
     // Stop about:blank from being loaded.
     docShell.stop(Ci.nsIWebNavigation.STOP_NETWORK);
 
     // Disable some types of content
     docShell.allowAuth = false;
     docShell.allowPlugins = false;
     docShell.allowImages = false;
     docShell.allowWindowControl = false;
--- a/toolkit/locales/l10n.mk
+++ b/toolkit/locales/l10n.mk
@@ -125,17 +125,17 @@ ifdef MOZ_WEBAPP_RUNTIME
 endif
 ifneq (en,$(AB))
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 	mv $(_ABS_DIST)/l10n-stage/$(MOZ_PKG_DIR)/$(_APPNAME)/Contents/Resources/en.lproj $(_ABS_DIST)/l10n-stage/$(MOZ_PKG_DIR)/$(_APPNAME)/Contents/Resources/$(AB).lproj
 endif
 endif
 	$(NSINSTALL) -D $(DIST)/l10n-stage/$(PKG_PATH)
 	cd $(DIST)/l10n-stage; \
-	  $(MAKE_PACKAGE)
+	  $(PREPARE_PACKAGE) && $(MAKE_PACKAGE)
 ifdef MAKE_COMPLETE_MAR
 	$(MAKE) -C $(MOZDEPTH)/tools/update-packaging full-update AB_CD=$(AB_CD) \
 	  MOZ_PKG_PRETTYNAMES=$(MOZ_PKG_PRETTYNAMES) \
 	  PACKAGE_BASE_DIR="$(_ABS_DIST)/l10n-stage" \
 	  DIST="$(_ABS_DIST)"
 endif
 # packaging done, undo l10n stuff
 ifneq (en,$(AB))
--- a/toolkit/mozapps/downloads/tests/Makefile.in
+++ b/toolkit/mozapps/downloads/tests/Makefile.in
@@ -17,9 +17,9 @@ XPCSHELL_TESTS = \
   unit \
   $(NULL)
 
 DIRS += chrome
 
 include $(topsrcdir)/config/rules.mk
 
 libs:: 
-	$(INSTALL) $(topsrcdir)/testing/mochitest/MockFilePicker.jsm $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit
+	$(INSTALL) $(topsrcdir)/testing/specialpowers/content/MockFilePicker.jsm $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit
--- a/toolkit/mozapps/installer/linux/rpm/mozilla.spec
+++ b/toolkit/mozapps/installer/linux/rpm/mozilla.spec
@@ -7,17 +7,17 @@
 #Use a consistent string to refer to the package by
 %define pr_name "%{moz_app_displayname} %{moz_app_version}"
 
 Name:           %{moz_app_name}
 Version:        %{moz_numeric_app_version}
 Release:        %{?moz_rpm_release:%{moz_rpm_release}}%{?buildid:.%{buildid}}
 Summary:        %{pr_name}
 Group:          Applications/Internet
-License:        MPLv1.1 or GPLv2+ or LGPLv2+
+License:        MPL 2
 Vendor:         Mozilla
 URL:            http://www.mozilla.org/projects/firefox/
 Source0:        %{name}.desktop
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 #AutoProv:       no
 
 BuildRequires:  desktop-file-utils
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -561,30 +561,29 @@ MOZ_SIGN_PREPARED_PACKAGE_CMD=$(MOZ_SIGN
 endif
 
 # For final GPG / authenticode signing / dmg signing if required
 ifdef MOZ_EXTERNAL_SIGNING_FORMAT
 MOZ_SIGN_PACKAGE_CMD=$(MOZ_SIGN_CMD) $(foreach f,$(MOZ_EXTERNAL_SIGNING_FORMAT),-f $(f))
 endif
 
 ifdef MOZ_SIGN_PREPARED_PACKAGE_CMD
-ifeq (Darwin, $(OS_ARCH)) 
-MAKE_PACKAGE    = $(PREPARE_PACKAGE) \
-                  && cd ./$(PKG_DMG_SOURCE) && $(MOZ_SIGN_PREPARED_PACKAGE_CMD) $(MOZ_MACBUNDLE_NAME) \
+ifeq (Darwin, $(OS_ARCH))
+MAKE_PACKAGE    = cd ./$(PKG_DMG_SOURCE) && $(MOZ_SIGN_PREPARED_PACKAGE_CMD) $(MOZ_MACBUNDLE_NAME) \
                   && rm $(MOZ_MACBUNDLE_NAME)/Contents/CodeResources \
                   && cp $(MOZ_MACBUNDLE_NAME)/Contents/_CodeSignature/CodeResources $(MOZ_MACBUNDLE_NAME)/Contents \
                   && cd $(PACKAGE_BASE_DIR) \
                   && $(INNER_MAKE_PACKAGE)
 else
-MAKE_PACKAGE    = $(PREPARE_PACKAGE) && $(MOZ_SIGN_PREPARED_PACKAGE_CMD) \
+MAKE_PACKAGE    = $(MOZ_SIGN_PREPARED_PACKAGE_CMD) \
 		  $(MOZ_PKG_DIR) && $(INNER_MAKE_PACKAGE)
 endif #Darwin
 
 else
-MAKE_PACKAGE    = $(PREPARE_PACKAGE) && $(INNER_MAKE_PACKAGE)
+MAKE_PACKAGE    = $(INNER_MAKE_PACKAGE)
 endif
 
 ifdef MOZ_SIGN_PACKAGE_CMD
 MAKE_PACKAGE    += && $(MOZ_SIGN_PACKAGE_CMD) "$(PACKAGE)"
 endif
 
 ifdef MOZ_SIGN_CMD
 MAKE_SDK           += && $(MOZ_SIGN_CMD) -f gpg $(SDK)
@@ -715,29 +714,23 @@ ifndef MOZ_PKG_FATAL_WARNINGS
 MOZ_PKG_FATAL_WARNINGS = 0
 endif
 
 define PACKAGER_COPY
 $(PERL) -I$(MOZILLA_DIR)/toolkit/mozapps/installer -e 'use Packager; \
        Packager::Copy($1,$2,$3,$4,$5,$(MOZ_PKG_FATAL_WARNINGS),$6,$7);'
 endef
 
-installer-stage: stage-package
+installer-stage: prepare-package
 ifndef MOZ_PKG_MANIFEST
 	$(error MOZ_PKG_MANIFEST unspecified!)
 endif
 	@rm -rf $(DEPTH)/installer-stage $(DIST)/xpt
 	@echo "Staging installer files..."
 	@$(NSINSTALL) -D $(DEPTH)/installer-stage/core
-ifdef MOZ_OMNIJAR
-	@(cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && $(PACK_OMNIJAR))
-ifdef MOZ_WEBAPP_RUNTIME
-	@(cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/webapprt && $(PACK_OMNIJAR_WEBAPP_RUNTIME))
-endif
-endif
 	@cp -av $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/. $(DEPTH)/installer-stage/core
 	@(cd $(DEPTH)/installer-stage/core && $(CREATE_PRECOMPLETE_CMD))
 ifdef MOZ_SIGN_PREPARED_PACKAGE_CMD
 # The && true is necessary to make sure Pymake spins a shell
 	$(MOZ_SIGN_PREPARED_PACKAGE_CMD) $(DEPTH)/installer-stage && true
 endif
 
 elfhack:
@@ -854,17 +847,20 @@ ifndef LIBXUL_SDK
 ifdef MOZ_PACKAGE_JSSHELL
 # Package JavaScript Shell
 	@echo "Packaging JavaScript Shell..."
 	$(RM) $(PKG_JSSHELL)
 	$(MAKE_JSSHELL)
 endif # MOZ_PACKAGE_JSSHELL
 endif # LIBXUL_SDK
 
-make-package-internal: stage-package $(PACKAGE_XULRUNNER) make-sourcestamp-file
+prepare-package: stage-package
+	cd $(DIST) && $(PREPARE_PACKAGE)
+
+make-package-internal: prepare-package $(PACKAGE_XULRUNNER) make-sourcestamp-file
 	@echo "Compressing..."
 	cd $(DIST) && $(MAKE_PACKAGE)
 
 ifdef MOZ_FAST_PACKAGE
 MAKE_PACKAGE_DEPS = $(wildcard $(subst * , ,$(addprefix $(DIST)/bin/,$(shell $(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/packager-deps.py $(MOZ_PKG_MANIFEST)))))
 else
 MAKE_PACKAGE_DEPS = FORCE
 endif
@@ -882,29 +878,23 @@ make-sourcestamp-file::
 
 # The install target will install the application to prefix/lib/appname-version
 # In addition if INSTALL_SDK is set, it will install the development headers,
 # libraries, and IDL files as follows:
 # dist/include -> prefix/include/appname-version
 # dist/idl -> prefix/share/idl/appname-version
 # dist/sdk/lib -> prefix/lib/appname-devel-version/lib
 # prefix/lib/appname-devel-version/* symlinks to the above directories
-install:: stage-package
+install:: prepare-package
 ifeq ($(OS_ARCH),WINNT)
 	$(error "make install" is not supported on this platform. Use "make package" instead.)
 endif
 ifeq (bundle,$(MOZ_FS_LAYOUT))
 	$(error "make install" is not supported on this platform. Use "make package" instead.)
 endif
-ifdef MOZ_OMNIJAR
-	cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && $(PACK_OMNIJAR)
-ifdef MOZ_WEBAPP_RUNTIME
-	cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/webapprt && $(PACK_OMNIJAR_WEBAPP_RUNTIME)
-endif
-endif
 	$(NSINSTALL) -D $(DESTDIR)$(installdir)
 	(cd $(DIST)/$(MOZ_PKG_DIR) && tar $(TAR_CREATE_FLAGS) - .) | \
 	  (cd $(DESTDIR)$(installdir) && tar -xf -)
 	$(NSINSTALL) -D $(DESTDIR)$(bindir)
 	$(RM) -f $(DESTDIR)$(bindir)/$(MOZ_APP_NAME)
 	ln -s $(installdir)/$(MOZ_APP_NAME) $(DESTDIR)$(bindir)
 ifdef INSTALL_SDK # Here comes the hard part
 	$(NSINSTALL) -D $(DESTDIR)$(includedir)
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -849,16 +849,17 @@ if [ "$ENABLE_TESTS" ]; then
     intl/uconv/tests/Makefile
     intl/unicharutil/tests/Makefile
     js/xpconnect/tests/Makefile
     js/xpconnect/tests/chrome/Makefile
     js/xpconnect/tests/components/js/Makefile
     js/xpconnect/tests/components/native/Makefile
     js/xpconnect/tests/idl/Makefile
     js/xpconnect/tests/mochitest/Makefile
+    testing/specialpowers/Makefile
     layout/base/tests/Makefile
     layout/base/tests/chrome/Makefile
     layout/base/tests/cpp-tests/Makefile
     layout/forms/test/Makefile
     layout/generic/test/Makefile
     layout/inspector/tests/Makefile
     layout/inspector/tests/chrome/Makefile
     layout/mathml/tests/Makefile
@@ -891,17 +892,16 @@ if [ "$ENABLE_TESTS" ]; then
     services/crypto/component/tests/Makefile
     startupcache/test/Makefile
     storage/test/Makefile
     testing/firebug/Makefile
     testing/mochitest/Makefile
     testing/mochitest/MochiKit/Makefile
     testing/mochitest/chrome/Makefile
     testing/mochitest/dynamic/Makefile
-    testing/mochitest/specialpowers/Makefile
     testing/mochitest/ssltunnel/Makefile
     testing/mochitest/static/Makefile
     testing/mochitest/tests/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/MochiKit/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/tests/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/tests/SimpleTest/Makefile
     testing/mochitest/tests/SimpleTest/Makefile
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -156,16 +156,20 @@ tier_platform_dirs += \
 		media/omx-plugin \
 		$(NULL)
 endif
 
 ifndef MOZ_NATIVE_PNG
 tier_platform_dirs += media/libpng
 endif
 
+ifdef ENABLE_TESTS
+tier_platform_dirs += testing/specialpowers
+endif
+
 tier_platform_dirs	+= \
 		uriloader \
 		caps \
 		parser \
 		gfx \
 		image \
 		dom \
 		view \
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -24,16 +24,18 @@
 #include "nsXPCOM.h"
 #include "nsXPCOMCID.h"
 #include "nsIHttpProtocolHandler.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIXULRuntime.h"
 #include "nsIXULAppInfo.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
+#include "nsIObserverService.h"
+#include "mozilla/Services.h"
 
 // JS
 #include "jsdbgapi.h"
 
 // we eventually want to make this runtime switchable
 #if defined(MOZ_PROFILING) && (defined(XP_UNIX) && !defined(XP_MACOSX))
  #ifndef ANDROID
   #define USE_BACKTRACE
@@ -1091,16 +1093,20 @@ void mozilla_sampler_start(int aProfileE
 
   TableTicker *t = new TableTicker(aInterval ? aInterval : PROFILE_DEFAULT_INTERVAL,
                                    aProfileEntries ? aProfileEntries : PROFILE_DEFAULT_ENTRY,
                                    stack, aFeatures, aFeatureCount);
   tlsTicker.set(t);
   t->Start();
   if (t->ProfileJS())
       stack->enableJSSampling();
+
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os)
+    os->NotifyObservers(nullptr, "profiler-started", nullptr);
 }
 
 void mozilla_sampler_stop()
 {
   if (!stack_key_initialized)
     mozilla_sampler_init();
 
   TableTicker *t = tlsTicker.get();
@@ -1113,16 +1119,20 @@ void mozilla_sampler_stop()
   t->Stop();
   delete t;
   tlsTicker.set(NULL);
   ProfileStack *stack = tlsStack.get();
   ASSERT(stack != NULL);
 
   if (disableJS)
     stack->disableJSSampling();
+
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os)
+    os->NotifyObservers(nullptr, "profiler-stopped", nullptr);
 }
 
 bool mozilla_sampler_is_active()
 {
   if (!stack_key_initialized)
     mozilla_sampler_init();
 
   TableTicker *t = tlsTicker.get();
--- a/widget/xpwidgets/nsIdleService.cpp
+++ b/widget/xpwidgets/nsIdleService.cpp
@@ -144,16 +144,20 @@ nsIdleServiceDaily::Init()
     lastDaily = 0;
   }
 
   // Check if it has been a day since the last notification.
   if (nowSec - lastDaily > SECONDS_PER_DAY) {
 #ifdef ANDROID
     __android_log_print(ANDROID_LOG_INFO, "IdleService", "DailyCallback started");
 #endif
+    // The timer would have been started after the previous idle-daily. Need to
+    // set this here so DailyCallback knows the timer didn't fire early.
+    mDailyTimerStart = lastDaily * PR_USEC_PER_SEC;
+
     // Wait for the user to become idle, so we can do todays idle tasks.
     DailyCallback(nullptr, this);
   }
   else {
 #ifdef ANDROID
     __android_log_print(ANDROID_LOG_INFO, "IdleService", "Setting timer a day from now");
 #endif