Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Thu, 06 Sep 2012 00:54:31 -0700
changeset 111066 16a74f8678e91aa93a5fab760818e55c90e4b71a
parent 111065 06cc6f281e4f4ce1d0a67f439ed5e89d89d8de4f (current diff)
parent 106439 0c4fa25f637ba230081d9fca316acc063187e6b2 (diff)
child 111067 c66677223fd860e4fc7c668c68eb6c1c9a178d80
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone18.0a1
Merge m-c to s-c.
build/macosx/common
config/makefiles/test/check-xpidl.mk
config/makefiles/xpidl.mk
dom/camera/CameraCapabilities.h
dom/camera/CameraControl.cpp
dom/camera/CameraControl.h
dom/camera/CameraPreview.cpp
dom/camera/CameraPreview.h
dom/camera/GonkCameraCapabilities.cpp
dom/camera/GonkCameraPreview.cpp
dom/camera/GonkCameraPreview.h
dom/tests/mochitest/webapps/apphelper.js
dom/tests/mochitest/webapps/apps/bug_765063.xul
dom/tests/mochitest/webapps/apps/include.html
dom/tests/mochitest/webapps/apps/manifest_with_bom.webapp
dom/tests/mochitest/webapps/apps/manifest_with_bom.webapp^headers^
dom/tests/mochitest/webapps/apps/super_crazy.webapp
dom/tests/mochitest/webapps/apps/super_crazy.webapp^headers^
dom/tests/mochitest/webapps/apps/wild_crazy.webapp
dom/tests/mochitest/webapps/apps/wild_crazy.webapp^headers^
dom/tests/mochitest/webapps/jshelper.js
dom/tests/mochitest/webapps/test_cross_domain.xul
editor/idl/nsIEditorLogging.idl
editor/libeditor/html/nsHTMLEditorLog.cpp
editor/libeditor/html/nsHTMLEditorLog.h
js/src/config/makefiles/xpidl.mk
--- a/accessible/src/base/FocusManager.cpp
+++ b/accessible/src/base/FocusManager.cpp
@@ -55,17 +55,17 @@ FocusManager::IsFocused(const Accessible
     // accessible creation for temporary about:blank document. Without this
     // peculiarity we would end up with plain implementation based on
     // FocusedAccessible() method call. Make sure this issue is fixed in
     // bug 638465.
     if (focusedNode->OwnerDoc() == aAccessible->GetNode()->OwnerDoc()) {
       DocAccessible* doc = 
         GetAccService()->GetDocAccessible(focusedNode->OwnerDoc());
       return aAccessible ==
-	(doc ? doc->GetAccessibleOrContainer(focusedNode) : nullptr);
+        (doc ? doc->GetAccessibleOrContainer(focusedNode) : nullptr);
     }
   }
   return false;
 }
 
 bool
 FocusManager::IsFocusWithin(const Accessible* aContainer) const
 {
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -2841,17 +2841,31 @@ bool
 Accessible::IsWidget() const
 {
   return false;
 }
 
 bool
 Accessible::IsActiveWidget() const
 {
-  return FocusMgr()->IsFocused(this);
+  if (FocusMgr()->HasDOMFocus(mContent))
+    return true;
+
+  // If text entry of combobox widget has a focus then the combobox widget is
+  // active.
+  if (mRoleMapEntry && mRoleMapEntry->Is(nsGkAtoms::combobox)) {
+    PRUint32 childCount = ChildCount();
+    for (PRUint32 idx = 0; idx < childCount; idx++) {
+      Accessible* child = mChildren.ElementAt(idx);
+      if (child->Role() == roles::ENTRY)
+        return FocusMgr()->HasDOMFocus(child->GetContent());
+    }
+  }
+
+  return false;
 }
 
 bool
 Accessible::AreItemsOperable() const
 {
   return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant);
 }
 
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -1216,21 +1216,21 @@ DocAccessible::ARIAAttributeChanged(nsIC
                                aContent);
     return;
   }
 }
 
 void
 DocAccessible::ARIAActiveDescendantChanged(nsIContent* aElm)
 {
-  if (FocusMgr()->HasDOMFocus(aElm)) {
+  Accessible* widget = GetAccessible(aElm);
+  if (widget && widget->IsActiveWidget()) {
     nsAutoString id;
     if (aElm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) {
-      nsIDocument* DOMDoc = aElm->OwnerDoc();
-      dom::Element* activeDescendantElm = DOMDoc->GetElementById(id);
+      dom::Element* activeDescendantElm = aElm->OwnerDoc()->GetElementById(id);
       if (activeDescendantElm) {
         Accessible* activeDescendant = GetAccessible(activeDescendantElm);
         if (activeDescendant) {
           FocusMgr()->ActiveItemChanged(activeDescendant, false);
           A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("ARIA activedescedant changed",
                                                  activeDescendant)
         }
       }
--- a/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html
+++ b/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html
@@ -65,16 +65,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     var gQueue = null;
     function doTest()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new synthFocus("container", new focusChecker("item1")));
       gQueue.push(new changeARIAActiveDescendant("container", "item2"));
+
+      gQueue.push(new synthFocus("combobox_entry", new focusChecker("combobox_entry")));
+      gQueue.push(new changeARIAActiveDescendant("combobox", "combobox_option2"));
+
       todo(false, "No focus for inserted element, bug 687011");
       //gQueue.push(new insertItemNFocus("container", "item3"));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
@@ -82,19 +86,32 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=429547"
      title="Support aria-activedescendant usage in nsIAccesible::TakeFocus()">
     Mozilla Bug 429547
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=761102"
+     title="Focus may be missed when ARIA active-descendant is changed on active composite widget">
+    Mozilla Bug 761102
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div role="listbox" aria-activedescendant="item1" id="container" tabindex="1">
     <div role="listitem" id="item1">item1</div>
     <div role="listitem" id="item2">item2</div>
   </div>
+
+  <div role="combobox" id="combobox">
+    <input id="combobox_entry">
+    <ul>
+      <li role="option" id="combobox_option1">option1</li>
+      <li role="option" id="combobox_option2">option2</li>
+    </ul>
+  </div>
 </body>
 </html>
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -39,19 +39,19 @@ pref("network.protocol-handler.warn-exte
 pref("network.protocol-handler.warn-external.vnd.youtube", false);
 
 /* http prefs */
 pref("network.http.pipelining", true);
 pref("network.http.pipelining.ssl", true);
 pref("network.http.proxy.pipelining", true);
 pref("network.http.pipelining.maxrequests" , 6);
 pref("network.http.keep-alive.timeout", 600);
-pref("network.http.max-connections", 6);
-pref("network.http.max-persistent-connections-per-server", 4);
-pref("network.http.max-persistent-connections-per-proxy", 4);
+pref("network.http.max-connections", 20);
+pref("network.http.max-persistent-connections-per-server", 6);
+pref("network.http.max-persistent-connections-per-proxy", 20);
 
 // See bug 545869 for details on why these are set the way they are
 pref("network.buffer.cache.count", 24);
 pref("network.buffer.cache.size",  16384);
 
 /* session history */
 pref("browser.sessionhistory.max_total_viewers", 1);
 pref("browser.sessionhistory.max_entries", 50);
@@ -502,17 +502,17 @@ pref("ui.showHideScrollbars", 1);
 
 // Enable the ProcessPriorityManager, and give processes with no visible
 // documents a 1s grace period before they're eligible to be marked as
 // background.
 pref("dom.ipc.processPriorityManager.enabled", true);
 pref("dom.ipc.processPriorityManager.gracePeriodMS", 1000);
 pref("hal.processPriorityManager.gonk.masterOomAdjust", 0);
 pref("hal.processPriorityManager.gonk.foregroundOomAdjust", 1);
-pref("hal.processPriorityManager.gonk.backgroundOomAdjust", 2);
+pref("hal.processPriorityManager.gonk.backgroundOomAdjust", 6);
 pref("hal.processPriorityManager.gonk.masterNice", -1);
 pref("hal.processPriorityManager.gonk.foregroundNice", 0);
 pref("hal.processPriorityManager.gonk.backgroundNice", 10);
 
 #ifndef DEBUG
 // Enable pre-launching content processes for improved startup time
 // (hiding latency).
 pref("dom.ipc.processPrelauch.enabled", true);
--- a/b2g/chrome/content/forms.js
+++ b/b2g/chrome/content/forms.js
@@ -113,23 +113,38 @@ let FormAssistant = {
     let json = msg.json;
     switch (msg.name) {
       case "Forms:Input:Value":
         target.value = json.value;
         break;
 
       case "Forms:Select:Choice":
         let options = target.options;
+        let valueChanged = false;
         if ("index" in json) {
-          options.item(json.index).selected = true;
+          if (options.selectedIndex != json.index) {
+            options.selectedIndex = json.index;
+            valueChanged = true;
+          }
         } else if ("indexes" in json) {
           for (let i = 0; i < options.length; i++) {
-            options.item(i).selected = (json.indexes.indexOf(i) != -1);
+            let newValue = (json.indexes.indexOf(i) != -1);
+            if (options.item(i).selected != newValue) {
+              options.item(i).selected = newValue;
+              valueChanged = true;
+            }
           }
         }
+
+        // only fire onchange event if any selected option is changed
+        if (valueChanged) {
+          let event = content.document.createEvent('HTMLEvents');
+          event.initEvent('change', true, true);
+          target.dispatchEvent(event);
+        }
         break;
     }
   },
 
   observe: function fa_observe(subject, topic, data) {
     switch (topic) {
       case "ime-enabled-state-changed":
         let isOpen = this.isKeyboardOpened;
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -504,16 +504,19 @@ var CustomEventManager = {
         break;
       case 'webapps-install-granted':
       case 'webapps-install-denied':
         WebappsHelper.handleEvent(detail);
         break;
       case 'select-choicechange':
         FormsHelper.handleEvent(detail);
         break;
+      case 'system-message-listener-ready':
+        Services.obs.notifyObservers(null, 'system-message-listener-ready', null);
+        break;
     }
   }
 }
 
 var AlertsHelper = {
   _listeners: {},
   _count: 0,
 
new file mode 100644
--- /dev/null
+++ b/b2g/config/mozconfigs/common
@@ -0,0 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file is included at the top of all b2g mozconfigs
+
+. "$topsrcdir/build/mozconfig.common"
new file mode 100644
--- /dev/null
+++ b/b2g/config/mozconfigs/common.override
@@ -0,0 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file is included at the bottom of all b2g mozconfigs
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/b2g/config/mozconfigs/gb_armv7a_gecko/debug
+++ b/b2g/config/mozconfigs/gb_armv7a_gecko/debug
@@ -1,8 +1,10 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
+
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 mk_add_options MOZ_MAKE_FLAGS="-j8"
 
 ac_add_options --enable-application=b2g
 
 ac_add_options --target=arm-android-eabi
 ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
@@ -10,8 +12,10 @@ ac_add_options --with-gonk-toolchain-pre
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 ac_add_options --enable-debug
 ac_add_options --with-ccache
 ENABLE_MARIONETTE=1
 
 # Enable dump() from JS.
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/gb_armv7a_gecko/nightly
+++ b/b2g/config/mozconfigs/gb_armv7a_gecko/nightly
@@ -1,8 +1,10 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
+
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 mk_add_options MOZ_MAKE_FLAGS="-j8"
 
 ac_add_options --enable-application=b2g
 
 ac_add_options --target=arm-android-eabi
 ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
@@ -10,8 +12,10 @@ ac_add_options --with-gonk-toolchain-pre
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 ac_add_options --enable-profiling
 ac_add_options --with-ccache
 ENABLE_MARIONETTE=1
 
 # Enable dump() from JS.
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/debug
+++ b/b2g/config/mozconfigs/ics_armv7a_gecko/debug
@@ -13,8 +13,10 @@ ac_add_options --with-gonk-toolchain-pre
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 ac_add_options --enable-debug
 #ac_add_options --with-ccache
 ENABLE_MARIONETTE=1
 
 # Enable dump() from JS.
 export CXXFLAGS="-DMOZ_ENABLE_JS_DUMP -include $topsrcdir/gonk-toolchain/gonk-misc/Unicode.h -include $topsrcdir/gonk-toolchain/system/vold/ResponseCode.h"
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/nightly
+++ b/b2g/config/mozconfigs/ics_armv7a_gecko/nightly
@@ -1,8 +1,10 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
+
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 mk_add_options MOZ_MAKE_FLAGS="-j8"
 
 ac_add_options --enable-application=b2g
 ac_add_options --enable-b2g-camera
 
 ac_add_options --target=arm-android-eabi
@@ -13,8 +15,10 @@ ac_add_options --with-gonk-toolchain-pre
 ac_add_options --disable-elf-hack
 ac_add_options --enable-debug-symbols
 ac_add_options --enable-profiling
 #ac_add_options --with-ccache
 ENABLE_MARIONETTE=1
 
 # Enable dump() from JS.
 export CXXFLAGS="-DMOZ_ENABLE_JS_DUMP -include $topsrcdir/gonk-toolchain/gonk-misc/Unicode.h -include $topsrcdir/gonk-toolchain/system/vold/ResponseCode.h"
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/linux32_gecko/nightly
+++ b/b2g/config/mozconfigs/linux32_gecko/nightly
@@ -1,8 +1,10 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
+
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 #ac_add_options --enable-js-diagnostics
 
@@ -31,8 +33,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
 # Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 #B2G options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
 ac_add_options --disable-elf-hack
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/linux64_gecko/nightly
+++ b/b2g/config/mozconfigs/linux64_gecko/nightly
@@ -33,8 +33,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
 # Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 #B2G options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
 ac_add_options --disable-elf-hack
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly
+++ b/b2g/config/mozconfigs/macosx64_gecko/nightly
@@ -1,9 +1,9 @@
-. $topsrcdir/build/macosx/common
+. $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
@@ -21,8 +21,10 @@ ac_add_options --enable-warnings-as-erro
 
 # B2G Stuff
 ac_add_options --enable-application=b2g
 ac_add_options --enable-debug-symbols
 ac_add_options --with-ccache
 ENABLE_MARIONETTE=1
 
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/b2g/config/mozconfigs/win32_gecko/nightly
+++ b/b2g/config/mozconfigs/win32_gecko/nightly
@@ -1,8 +1,10 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
+
 # for pgo
 mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py'
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 
@@ -22,8 +24,10 @@ else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # B2G Options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
 
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
+
+. "$topsrcdir/b2g/config/mozconfigs/common.override"
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -121,42 +121,42 @@ endif #}
 endif #}
 endif #}
 
 ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH)))
 
 libs:: 
 	cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 
-GARBAGE += $(addprefix $(DIST)/bin/defaults/pref/, firefox.js)
+GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, firefox.js)
 
 endif
 
 endif #} LIBXUL_SDK
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 libs::
-	$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(DIST)/bin/icons
-	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png  $(DIST)/bin/chrome/icons/default
-	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png  $(DIST)/bin/chrome/icons/default
-	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png  $(DIST)/bin/chrome/icons/default
+	$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(FINAL_TARGET)/icons
+	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png  $(FINAL_TARGET)/chrome/icons/default
+	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default32.png  $(FINAL_TARGET)/chrome/icons/default
+	$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png  $(FINAL_TARGET)/chrome/icons/default
 endif
 
 libs:: $(srcdir)/profile/prefs.js
-	$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile
+	$(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/defaults/profile
 
 ifndef LIBXUL_SDK
 # channel-prefs.js is handled separate from other prefs due to bug 756325
 libs:: $(srcdir)/profile/channel-prefs.js
-	$(NSINSTALL) -D $(DIST)/bin/defaults/pref
-	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(ACDEFINES) $^ > $(DIST)/bin/defaults/pref/channel-prefs.js
+	$(NSINSTALL) -D $(FINAL_TARGET)/defaults/pref
+	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(ACDEFINES) $^ > $(FINAL_TARGET)/defaults/pref/channel-prefs.js
 endif
 
 libs:: $(srcdir)/blocklist.xml
-	$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin
+	$(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 
 MAC_APP_NAME = $(MOZ_APP_DISPLAYNAME)
 
 ifdef MOZ_DEBUG
 MAC_APP_NAME := $(MAC_APP_NAME)Debug
 endif
--- a/browser/app/profile/extensions/Makefile.in
+++ b/browser/app/profile/extensions/Makefile.in
@@ -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/.
 
 DEPTH      = @DEPTH@
 topsrcdir  = @top_srcdir@
 srcdir     = @srcdir@
 VPATH      = @srcdir@
 
-DISTROEXT = $(call core_abspath,$(DIST))/bin/distribution/extensions
+DISTROEXT = $(call core_abspath,$(FINAL_TARGET))/distribution/extensions
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = \
   {972ce4c6-7e08-4474-a285-3208198ce6fd} \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in
+++ b/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in
@@ -12,14 +12,11 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 FILES := \
 	install.rdf \
 	$(NULL)
 
 libs::
 	$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(srcdir)/install.rdf.in > install.rdf
-	$(INSTALL) $(FILES) $(DIST)/bin/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+	$(INSTALL) $(FILES) $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
  
-install::
-	$(SYSINSTALL) $(IFLAGS1) $(FILES) $(DESTDIR)$(mozappdir)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
-
 GARBAGE += $(FILES)
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -86,17 +86,17 @@
     <command id="cmd_fullZoomToggle"  oncommand="ZoomManager.toggleZoom();"/>
     <command id="Browser:OpenLocation" oncommand="openLocation();"/>
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
     <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
     <command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
     <command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focus();" disabled="true"/>
     <command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
-    <command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();" disabled="true" hidden="true"/>
+    <command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();"/>
     <command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true" hidden="true"/>
     <command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true" hidden="true"/>
     <command id="Tools:ChromeDebugger" oncommand="DebuggerUI.toggleChromeDebugger();" disabled="true" hidden="true"/>
     <command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true" hidden="true"/>
     <command id="Tools:StyleEditor" oncommand="StyleEditor.toggle();" disabled="true" hidden="true"/>
     <command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -600,34 +600,34 @@ html|*#gcli-output-frame,
 /* We don't show the Style Editor button in the developer toolbar for now.
    See bug 771203 */
 #developer-toolbar-styleeditor {
   display: none;
 }
 
 /* Responsive Mode */
 
-vbox[anonid=browserContainer][responsivemode] {
+.browserContainer[responsivemode] {
   overflow: auto;
 }
 
 .devtools-responsiveui-toolbar:-moz-locale-dir(rtl) {
   -moz-box-pack: end;
 }
 
-stack[anonid=browserStack][responsivemode] {
+.browserStack[responsivemode] {
   transition-duration: 200ms;
   transition-timing-function: linear;
 }
 
-stack[anonid=browserStack][responsivemode] {
+.browserStack[responsivemode] {
   transition-property: min-width, max-width, min-height, max-height;
 }
 
-stack[anonid=browserStack][responsivemode][notransition] {
+.browserStack[responsivemode][notransition] {
   transition: none;
 }
 
 chatbox {
   -moz-binding: url("chrome://browser/content/socialchat.xml#chatbox");
 }
 
 chatbar {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -141,24 +141,24 @@ XPCOMUtils.defineLazyGetter(this, "Socia
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
   "resource:///modules/PageThumbs.jsm");
 
 #ifdef MOZ_SAFE_BROWSING
 XPCOMUtils.defineLazyGetter(this, "SafeBrowsing", function() {
   let tmp = {};
-  Cu.import("resource://gre/modules/SafeBrowsing.jsm", tmp);
+  Cu.import("resource:///modules/SafeBrowsing.jsm", tmp);
   return tmp.SafeBrowsing;
 });
 #endif
 
 XPCOMUtils.defineLazyGetter(this, "gBrowserNewTabPreloader", function () {
   let tmp = {};
-  Cu.import("resource://gre/modules/BrowserNewTabPreloader.jsm", tmp);
+  Cu.import("resource:///modules/BrowserNewTabPreloader.jsm", tmp);
   return new tmp.BrowserNewTabPreloader();
 });
 
 let gInitialPages = [
   "about:blank",
   "about:newtab",
   "about:home",
   "about:privatebrowsing",
@@ -1429,24 +1429,16 @@ var gBrowserInit = {
       document.getElementById("Tools:DevToolbarFocus").removeAttribute("disabled");
 
       // Show the toolbar if it was previously visible
       if (gPrefService.getBoolPref("devtools.toolbar.visible")) {
         DeveloperToolbar.show(false);
       }
     }
 
-    // Enable Inspector?
-    let enabled = gPrefService.getBoolPref("devtools.inspector.enabled");
-    if (enabled) {
-      let cmd = document.getElementById("Tools:Inspect");
-      cmd.removeAttribute("disabled");
-      cmd.removeAttribute("hidden");
-    }
-
     // Enable Debugger?
     let enabled = gPrefService.getBoolPref("devtools.debugger.enabled");
     if (enabled) {
       let cmd = document.getElementById("Tools:Debugger");
       cmd.removeAttribute("disabled");
       cmd.removeAttribute("hidden");
     }
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -394,20 +394,16 @@
                     label="&identity.moreInfoLinkText;"
                     onblur="gIdentityHandler.hideIdentityPopup();"
                     oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
           </hbox>
         </vbox>
       </hbox>
     </panel>
 
-    <tooltip id="urlTooltip">
-      <label crop="center" flex="1" class="tooltip-label"/>
-    </tooltip>
-
     <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top">
       <hbox>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
--- a/browser/base/content/tabbrowser.css
+++ b/browser/base/content/tabbrowser.css
@@ -48,8 +48,18 @@ tabpanels {
 
 .closing-tabs-spacer {
   pointer-events: none;
 }
 
 .tabbrowser-tabs:not(:hover) > .tabbrowser-arrowscrollbox > .closing-tabs-spacer {
   transition: width .15s ease-out;
 }
+
+/**
+ * Optimization for tabs that are restored lazily. We can save a good amount of
+ * memory that to-be-restored tabs would otherwise consume simply by setting
+ * their browsers to 'display: none' as that will prevent them from having to
+ * create a presentation and the like.
+ */
+browser[pending] {
+  display: none;
+}
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -21,22 +21,24 @@
 
     <content>
       <xul:stringbundle anonid="tbstringbundle" src="chrome://browser/locale/tabbrowser.properties"/>
       <xul:tabbox anonid="tabbox" class="tabbrowser-tabbox"
                   flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
                   onselect="if (event.target.localName == 'tabpanels') this.parentNode.updateCurrentBrowser();">
         <xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer">
           <xul:notificationbox flex="1">
-            <xul:vbox flex="1" anonid="browserContainer">
-              <xul:stack flex="1" anonid="browserStack">
-                <xul:browser type="content-primary" message="true" disablehistory="true"
-                             xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/>
-              </xul:stack>
-            </xul:vbox>
+            <xul:hbox flex="1" class="browserSidebarContainer">
+              <xul:vbox flex="1" class="browserContainer">
+                <xul:stack flex="1" class="browserStack">
+                  <xul:browser anonid="initialBrowser" type="content-primary" message="true" disablehistory="true"
+                               xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/>
+                </xul:stack>
+              </xul:vbox>
+            </xul:hbox>
           </xul:notificationbox>
         </xul:tabpanels>
       </xul:tabbox>
       <children/>
     </content>
     <implementation implements="nsIDOMEventListener">
 
       <property name="tabContextMenu" readonly="true"
@@ -290,16 +292,25 @@
         ]]>
         </body>
       </method>
 
       <method name="getNotificationBox">
         <parameter name="aBrowser"/>
         <body>
           <![CDATA[
+            return this.getSidebarContainer(aBrowser).parentNode;
+          ]]>
+        </body>
+      </method>
+
+      <method name="getSidebarContainer">
+        <parameter name="aBrowser"/>
+        <body>
+          <![CDATA[
             return this.getBrowserContainer(aBrowser).parentNode;
           ]]>
         </body>
       </method>
 
       <method name="getBrowserContainer">
         <parameter name="aBrowser"/>
         <body>
@@ -1287,34 +1298,42 @@
             if (this.hasAttribute("autocompletepopup"))
               b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
             b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
 
             // Create the browserStack container
             var stack = document.createElementNS(
                                     "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                                     "stack");
-            stack.setAttribute("anonid", "browserStack");
+            stack.className = "browserStack";
             stack.appendChild(b);
             stack.setAttribute("flex", "1");
 
             // Create the browserContainer
-            var box = document.createElementNS(
+            var browserContainer = document.createElementNS(
                                     "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                                     "vbox");
-            box.setAttribute("anonid", "browserContainer");
-            box.appendChild(stack);
-            box.setAttribute("flex", "1");
+            browserContainer.className = "browserContainer";
+            browserContainer.appendChild(stack);
+            browserContainer.setAttribute("flex", "1");
+
+            // Create the sidebar container
+            var browserSidebarContainer = document.createElementNS(
+                                      "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
+                                      "hbox");
+            browserSidebarContainer.className = "browserSidebarContainer";
+            browserSidebarContainer.appendChild(browserContainer);
+            browserSidebarContainer.setAttribute("flex", "1");
 
             // Add the Message and the Browser to the box
             var notificationbox = document.createElementNS(
                                     "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                                     "notificationbox");
             notificationbox.setAttribute("flex", "1");
-            notificationbox.appendChild(box);
+            notificationbox.appendChild(browserSidebarContainer);
 
             var position = this.tabs.length - 1;
             var uniqueId = "panel" + Date.now() + position;
             notificationbox.id = uniqueId;
             t.linkedPanel = uniqueId;
             t.linkedBrowser = b;
             t._tPos = position;
             if (t.previousSibling.selected)
@@ -1749,17 +1768,17 @@
             // browser removal. So we remove the browser and the panel in two
             // steps.
 
             var panel = this.getNotificationBox(browser);
 
             // This will unload the document. An unload handler could remove
             // dependant tabs, so it's important that the tabbrowser is now in
             // a consistent state (tab removed, tab positions updated, etc.).
-            panel.removeChild(this.getBrowserContainer(browser));
+            browser.parentNode.removeChild(browser);
 
             // Release the browser in case something is erroneously holding a
             // reference to the tab after its removal.
             aTab.linkedBrowser = null;
 
             // As the browser is removed, the removal of a dependent document can
             // cause the whole window to close. So at this point, it's possible
             // that the binding is destructed.
@@ -2554,17 +2573,17 @@
               }
               break;
           }
         ]]></body>
       </method>
 
       <constructor>
         <![CDATA[
-          this.mCurrentBrowser = this.mPanelContainer.firstChild.firstChild.firstChild.firstChild;
+          this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser");
           this.mCurrentTab = this.tabContainer.firstChild;
           document.addEventListener("keypress", this, false);
           window.addEventListener("sizemodechange", this, false);
 
           var uniqueId = "panel" + Date.now();
           this.mPanelContainer.childNodes[0].id = uniqueId;
           this.mCurrentTab.linkedPanel = uniqueId;
           this.mCurrentTab._tPos = 0;
--- a/browser/base/content/test/browser_bug462673.js
+++ b/browser/base/content/test/browser_bug462673.js
@@ -10,17 +10,17 @@ var runs = [
     var newBrowser = newTab.linkedBrowser;
     tabbrowser.removeTab(tab);
     ok(!win.closed, "Window stays open");
     if (!win.closed) {
       is(tabbrowser.tabContainer.childElementCount, 1, "Window has one tab");
       is(tabbrowser.browsers.length, 1, "Window has one browser");
       is(tabbrowser.selectedTab, newTab, "Remaining tab is selected");
       is(tabbrowser.selectedBrowser, newBrowser, "Browser for remaining tab is selected");
-      is(tabbrowser.mTabBox.selectedPanel, newBrowser.parentNode.parentNode.parentNode, "Panel for remaining tab is selected");
+      is(tabbrowser.mTabBox.selectedPanel, newBrowser.parentNode.parentNode.parentNode.parentNode, "Panel for remaining tab is selected");
     }
   }
 ];
 
 function test() {
   waitForExplicitFinish();
   runOneTest();
 }
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -53,18 +53,16 @@
         this._prefs.addObserver("", this, false);
         this.clickSelectsAll = this._prefs.getBoolPref("clickSelectsAll");
         this.doubleClickSelectsAll = this._prefs.getBoolPref("doubleClickSelectsAll");
         this.completeDefaultIndex = this._prefs.getBoolPref("autoFill");
         this.timeout = this._prefs.getIntPref("delay");
         this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled");
         this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
 
-        this._urlTooltip = document.getElementById("urlTooltip");
-
         this.inputField.controllers.insertControllerAt(0, this._copyCutController);
         this.inputField.addEventListener("mousedown", this, false);
         this.inputField.addEventListener("mousemove", this, false);
         this.inputField.addEventListener("mouseout", this, false);
         this.inputField.addEventListener("overflow", this, false);
         this.inputField.addEventListener("underflow", this, false);
 
         const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -405,36 +403,23 @@
       </method>
 
       <field name="_contentIsCropped">false</field>
 
       <method name="_initURLTooltip">
         <body><![CDATA[
           if (this.focused || !this._contentIsCropped)
             return;
-          if (this._tooltipTimer)
-            clearTimeout(this._tooltipTimer);
-          this._tooltipTimer = setTimeout(function (self) {
-            self._tooltipTimer = 0;
-            var label = self._urlTooltip.firstChild;
-            label.value = self.value;
-            var bO = self.boxObject;
-            self._urlTooltip.maxWidth = bO.width;
-            self._urlTooltip.showPopup(self, bO.screenX, bO.screenY + bO.height, "tooltip");
-          }, 700, this);
+          this.inputField.setAttribute("tooltiptext", this.value);
         ]]></body>
       </method>
 
       <method name="_hideURLTooltip">
         <body><![CDATA[
-          if (this._tooltipTimer) {
-            clearTimeout(this._tooltipTimer);
-            this._tooltipTimer = 0;
-          }
-          this._urlTooltip.hidePopup();
+          this.inputField.removeAttribute("tooltiptext");
         ]]></body>
       </method>
 
       <method name="onDragOver">
         <parameter name="aEvent"/>
         <body>
           var types = aEvent.dataTransfer.types;
           if (types.contains("application/x-moz-file") ||
--- a/browser/components/feeds/src/nsFeedSniffer.cpp
+++ b/browser/components/feeds/src/nsFeedSniffer.cpp
@@ -341,17 +341,17 @@ nsFeedSniffer::AppendSegmentToString(nsI
   nsCString* decodedData = static_cast<nsCString*>(closure);
   decodedData->Append(rawSegment, count);
   *writeCount = count;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFeedSniffer::OnDataAvailable(nsIRequest* request, nsISupports* context,
-                               nsIInputStream* stream, uint32_t offset, 
+                               nsIInputStream* stream, uint64_t offset, 
                                uint32_t count)
 {
   uint32_t read;
   return stream->ReadSegments(AppendSegmentToString, &mDecodedData, count, 
                               &read);
 }
 
 NS_IMETHODIMP
--- a/browser/components/safebrowsing/Makefile.in
+++ b/browser/components/safebrowsing/Makefile.in
@@ -1,14 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
-DEPTH     = ../../..
+DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 TEST_DIRS += content/test
 
--- a/browser/components/safebrowsing/content/test/Makefile.in
+++ b/browser/components/safebrowsing/content/test/Makefile.in
@@ -1,18 +1,18 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-DEPTH		= ../../../../..
+DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
-relativesrcdir  = browser/components/safebrowsing/content/test
+relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 # The browser chrome test for bug 415846 doesn't run on Mac because of its
 # bizarre special-and-unique snowflake of a help menu.
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _NON_MAC_BROWSER_TESTS = browser_bug415846.js
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -2982,16 +2982,17 @@ let SessionStoreInternal = {
         this.xulAttributes[name] = true;
 
       browser.__SS_tabStillLoading = true;
 
       // keep the data around to prevent dataloss in case
       // a tab gets closed before it's been properly restored
       browser.__SS_data = tabData;
       browser.__SS_restoreState = TAB_STATE_NEEDS_RESTORE;
+      browser.setAttribute("pending", "true");
       tab.setAttribute("pending", "true");
 
       // Make sure that set/getTabValue will set/read the correct data by
       // wiping out any current value in tab.__SS_extdata.
       delete tab.__SS_extdata;
 
       if (!tabData.entries || tabData.entries.length == 0) {
         // make sure to blank out this tab's content
@@ -3166,16 +3167,17 @@ let SessionStoreInternal = {
     // Make sure that this tab is removed from _tabsToRestore
     this._removeTabFromTabsToRestore(aTab);
 
     // Increase our internal count.
     this._tabsRestoringCount++;
 
     // Set this tab's state to restoring
     browser.__SS_restoreState = TAB_STATE_RESTORING;
+    browser.removeAttribute("pending");
     aTab.removeAttribute("pending");
 
     // Remove the history listener, since we no longer need it once we start restoring
     this._removeSHistoryListener(aTab);
 
     let activeIndex = (tabData.index || tabData.entries.length) - 1;
     if (activeIndex >= tabData.entries.length)
       activeIndex = tabData.entries.length - 1;
@@ -4330,16 +4332,19 @@ let SessionStoreInternal = {
     let browser = aTab.linkedBrowser;
 
     // Keep the tab's previous state for later in this method
     let previousState = browser.__SS_restoreState;
 
     // The browser is no longer in any sort of restoring state.
     delete browser.__SS_restoreState;
 
+    aTab.removeAttribute("pending");
+    browser.removeAttribute("pending");
+
     // We want to decrement window.__SS_tabsToRestore here so that we always
     // decrement it AFTER a tab is done restoring or when a tab gets "reset".
     window.__SS_tabsToRestore--;
 
     // Remove the progress listener if we should.
     this._removeTabsProgressListener(window);
 
     if (previousState == TAB_STATE_RESTORING) {
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/common
@@ -0,0 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file is included by all browser mozconfigs
+
+. "$topsrcdir/build/mozconfig.common"
--- a/browser/config/mozconfigs/linux32/debug
+++ b/browser/config/mozconfigs/linux32/debug
@@ -17,8 +17,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
 #Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/debug-asan
+++ b/browser/config/mozconfigs/linux32/debug-asan
@@ -11,8 +11,10 @@ ac_add_options --enable-valgrind
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/l10n-mozconfig
+++ b/browser/config/mozconfigs/linux32/l10n-mozconfig
@@ -1,7 +1,9 @@
 ac_add_options --with-l10n-base=../../l10n-central
 ac_add_options --enable-official-branding
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 
 . $topsrcdir/build/unix/mozconfig.linux
 
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/nightly
+++ b/browser/config/mozconfigs/linux32/nightly
@@ -31,8 +31,10 @@ ac_add_options --enable-warnings-as-erro
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/nightly-asan
+++ b/browser/config/mozconfigs/linux32/nightly-asan
@@ -13,8 +13,10 @@ ac_add_options --enable-codesighs
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/qt
+++ b/browser/config/mozconfigs/linux32/qt
@@ -21,8 +21,10 @@ ac_add_options --with-ccache=/usr/bin/cc
 # QT Options
 export PKG_CONFIG_PATH=/tools/qt-4.6.3/qt/lib/pkgconfig
 ac_add_options --with-qtdir=/tools/qt-4.6.3/qt
 ac_add_options --enable-default-toolkit=cairo-qt
 ac_add_options --disable-crashreporter
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/release
+++ b/browser/config/mozconfigs/linux32/release
@@ -19,8 +19,10 @@ export MOZ_TELEMETRY_REPORTING=1
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux32/rpm
+++ b/browser/config/mozconfigs/linux32/rpm
@@ -24,8 +24,10 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 #Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -17,8 +17,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
 # Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/debug-asan
+++ b/browser/config/mozconfigs/linux64/debug-asan
@@ -11,8 +11,10 @@ ac_add_options --enable-valgrind
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/l10n-mozconfig
+++ b/browser/config/mozconfigs/linux64/l10n-mozconfig
@@ -1,7 +1,9 @@
 ac_add_options --with-l10n-base=../../l10n-central
 ac_add_options --enable-official-branding
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 
 . $topsrcdir/build/unix/mozconfig.linux
 
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/nightly
+++ b/browser/config/mozconfigs/linux64/nightly
@@ -31,8 +31,10 @@ ac_add_options --enable-warnings-as-erro
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/nightly-asan
+++ b/browser/config/mozconfigs/linux64/nightly-asan
@@ -13,8 +13,10 @@ ac_add_options --enable-codesighs
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/release
+++ b/browser/config/mozconfigs/linux64/release
@@ -19,8 +19,10 @@ export MOZ_TELEMETRY_REPORTING=1
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/rpm
+++ b/browser/config/mozconfigs/linux64/rpm
@@ -24,8 +24,10 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYT
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 #Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx-universal/nightly
+++ b/browser/config/mozconfigs/macosx-universal/nightly
@@ -21,8 +21,10 @@ mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 ac_add_options --with-macbundlename-prefix=Firefox
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx-universal/release
+++ b/browser/config/mozconfigs/macosx-universal/release
@@ -15,8 +15,10 @@ export MOZ_TELEMETRY_REPORTING=1
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx-universal/shark
+++ b/browser/config/mozconfigs/macosx-universal/shark
@@ -19,8 +19,10 @@ ac_add_options --enable-shark
 ac_add_options --enable-dtrace
 
 # Need this to prevent name conflicts with the normal nightly build packages
 export MOZ_PKG_SPECIAL="shark"
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 ac_add_options --with-ccache
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx32/debug
+++ b/browser/config/mozconfigs/macosx32/debug
@@ -1,16 +1,19 @@
 . $topsrcdir/build/macosx/mozconfig.leopard
+
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-signmar
 ENABLE_MARIONETTE=1
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64/debug
@@ -1,9 +1,9 @@
-. $topsrcdir/build/macosx/common
+. $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-accessibility
 ac_add_options --enable-signmar
 ENABLE_MARIONETTE=1
 
 # Enable parallel compiling
@@ -14,8 +14,10 @@ export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx64/debug-asan
+++ b/browser/config/mozconfigs/macosx64/debug-asan
@@ -7,8 +7,10 @@ ac_add_options --enable-accessibility
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/macosx64/l10n-mozconfig
+++ b/browser/config/mozconfigs/macosx64/l10n-mozconfig
@@ -1,5 +1,9 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
 ac_add_options --with-l10n-base=../../l10n-central
 ac_add_options --enable-official-branding
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --with-ccache
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -1,8 +1,10 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-signmar
 ENABLE_MARIONETTE=1
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
@@ -15,8 +17,10 @@ fi
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/l10n-mozconfig
+++ b/browser/config/mozconfigs/win32/l10n-mozconfig
@@ -1,10 +1,14 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-official-branding
 ac_add_options --with-l10n-base=../../l10n-central
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -1,8 +1,10 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
 # for pgo
 mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py'
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 ac_add_options --enable-profiling
@@ -24,8 +26,10 @@ fi
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/release
+++ b/browser/config/mozconfigs/win32/release
@@ -1,8 +1,10 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
 # for pgo
 mk_add_options MOZ_PGO=1
 mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py'
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-official-branding
@@ -21,8 +23,10 @@ fi
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -10,8 +10,10 @@ ENABLE_MARIONETTE=1
 export MOZILLA_OFFICIAL=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 . $topsrcdir/build/win64/mozconfig.vs2010
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -19,8 +19,10 @@ export MOZILLA_OFFICIAL=1
 export MOZ_TELEMETRY_REPORTING=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 . $topsrcdir/build/win64/mozconfig.vs2010
+
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/devtools/commandline/CmdCmd.jsm
+++ b/browser/devtools/commandline/CmdCmd.jsm
@@ -13,17 +13,17 @@ let prefSvc = "@mozilla.org/preferences-
 XPCOMUtils.defineLazyGetter(this, "prefBranch", function() {
   let prefService = Cc[prefSvc].getService(Ci.nsIPrefService);
   return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "console",
-                                  "resource:///modules/devtools/Console.jsm");
+                                  "resource://gre/modules/devtools/Console.jsm");
 
 const PREF_DIR = "devtools.commands.dir";
 
 /**
  * A place to store the names of the commands that we have added as a result of
  * calling refreshAutoCommands(). Used by refreshAutoCommands to remove the
  * added commands.
  */
--- a/browser/devtools/commandline/CmdCookie.jsm
+++ b/browser/devtools/commandline/CmdCookie.jsm
@@ -5,17 +5,17 @@
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 let EXPORTED_SYMBOLS = [ ];
 
 Cu.import("resource:///modules/devtools/gcli.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "console",
-                                  "resource:///modules/devtools/Console.jsm");
+                                  "resource://gre/modules/devtools/Console.jsm");
 
 // We should really be using nsICookieManager so we can read more than just the
 // key/value of cookies. The difficulty is filtering the cookies that are
 // relevant to the current page. See
 // https://github.com/firebug/firebug/blob/master/extension/content/firebug/cookies/cookieObserver.js#L123
 // For details on how this is done with Firebug
 
 /**
--- a/browser/devtools/highlighter/highlighter.jsm
+++ b/browser/devtools/highlighter/highlighter.jsm
@@ -143,28 +143,28 @@ Highlighter.prototype = {
 
     // The controlsBox will host the different interactive
     // elements of the highlighter (buttons, toolbars, ...).
     let controlsBox = this.chromeDoc.createElement("box");
     controlsBox.id = "highlighter-controls";
     this.highlighterContainer.appendChild(outlineContainer);
     this.highlighterContainer.appendChild(controlsBox);
 
-    stack.appendChild(this.highlighterContainer);
-
-    this.showOutline();
+    // Insert the highlighter right after the browser
+    stack.insertBefore(this.highlighterContainer, stack.childNodes[1]);
 
     this.buildInfobar(controlsBox);
 
     this.transitionDisabler = null;
     this.pageEventsMuter = null;
 
-    this.computeZoomFactor();
     this.unlock();
-    this.hide();
+
+    this.hidden = true;
+    this.show();
   },
 
   /**
    * Destroy the nodes. Remove listeners.
    */
   destroy: function Highlighter_destroy()
   {
     this.detachMouseListeners();
@@ -215,16 +215,20 @@ Highlighter.prototype = {
     }
 
     if (oldNode !== this.node) {
       this.updateInfobar();
     }
 
     this.invalidateSize(!!aScroll);
 
+    if (this._highlighting) {
+      this.showOutline();
+    }
+
     if (oldNode !== this.node) {
       this.emitEvent("nodeselected");
     }
   },
 
   /**
    * Notify that a pseudo-class lock was toggled on the highlighted element
    *
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -891,16 +891,20 @@ InspectorUI.prototype = {
   {
     if (!this.inspecting) {
       return;
     }
 
     this.inspectCommand.setAttribute("checked", "false");
 
     this.inspecting = false;
+
+    if (this.closing)
+      return;
+
     if (this.highlighter.getNode()) {
       this.select(this.highlighter.getNode(), true, !aPreventScroll);
     } else {
       this.select(null, true, true);
     }
 
     this.highlighter.lock();
     this._notifySelected();
--- a/browser/devtools/responsivedesign/responsivedesign.jsm
+++ b/browser/devtools/responsivedesign/responsivedesign.jsm
@@ -88,17 +88,17 @@ let presets = [
 function ResponsiveUI(aWindow, aTab)
 {
   this.mainWindow = aWindow;
   this.tab = aTab;
   this.tabContainer = aWindow.gBrowser.tabContainer;
   this.browser = aTab.linkedBrowser;
   this.chromeDoc = aWindow.document;
   this.container = aWindow.gBrowser.getBrowserContainer(this.browser);
-  this.stack = this.container.querySelector("[anonid=browserStack]");
+  this.stack = this.container.querySelector(".browserStack");
 
   // Try to load presets from prefs
   if (Services.prefs.prefHasUserValue("devtools.responsiveUI.presets")) {
     try {
       presets = JSON.parse(Services.prefs.getCharPref("devtools.responsiveUI.presets"));
     } catch(e) {
       // User pref is malformated.
       Cu.reportError("Could not parse pref `devtools.responsiveUI.presets`: " + e);
@@ -277,22 +277,22 @@ ResponsiveUI.prototype = {
    */
    unCheckMenus: function RUI_unCheckMenus() {
      this.chromeDoc.getElementById("Tools:ResponsiveUI").setAttribute("checked", "false");
    },
 
   /**
    * Build the toolbar and the resizers.
    *
-   * <vbox anonid="browserContainer"> From tabbrowser.xml
+   * <vbox class="browserContainer"> From tabbrowser.xml
    *  <toolbar class="devtools-toolbar devtools-responsiveui-toolbar">
    *    <menulist class="devtools-menulist"/> // presets
    *    <toolbarbutton tabindex="0" class="devtools-toolbarbutton" label="rotate"/> // rotate
    *  </toolbar>
-   *  <stack anonid="browserStack"> From tabbrowser.xml
+   *  <stack class="browserStack"> From tabbrowser.xml
    *    <browser/>
    *    <box class="devtools-responsiveui-resizehandle" bottom="0" right="0"/>
    *    <box class="devtools-responsiveui-resizebar" top="0" right="0"/>
    *  </stack>
    * </vbox>
    */
   buildUI: function RUI_buildUI() {
     // Toolbar
--- a/browser/devtools/tilt/test/head.js
+++ b/browser/devtools/tilt/test/head.js
@@ -56,24 +56,21 @@ const BEFORE_DESTROYED = Tilt.NOTIFICATI
 const DESTROYED = Tilt.NOTIFICATIONS.DESTROYED;
 const SHOWN = Tilt.NOTIFICATIONS.SHOWN;
 const HIDDEN = Tilt.NOTIFICATIONS.HIDDEN;
 const HIGHLIGHTING = Tilt.NOTIFICATIONS.HIGHLIGHTING;
 const UNHIGHLIGHTING = Tilt.NOTIFICATIONS.UNHIGHLIGHTING;
 const NODE_REMOVED = Tilt.NOTIFICATIONS.NODE_REMOVED;
 
 const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled");
-const INSP_ENABLED = Services.prefs.getBoolPref("devtools.inspector.enabled");
 
 
 function isTiltEnabled() {
-  let enabled = TILT_ENABLED && INSP_ENABLED;
-
-  info("Apparently, Tilt is" + (enabled ? "" : " not") + " enabled.");
-  return enabled;
+  info("Apparently, Tilt is" + (TILT_ENABLED ? "" : " not") + " enabled.");
+  return TILT_ENABLED;
 }
 
 function isWebGLSupported() {
   let supported = !TiltGL.isWebGLForceEnabled() &&
                    TiltGL.isWebGLSupported() &&
                    TiltGL.create3DContext(createCanvas());
 
   info("Apparently, WebGL is" + (supported ? "" : " not") + " supported.");
--- a/browser/extensions/Makefile.in
+++ b/browser/extensions/Makefile.in
@@ -2,34 +2,34 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEPTH      = @DEPTH@
 topsrcdir  = @top_srcdir@
 srcdir     = @srcdir@
 VPATH      = @srcdir@
 
-CHROMEDIR = $(call core_abspath,$(DIST))/bin/chrome
+CHROMEDIR = $(call core_abspath,$(FINAL_TARGET))/chrome
 
 include $(DEPTH)/config/autoconf.mk
 
 TEST_DIRS += pdfjs/test
 
 include $(topsrcdir)/config/rules.mk
 
 exclude_files = \
   test \
   install.rdf \
   bootstrap.js \
   icon.png \
   icon64.png \
   $(NULL)
 
-$(DIST)/bin/chrome/pdfjs.manifest: $(GLOBAL_DEPS)
+$(FINAL_TARGET)/chrome/pdfjs.manifest: $(GLOBAL_DEPS)
 	printf "manifest pdfjs/chrome.manifest" > $@
 
-libs:: $(DIST)/bin/chrome/pdfjs.manifest
+libs:: $(FINAL_TARGET)/chrome/pdfjs.manifest
 	$(PYTHON) $(topsrcdir)/config/nsinstall.py \
 	  $(srcdir)/pdfjs \
           $(foreach exclude,$(exclude_files), -X $(srcdir)/pdfjs/$(exclude)) \
-          $(DIST)/bin/chrome
+          $(FINAL_TARGET)/chrome
 	$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \
-	  $(DIST)/bin/chrome.manifest "manifest chrome/pdfjs.manifest"
+	  $(FINAL_TARGET)/chrome.manifest "manifest chrome/pdfjs.manifest"
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -193,27 +193,29 @@ langpack: langpack-$(AB_CD)
 # This is a generic target that will make a langpack, repack ZIP (+tarball)
 # builds, and repack an installer if applicable. It is called from the
 # 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)
 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)/" > \
-	  $(FINAL_TARGET)/updater.ini
+	  $(DIST)/bin/updater.ini
 else
 	cat $< | \
 	  sed -e "s/^InfoText=/Info=/" -e "s/^TitleText=/Title=/" | \
 	  sed -e "s/%MOZ_APP_DISPLAYNAME%/$(MOZ_APP_DISPLAYNAME)/" > \
-	  $(FINAL_TARGET)/updater.ini
+	  $(DIST)/bin/updater.ini
 endif
 endif
 
 ifdef MOZ_CRASHREPORTER
 libs:: crashreporter-override.ini
 	$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
 endif
 
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -2482,23 +2482,23 @@ html|*#gcli-output-frame {
 }
 
 .gcli-in-closebrace {
   color: hsl(0,0%,80%);
 }
 
 /* Responsive Mode */
 
-vbox[anonid=browserContainer][responsivemode] {
+.browserContainer[responsivemode] {
   background: #2a3643 url("chrome://browser/skin/devtools/responsive-background.png");
   box-shadow: 0 0 7px black inset;
   padding: 0 20px 20px 20px;
 }
 
-stack[anonid=browserStack][responsivemode] {
+.browserStack[responsivemode] {
   box-shadow: 0 0 7px black;
 }
 
 .devtools-responsiveui-toolbar {
   background: transparent;
   margin: 10px 0;
   padding: 0;
   box-shadow: none;
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -3201,23 +3201,23 @@ html|*#gcli-output-frame {
 }
 
 .gcli-in-closebrace {
   color: hsl(0,0%,80%);
 }
 
 /* Responsive Mode */
 
-vbox[anonid=browserContainer][responsivemode] {
+.browserContainer[responsivemode] {
   background: #2a3643 url("chrome://browser/skin/devtools/responsive-background.png");
   box-shadow: 0 0 7px black inset;
   padding: 0 20px 20px 20px;
 }
 
-stack[anonid=browserStack][responsivemode] {
+.browserStack[responsivemode] {
   box-shadow: 0 0 7px black;
 }
 
 .devtools-responsiveui-toolbar {
   background: transparent;
   margin: 10px 0;
   padding: 0;
   box-shadow: none;
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -3162,23 +3162,23 @@ html|*#gcli-output-frame {
 }
 
 .gcli-in-closebrace {
   color: hsl(0,0%,80%);
 }
 
 /* Responsive Mode */
 
-vbox[anonid=browserContainer][responsivemode] {
+.browserContainer[responsivemode] {
   background: #2a3643 url("chrome://browser/skin/devtools/responsive-background.png");
   box-shadow: 0 0 7px black inset;
   padding: 0 20px 20px 20px;
 }
 
-stack[anonid=browserStack][responsivemode] {
+.browserStack[responsivemode] {
   box-shadow: 0 0 7px black;
 }
 
 .devtools-responsiveui-toolbar {
   background: transparent;
   margin: 10px 0;
   padding: 0;
   box-shadow: none;
deleted file mode 100644
--- a/build/macosx/common
+++ /dev/null
@@ -1,12 +0,0 @@
-if [ -d "$topsrcdir/clang" ]; then
-    # mozilla-central based build
-    export CC=$topsrcdir/clang/bin/clang
-    export CXX=$topsrcdir/clang/bin/clang++
-elif [ -d "$topsrcdir/../clang" ]; then
-    # comm-central based build
-    export CC=$topsrcdir/../clang/bin/clang
-    export CXX=$topsrcdir/../clang/bin/clang++
-fi
-
-ac_add_options --enable-stdcxx-compat
-ac_add_options --with-ccache
new file mode 100644
--- /dev/null
+++ b/build/macosx/mozconfig.common
@@ -0,0 +1,18 @@
+# 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/.
+
+. "$topsrcdir/build/mozconfig.common"
+
+if [ -d "$topsrcdir/clang" ]; then
+    # mozilla-central based build
+    export CC=$topsrcdir/clang/bin/clang
+    export CXX=$topsrcdir/clang/bin/clang++
+elif [ -d "$topsrcdir/../clang" ]; then
+    # comm-central based build
+    export CC=$topsrcdir/../clang/bin/clang
+    export CXX=$topsrcdir/../clang/bin/clang++
+fi
+
+ac_add_options --enable-stdcxx-compat
+ac_add_options --with-ccache
--- a/build/macosx/mozconfig.leopard
+++ b/build/macosx/mozconfig.leopard
@@ -1,11 +1,11 @@
-. $topsrcdir/build/macosx/common
+. $topsrcdir/build/macosx/mozconfig.common
 
-# Mac builds don't nomally have to be handled as cross
+# Mac builds don't normally have to be handled as cross
 # compilation, but some of the libraries on the bots
 # (IDL for example) are built only for one arch.
 
 HOST_CC=$CC
 HOST_CXX=$CXX
 
 # These must be set for cross builds, and don't hurt straight builds.
 RANLIB=ranlib
--- a/build/macosx/universal/mozconfig.common
+++ b/build/macosx/universal/mozconfig.common
@@ -7,17 +7,17 @@ mk_add_options MOZ_UNIFY_BDATE=1
 mk_add_options MOZ_POSTFLIGHT_ALL+=build/macosx/universal/flight.mk
 
 # Note, the version (10) is used by libffi's configure.
 ac_add_app_options i386 --target=i386-apple-darwin10
 ac_add_app_options x86_64 --target=x86_64-apple-darwin10
 
 ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk
 
-. $topsrcdir/build/macosx/common
+. $topsrcdir/build/macosx/mozconfig.common
 
 # $MOZ_BUILD_APP is only defined when sourced by configure.  That's not a
 # problem, because the variables it affects only need to be set for
 # configure.
 if test -n "$MOZ_BUILD_APP" ; then
 if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
   TARGET_CPU=$MOZ_BUILD_APP
 
new file mode 100644
--- /dev/null
+++ b/build/mozconfig.common
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Common mozconfig for all users
+#
+# Add options to this file that will be inherited by all in-tree mozconfigs.
+# This is useful for eg try builds with nondefault options that apply to all
+# architectures, though note that if you want to override options set in
+# another mozconfig file, you'll need to use mozconfig.common.override instead
+# of this file.
new file mode 100644
--- /dev/null
+++ b/build/mozconfig.common.override
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Common mozconfig for all users
+#
+# Add options to this file that will be inherited by all in-tree mozconfigs.
+# This file is included at the *end* of the mozconfigs, and so may be used
+# to override anything done previously.
+#
+# The common expected usage is for try builds with nondefault options.
--- a/build/pymake/pymake/functions.py
+++ b/build/pymake/pymake/functions.py
@@ -766,19 +766,18 @@ class ShellFunction(Function):
     __slots__ = Function.__slots__
 
     def resolve(self, makefile, variables, fd, setting):
         #TODO: call this once up-front somewhere and save the result?
         shell, msys = util.checkmsyscompat()
         cline = self._arguments[0].resolvestr(makefile, variables, setting)
 
         log.debug("%s: running shell command '%s'" % (self.loc, cline))
-        if msys:
-            cline = [shell, "-c", cline]
-        p = subprocess.Popen(cline, env=makefile.env, shell=not msys,
+        cline = [shell, "-c", cline]
+        p = subprocess.Popen(cline, env=makefile.env, shell=False,
                              stdout=subprocess.PIPE, cwd=makefile.workdir)
         stdout, stderr = p.communicate()
 
         stdout = stdout.replace('\r\n', '\n')
         if stdout.endswith('\n'):
             stdout = stdout[:-1]
         stdout = stdout.replace('\n', ' ')
 
--- a/build/pymake/pymake/process.py
+++ b/build/pymake/pymake/process.py
@@ -83,18 +83,18 @@ def call(cline, env, cwd, loc, cb, conte
         else:
             argv = doglobbing(argv, cwd)
 
     if shellreason is not None:
         _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline)
         if msys:
             if len(cline) > 3 and cline[1] == ':' and cline[2] == '/':
                 cline = '/' + cline[0] + cline[2:]
-            cline = [shell, "-c", cline]
-        context.call(cline, shell=not msys, env=env, cwd=cwd, cb=cb, echo=echo,
+        cline = [shell, "-c", cline]
+        context.call(cline, shell=False, env=env, cwd=cwd, cb=cb, echo=echo,
                      justprint=justprint)
         return
 
     if not len(argv):
         cb(res=0)
         return
 
     if argv[0] == command.makepypath:
--- a/build/unix/mozconfig.linux
+++ b/build/unix/mozconfig.linux
@@ -1,2 +1,4 @@
+. "$topsrcdir/build/mozconfig.common"
+
 CC=/tools/gcc-4.5-0moz3/bin/gcc
 CXX=/tools/gcc-4.5-0moz3/bin/g++
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -15,25 +15,23 @@ include $(DEPTH)/config/autoconf.mk
 # headers, so that we can use it to set up the wrapped system headers.
 VISIBILITY_FLAGS =
 
 # STDCXX_COMPAT is not needed here, and will actually fail because
 # libstdc++-compat is not built yet.
 STDCXX_COMPAT =
 
 ifneq (WINNT,$(HOST_OS_ARCH))
-HOST_PROGRAM	= nsinstall$(HOST_BIN_SUFFIX)
+HOST_PROGRAM	= nsinstall_real$(HOST_BIN_SUFFIX)
 HOST_CSRCS	= nsinstall.c pathsub.c
 endif
 
-TARGETS		= $(HOST_PROGRAM) $(SIMPLE_PROGRAMS)
-
 ifndef CROSS_COMPILE
 ifdef USE_ELF_DYNSTR_GC
-TARGETS		+= elf-dynstr-gc
+export:: elf-dynstr-gc
 # Compiling the above will create dependency files.
 NEED_MDDEPDIR	= 1
 endif
 endif
 
 # IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have
 # a recursive rule for finding nsinstall and the Perl scripts.
 ifdef NSBUILDROOT
@@ -44,35 +42,46 @@ ifdef GNU_CC
 MODULE_OPTIMIZE_FLAGS = -O3
 endif
 
 include $(topsrcdir)/config/config.mk
 
 # Do not install util programs
 NO_INSTALL=1
 
+ifneq (WINNT,$(HOST_OS_ARCH))
+# Ensure nsinstall is atomically created
+nsinstall$(HOST_BIN_SUFFIX): $(HOST_PROGRAM)
+	cp $^ $@.tmp
+	mv $@.tmp $@
+
+NSINSTALL_FILES := nsinstall$(HOST_BIN_SUFFIX)
+NSINSTALL_DEST := $(DIST)/bin
+NSINSTALL_TARGET := export
+INSTALL_TARGETS += NSINSTALL
+endif
+
+HEADERS_FILES = \
+	$(DEPTH)/mozilla-config.h \
+	$(srcdir)/nsStaticComponents.h \
+	$(NULL)
+HEADERS_DEST := $(DIST)/include
+HEADERS_TARGET := export
+INSTALL_TARGETS += HEADERS
+
 include $(topsrcdir)/config/rules.mk
 
 HOST_CFLAGS += -DUNICODE -D_UNICODE
 
 ifeq ($(OS_CONFIG),SunOS4.1)
 NSPR_CFLAGS	+= -I$(srcdir)/../nsprpub/pr/include/md
 endif
 
-HEADERS = \
-	$(DEPTH)/mozilla-config.h \
-	$(srcdir)/nsStaticComponents.h \
-	$(NULL)
-
-export:: $(TARGETS) $(HEADERS)
-	$(INSTALL) $(IFLAGS1) $(HEADERS) $(DIST)/include
+export::
 	-$(RM) $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES)
-ifdef HOST_PROGRAM
-	$(INSTALL) $(HOST_PROGRAM) $(DIST)/bin
-endif
 
 # Generate a new buildid every time we "export" in config... that's only
 # supposed to be once per-build!
 export::
 ifdef MOZ_BUILD_DATE
 	printf "%s" $(MOZ_BUILD_DATE) > buildid
 else
 	$(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-buildid > buildid
--- a/config/makefiles/target_export.mk
+++ b/config/makefiles/target_export.mk
@@ -22,17 +22,17 @@ export_tier_%:
 #################
 ifdef PARALLEL_DIRS
 export:: $(PARALLEL_DIRS_export)
 
 $(PARALLEL_DIRS_export): %_export: %/Makefile
 	+@$(call SUBMAKE,export,$*)
 endif
 
-export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(XPIDLSRCS),$(IDL_DIR))
+export:: $(SUBMAKEFILES) $(MAKE_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 
 
 #
 # Rule to create list of libraries for final link
 #
 # todo: use pre-req deps rather than conditionals
--- a/config/makefiles/test/Makefile.in
+++ b/config/makefiles/test/Makefile.in
@@ -15,34 +15,31 @@ USE_AUTOTARGETS_MK  = 1
 MAKEUTILS_UNIT_TEST = 1
 include $(topsrcdir)/config/makefiles/makeutils.mk
 
 dir-ts = .deps/test
 check-arglist        = $(dir-ts)/arglist.ts
 check-autotargets    = $(dir-ts)/autotargets_mk.ts
 check-export-targets = $(dir-ts)/export-targets-mk.ts
 check-XinY           = $(dir-ts)/check_XinY_mk.ts
-check-xpidl          = $(dir-ts)/xpidl-mk.ts
 check-tests =\
   $(check-arglist) \
   $(check-autotargets) \
   $(check-export-targets) \
   $(check-XinY) \
-  $(check-xpidl) \
   $(NULL)
 
 
 ##------------------_##
 ##---]  TARGETS  [---##
 ##------------------_##
 all::
 
 clean:
 	$(RM) $(check-tests)
-	@$(MAKE) --no-print-directory -f $(srcdir)/check-xpidl.mk clean-xpidl topsrcdir=$(topsrcdir)
 
 ###########################################################################
 ## Logic processed at compile time so be selective about when to test
 ## $(MAKE) check VERBOSE=1
 ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #
 
 check-preqs =\
   $(call mkdir_deps,$(dir-ts)) \
@@ -119,28 +116,9 @@ check-export-targets-preqs=\
 
 # include then test
 checkup: $(eval include $(srcdir)/check-export-targets.mk)
 
 $(check-export-targets): $(check-export-targets-preqs)
 	@$(TOUCH) $@
 # </CHECK: export-targets.mk>
 
-###########################################################################
-##{ <CHECK: xpidl.mk>
-check-xpidl-preqs=\
-  $(call mkdir_deps,$(dir-ts)) \
-  $(topsrcdir)/config/config.mk \
-  $(topsrcdir)/config/makefiles/makeutils.mk \
-  $(topsrcdir)/config/makefiles/xpidl.mk \
-  $(srcdir)/check-xpidl.mk \
-  $(NULL)
-
-check-xpidl-args =\
-  "topsrcdir=$(topsrcdir)" \
-  "srcdir=$(srcdir)" \
-  $(NULL)
-$(check-xpidl): $(check-xpidl-preqs)
-	$(MAKE) -f $(srcdir)/check-xpidl.mk check-xpidl $(check-xpidl-args)
-	@$(TOUCH) $@
-#} </check-xpidl.mk>
-
 endif #} findstring MAKECMDGOAL
deleted file mode 100644
--- a/config/makefiles/test/check-xpidl.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- makefile -*-
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-# You can obtain one at http://mozilla.org/MPL/2.0/.
-
-ifdef VERBOSE
-  $(warning loading test)
-endif
-
-# Limit scope, we only need install_cmd= for testing
-INCLUDED_AUTOCONF_MK = 1
-include $(topsrcdir)/config/config.mk
-
-USE_AUTOTARGETS_MK = 1
-include $(topsrcdir)/config/makefiles/makeutils.mk
-
-basedir  = blah
-DIST     = $(basedir)/dist
-DI       = $(DIST)/include
-IDL_DIR  = $(basedir)/idl
-INSTALL := cp
-
-XPIDLSRCS = $(srcdir)/check-xpidl.mk
-
-include $(topsrcdir)/config/makefiles/xpidl.mk
-
-
-$(call requiredfunction,topsrcdir)
-$(call requiredfunction,XPIDL_GEN_DIR)
-
-HIDE=@
-check-xpidl: xpidl-install-src xpidl-install-headers
-	$(HIDE)test -d $(DIST)                   || exit 90
-	$(HIDE)test -f $(DI)/check-xpidl.mk      || exit 91
-	$(HIDE)test -f $(IDL_DIR)/check-xpidl.mk || exit 92
-
-# Declare targets to avoid including rules.mk
-$(DI) $(IDL_DIR):
-	mkdir -p $@
-
-clean-xpidl:
-	$(RM) -r $(basedir)
deleted file mode 100644
--- a/config/makefiles/xpidl.mk
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- makefile -*-
-# vim:set ts=8 sw=8 sts=8 noet:
-#
-# 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/.
-#
-
-# Always declared, general use by:
-# js/xpconnect/tests/idl/Makefile.in:libs
-# toolkit/crashreporter/test/Makefile.in
-XPIDL_GEN_DIR ?= _xpidlgen
-GARBAGE_DIRS  += $(XPIDL_GEN_DIR)
-
-
-###########################################################################
-## Conditional logic
-###########################################################################
-ifndef INCLUDED_XPIDL_MK #{
-  INCLUDED_XPIDL_MK = 1
-
-  ifneq (,$(XPIDLSRCS)) #{
-
-    ifndef NO_DIST_INSTALL #{
-      _xpidl-todo_ += xpidl-install-src
-      _xpidl-todo_ += xpidl-install-headers
-    endif #}
-
-  endif #} XPIDLSRCS
-
-  export:: $(_xpidl-todo_)
-
-  $(call requiredfunction,mkdir_deps)
-endif #} INCLUDED_XPIDL_MK
-
-
-###########################################################################
-## processing targets
-###########################################################################
-ifdef _xpidl-todo_ #{
-
-$(call requiredfunction,install_cmd)
-
-## Logic batch #1
-xpidl-install-src-preqs=\
-  $(XPIDLSRCS) \
-  $(call mkdir_deps,$(IDL_DIR)) \
-  $(NULL)
-
-xpidl-install-src: $(xpidl-install-src-preqs)
-	$(call install_cmd,$(IFLAGS1) $(foreach val,$^,$(call mkdir_stem,$(val))))
-
-xpidl-install-headers-preqs =\
-  $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) \
-  $(call mkdir_deps,$(DIST)/include) \
-  $(NULL)
-xpidl-install-headers: $(xpidl-install-headers-preqs)
-	$(call install_cmd,$(IFLAGS1) $(foreach val,$^,$(call mkdir_stem,$(val))))
-
-endif #} _xpidl-todo_
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -21,20 +21,22 @@ endif
 ifndef INCLUDED_VERSION_MK
 include $(topsrcdir)/config/version.mk
 endif
 
 USE_AUTOTARGETS_MK = 1
 include $(topsrcdir)/config/makefiles/makeutils.mk
 
 ifdef SDK_XPIDLSRCS
-XPIDLSRCS += $(SDK_XPIDLSRCS)
+_EXTRA_XPIDLSRCS := $(filter-out $(XPIDLSRCS),$(SDK_XPIDLSRCS))
+XPIDLSRCS += $(_EXTRA_XPIDLSRCS)
 endif
 ifdef SDK_HEADERS
-EXPORTS += $(SDK_HEADERS)
+_EXTRA_EXPORTS := $(filter-out $(EXPORTS),$(SDK_HEADERS))
+EXPORTS += $(_EXTRA_EXPORTS)
 endif
 
 REPORT_BUILD = $(info $(notdir $<))
 
 ifeq ($(OS_ARCH),OS2)
 EXEC			=
 else
 EXEC			= exec
@@ -1154,25 +1156,29 @@ ifneq ($(XPI_NAME),)
 $(FINAL_TARGET):
 	$(NSINSTALL) -D $@
 
 export:: $(FINAL_TARGET)
 endif
 
 ifndef NO_DIST_INSTALL
 ifneq (,$(EXPORTS))
-export:: $(EXPORTS)
-	$(call install_cmd,$(IFLAGS1) $^ $(DIST)/include)
+EXPORTS_FILES := $(EXPORTS)
+EXPORTS_DEST := $(DIST)/include
+EXPORTS_TARGET := export
+INSTALL_TARGETS += EXPORTS
 endif
 endif # NO_DIST_INSTALL
 
 define EXPORT_NAMESPACE_RULE
 ifndef NO_DIST_INSTALL
-export:: $(EXPORTS_$(namespace))
-	$(call install_cmd,$(IFLAGS1) $$^ $(DIST)/include/$(namespace))
+EXPORTS_$(namespace)_FILES := $$(EXPORTS_$(namespace))
+EXPORTS_$(namespace)_DEST := $$(DIST)/include/$(namespace)
+EXPORTS_$(namespace)_TARGET := export
+INSTALL_TARGETS += EXPORTS_$(namespace)
 endif # NO_DIST_INSTALL
 endef
 
 $(foreach namespace,$(EXPORTS_NAMESPACES),$(eval $(EXPORT_NAMESPACE_RULE)))
 
 ################################################################################
 # Copy each element of PREF_JS_EXPORTS
 
@@ -1198,24 +1204,22 @@ PREF_JS_EXPORTS_FLAGS := $(PREF_PPFLAGS)
 PP_TARGETS += PREF_JS_EXPORTS
 endif
 endif
 
 ################################################################################
 # Copy each element of AUTOCFG_JS_EXPORTS to $(FINAL_TARGET)/defaults/autoconfig
 
 ifneq ($(AUTOCFG_JS_EXPORTS),)
-$(FINAL_TARGET)/defaults/autoconfig::
-	$(NSINSTALL) -D $@
-
 ifndef NO_DIST_INSTALL
-export:: $(AUTOCFG_JS_EXPORTS) $(FINAL_TARGET)/defaults/autoconfig
-	$(call install_cmd,$(IFLAGS1) $^)
+AUTOCFG_JS_EXPORTS_FILES := $(AUTOCFG_JS_EXPORTS)
+AUTOCFG_JS_EXPORTS_DEST := $(FINAL_TARGET)/defaults/autoconfig
+AUTOCFG_JS_EXPORTS_TARGET := export
+INSTALL_TARGETS += AUTOCFG_JS_EXPORTS
 endif
-
 endif
 
 ################################################################################
 # Export the elements of $(XPIDLSRCS)
 # generating .h and .xpt files and moving them to the appropriate places.
 
 ifneq ($(XPIDLSRCS),) #{
 
@@ -1266,48 +1270,46 @@ xpidl-preqs = \
 	  $(LIBXUL_DIST)/sdk/bin/typelib.py $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
 $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS)
 	$(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS))
 endif # XPIDL_MODULE.xpt != XPIDLSRCS
 
-libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
 ifndef NO_DIST_INSTALL
-	$(call install_cmd,$(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components)
+XPIDL_MODULE_FILES := $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
+XPIDL_MODULE_DEST := $(FINAL_TARGET)/components
+INSTALL_TARGETS += XPIDL_MODULE
+
 ifndef NO_INTERFACES_MANIFEST
 libs:: $(call mkdir_deps,$(FINAL_TARGET)/components)
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt"
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
 endif
 endif
 
 GARBAGE_DIRS		+= $(XPIDL_GEN_DIR)
 
+ifndef NO_DIST_INSTALL
+XPIDL_HEADERS_FILES := $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS))
+XPIDL_HEADERS_DEST := $(DIST)/include
+XPIDL_HEADERS_TARGET := export
+INSTALL_TARGETS += XPIDL_HEADERS
+
+XPIDLSRCS_FILES := $(XPIDLSRCS)
+XPIDLSRCS_DEST := $(IDL_DIR)
+XPIDLSRCS_TARGET := export-idl
+INSTALL_TARGETS += XPIDLSRCS
+
+export:: export-idl
+endif
 endif #} XPIDLSRCS
 
-
-ifndef INCLUDED_XPIDL_MK
-  include $(topsrcdir)/config/makefiles/xpidl.mk
-endif
-
-
-# General rules for exporting idl files.
-$(IDL_DIR):
-	$(NSINSTALL) -D $@
-
 export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
-
-ifneq ($(XPIDLSRCS),)
-ifndef NO_DIST_INSTALL
-export-idl:: $(XPIDLSRCS) $(IDL_DIR)
-	$(call install_cmd,$(IFLAGS1) $^)
-endif
-endif
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 
 ################################################################################
 # Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
 ifneq (,$(filter %.js,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)))
 ifeq (,$(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)))
@@ -1315,17 +1317,19 @@ ifndef NO_JS_MANIFEST
 $(error .js component without matching .manifest. See https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0)
 endif
 endif
 endif
 
 ifdef EXTRA_COMPONENTS
 libs:: $(EXTRA_COMPONENTS)
 ifndef NO_DIST_INSTALL
-	$(call install_cmd,$(IFLAGS1) $^ $(FINAL_TARGET)/components)
+EXTRA_COMPONENTS_FILES := $(EXTRA_COMPONENTS)
+EXTRA_COMPONENTS_DEST := $(FINAL_TARGET)/components
+INSTALL_TARGETS += EXTRA_COMPONENTS
 endif
 
 endif
 
 ifdef EXTRA_PP_COMPONENTS
 ifndef NO_DIST_INSTALL
 EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components
 PP_TARGETS += EXTRA_PP_COMPONENTS
@@ -1339,21 +1343,21 @@ libs:: $(call mkdir_deps,$(FINAL_TARGET)
 endif
 
 ################################################################################
 # Copy each element of EXTRA_JS_MODULES to JS_MODULES_PATH, or
 # $(FINAL_TARGET)/modules if that isn't defined.
 JS_MODULES_PATH ?= $(FINAL_TARGET)/modules
 
 ifdef EXTRA_JS_MODULES
-libs:: $(EXTRA_JS_MODULES)
 ifndef NO_DIST_INSTALL
-	$(call install_cmd,$(IFLAGS1) $^ $(JS_MODULES_PATH))
+EXTRA_JS_MODULES_FILES := $(EXTRA_JS_MODULES)
+EXTRA_JS_MODULES_DEST := $(JS_MODULES_PATH)
+INSTALL_TARGETS += EXTRA_JS_MODULES
 endif
-
 endif
 
 ifdef EXTRA_PP_JS_MODULES
 ifndef NO_DIST_INSTALL
 EXTRA_PP_JS_MODULES_PATH := $(JS_MODULES_PATH)
 PP_TARGETS += EXTRA_PP_JS_MODULES
 endif
 endif
@@ -1365,46 +1369,41 @@ endif
 # objdir/_tests/modules/. If TESTING_JS_MODULE_DIR is defined, that path
 # wlll be appended to the output directory.
 
 ifdef TESTING_JS_MODULES
 testmodulesdir = $(DEPTH)/_tests/modules/$(TESTING_JS_MODULE_DIR)
 
 GENERATED_DIRS += $(testmodulesdir)
 
-libs:: $(TESTING_JS_MODULES)
 ifndef NO_DIST_INSTALL
-	$(call install_cmd,$(IFLAGS) $^ $(testmodulesdir))
+TESTING_JS_MODULES_FILES := $(TESTING_JS_MODULES)
+TESTING_JS_MODULES_DEST := $(testmodulesdir)
+INSTALL_TARGETS += TESTING_JS_MODULES
 endif
 
 endif
 
 ################################################################################
 # SDK
 
 ifneq (,$(SDK_LIBRARY))
-$(SDK_LIB_DIR)::
-	$(NSINSTALL) -D $@
-
 ifndef NO_DIST_INSTALL
-libs:: $(SDK_LIBRARY) $(SDK_LIB_DIR)
-	$(call install_cmd,$(IFLAGS2) $^)
+SDK_LIBRARY_FILES := $(SDK_LIBRARY)
+SDK_LIBRARY_DEST := $(SDK_LIB_DIR)
+INSTALL_TARGETS += SDK_LIBRARY
 endif
-
 endif # SDK_LIBRARY
 
 ifneq (,$(strip $(SDK_BINARY)))
-$(SDK_BIN_DIR)::
-	$(NSINSTALL) -D $@
-
 ifndef NO_DIST_INSTALL
-libs:: $(SDK_BINARY) $(SDK_BIN_DIR)
-	$(call install_cmd,$(IFLAGS2) $^)
+SDK_BINARY_FILES := $(SDK_BINARY)
+SDK_BINARY_DEST := $(SDK_BIN_DIR)
+INSTALL_TARGETS += SDK_BINARY
 endif
-
 endif # SDK_BINARY
 
 ################################################################################
 # CHROME PACKAGING
 
 JAR_MANIFEST := $(srcdir)/jar.mn
 
 chrome::
@@ -1530,61 +1529,78 @@ TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS)
 	$(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS)
 endif
 endif
 
 ################################################################################
 # Install/copy rules
 #
 # The INSTALL_TARGETS variable contains a list of all install target
-# categories. Each category defines a list of files, an install destination,
-# and whether the files are executables or not.
+# categories. Each category defines a list of files and executables, and an
+# install destination,
 #
 # FOO_FILES := foo bar
 # FOO_EXECUTABLES := baz
 # FOO_DEST := target_path
 # INSTALL_TARGETS += FOO
+#
+# Additionally, a FOO_TARGET variable may be added to indicate the target for
+# which the files and executables are installed. Default is "libs".
+
+# If we're using binary nsinstall and it's not built yet, fallback to python nsinstall.
+ifneq (,$(filter $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX),$(install_cmd)))
+nsinstall_is_usable = $(if $(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)),$(eval nsinstall_is_usable := yes)yes)
+
+define install_cmd_override
+$(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY)) $$(1)
+endef
+endif
+
 define install_file_template
-libs:: $(2)/$(notdir $(1))
+$(or $(3),libs):: $(2)/$(notdir $(1))
+$(call install_cmd_override,$(2)/$(notdir $(1)))
 $(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2))
-	$(INSTALL) $(3) $$< $${@D}
+	$$(call install_cmd,$(4) $$< $${@D})
 endef
 $(foreach category,$(INSTALL_TARGETS),\
   $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\
   $(foreach file,$($(category)_FILES),\
-    $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS1)))\
+    $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS1)))\
   )\
   $(foreach file,$($(category)_EXECUTABLES),\
-    $(eval $(call install_file_template,$(file),$($(category)_DEST),$(IFLAGS2)))\
+    $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS2)))\
   )\
 )
 
 ################################################################################
 # Preprocessing rules
 #
 # The PP_TARGETS variable contains a list of all preprocessing target
 # categories. Each category defines a target path, and optional extra flags
 # like the following:
 #
 # FOO_PATH := target_path
 # FOO_FLAGS := -Dsome_flag
 # PP_TARGETS += FOO
+#
+# Additionally, a FOO_TARGET variable may be added to indicate the target for
+# which the files and executables are installed. Default is "libs".
 
 # preprocess_file_template defines preprocessing rules.
 # $(call preprocess_file_template, source_file, target_path, extra_flags)
 define preprocess_file_template
 $(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2)) $$(GLOBAL_DEPS)
 	$$(RM) $$@
-	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(3) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@
-libs:: $(2)/$(notdir $(1))
+	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@
+$(or $(3),libs):: $(2)/$(notdir $(1))
 endef
 
 $(foreach category,$(PP_TARGETS),\
   $(foreach file,$($(category)),\
-    $(eval $(call preprocess_file_template,$(file),$($(category)_PATH),$($(category)_FLAGS)))\
+    $(eval $(call preprocess_file_template,$(file),$($(category)_PATH),$($(category)_TARGET),$($(category)_FLAGS)))\
    )\
  )
 
 ################################################################################
 # Special gmake rules.
 ################################################################################
 
 
--- a/configure.in
+++ b/configure.in
@@ -3849,48 +3849,49 @@ else
         NSPR_CFLAGS=`"${LIBXUL_DIST}"/sdk/bin/nspr-config --prefix="${LIBXUL_DIST}" --includedir="${LIBXUL_DIST}/include/nspr" --cflags`
         NSPR_LIBS=`"${LIBXUL_DIST}"/sdk/bin/nspr-config --prefix="${LIBXUL_DIST}" --libdir="${LIBXUL_DIST}"/lib --libs`
     fi
 fi
 
 dnl system libevent Support
 dnl ========================================================
 MOZ_ARG_WITH_STRING(system-libevent,
-[  --with-system-libevent=[PFX]
+[  --with-system-libevent[=PFX]
                           Use system libevent [installed at prefix PFX]],
     LIBEVENT_DIR=$withval)
 
 _SAVE_CFLAGS=$CFLAGS
 _SAVE_LDFLAGS=$LDFLAGS
 _SAVE_LIBS=$LIBS
 if test -z "$LIBEVENT_DIR" -o "$LIBEVENT_DIR" = no; then
     MOZ_NATIVE_LIBEVENT=
+elif test "$LIBEVENT_DIR" = yes; then
+    PKG_CHECK_MODULES(MOZ_LIBEVENT, libevent,
+        MOZ_NATIVE_LIBEVENT=1,
+        AC_MSG_ERROR([--with-system-libevent requested but libevent package not found]))
 else
-    if test "${LIBEVENT_DIR}" = "yes"; then
-        LIBEVENT_DIR=/usr
-    fi
     CFLAGS="-I${LIBEVENT_DIR}/include $CFLAGS"
     LDFLAGS="-L${LIBEVENT_DIR}/lib $LDFLAGS"
     MOZ_CHECK_HEADER(event.h,
         [if test ! -f "${LIBEVENT_DIR}/include/event.h"; then
              AC_MSG_ERROR([event.h found, but is not in ${LIBEVENT_DIR}/include])
          fi],
         AC_MSG_ERROR([--with-system-libevent requested but event.h not found]))
     AC_CHECK_LIB(event, event_init,
                  [MOZ_NATIVE_LIBEVENT=1
-                  MOZ_LIBEVENT_INCLUDES="${LIBEVENT_DIR}/include"
+                  MOZ_LIBEVENT_CFLAGS="-I${LIBEVENT_DIR}/include"
                   MOZ_LIBEVENT_LIBS="-L${LIBEVENT_DIR}/lib -levent"],
-                 [MOZ_NATIVE_LIBEVENT= MOZ_LIBEVENT_INCLUDES= MOZ_LIBEVENT_LIBS=])
+                 [MOZ_NATIVE_LIBEVENT= MOZ_LIBEVENT_CFLAGS= MOZ_LIBEVENT_LIBS=])
 fi
 CFLAGS=$_SAVE_CFLAGS
 LDFLAGS=$_SAVE_LDFLAGS
 LIBS=$_SAVE_LIBS
 
 AC_SUBST(MOZ_NATIVE_LIBEVENT)
-AC_SUBST(MOZ_LIBEVENT_INCLUDES)
+AC_SUBST(MOZ_LIBEVENT_CFLAGS)
 AC_SUBST(MOZ_LIBEVENT_LIBS)
 
 dnl ========================================================
 dnl = If NSS was not detected in the system,
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
--- a/content/base/src/FileIOObject.cpp
+++ b/content/base/src/FileIOObject.cpp
@@ -160,17 +160,17 @@ FileIOObject::DoOnStartRequest(nsIReques
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 FileIOObject::OnDataAvailable(nsIRequest *aRequest,
                               nsISupports *aContext,
                               nsIInputStream *aInputStream,
-                              uint32_t aOffset,
+                              uint64_t aOffset,
                               uint32_t aCount)
 {
   nsresult rv;
   rv = DoOnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mTransferred += aCount;
 
--- a/content/base/src/FileIOObject.h
+++ b/content/base/src/FileIOObject.h
@@ -63,17 +63,17 @@ protected:
   // special handling
   NS_IMETHOD DoOnStartRequest(nsIRequest *aRequest, nsISupports *aContext);
   // for onStopRequest
   NS_IMETHOD DoOnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
                              nsresult aStatus, nsAString& aSuccessEvent,
                              nsAString& aTerminationEvent) = 0;
   // and for onDataAvailable
   NS_IMETHOD DoOnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
-                               nsIInputStream *aInputStream, uint32_t aOffset,
+                               nsIInputStream *aInputStream, uint64_t aOffset,
                                uint32_t aCount) = 0;
 
   void StartProgressEventTimer();
   void ClearProgressEventTimer();
   void DispatchError(nsresult rv, nsAString& finalEvent);
   nsresult DispatchProgressEvent(const nsAString& aType);
 
   nsCOMPtr<nsITimer> mProgressNotifier;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3593,31 +3593,49 @@ nsContentUtils::ConvertStringFromCharset
 
   nsCOMPtr<nsIUnicodeDecoder> decoder;
   rv = ccm->GetUnicodeDecoder(PromiseFlatCString(aCharset).get(),
                               getter_AddRefs(decoder));
   if (NS_FAILED(rv))
     return rv;
 
   nsPromiseFlatCString flatInput(aInput);
-  int32_t srcLen = flatInput.Length();
-  int32_t dstLen;
-  rv = decoder->GetMaxLength(flatInput.get(), srcLen, &dstLen);
+  int32_t length = flatInput.Length();
+  int32_t outLen;
+  rv = decoder->GetMaxLength(flatInput.get(), length, &outLen);
   if (NS_FAILED(rv))
     return rv;
 
-  PRUnichar *ustr = (PRUnichar *)nsMemory::Alloc((dstLen + 1) *
+  PRUnichar *ustr = (PRUnichar *)nsMemory::Alloc((outLen + 1) *
                                                  sizeof(PRUnichar));
   if (!ustr)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  rv = decoder->Convert(flatInput.get(), &srcLen, ustr, &dstLen);
-  if (NS_SUCCEEDED(rv)) {
+  const char* data = flatInput.get();
+  aOutput.Truncate();
+  for (;;) {
+    int32_t srcLen = length;
+    int32_t dstLen = outLen;
+    rv = decoder->Convert(data, &srcLen, ustr, &dstLen);
+    // Convert will convert the input partially even if the status
+    // indicates a failure.
     ustr[dstLen] = 0;
-    aOutput.Assign(ustr, dstLen);
+    aOutput.Append(ustr, dstLen);
+    if (rv != NS_ERROR_ILLEGAL_INPUT) {
+      break;
+    }
+    // Emit a decode error manually because some decoders
+    // do not support kOnError_Recover (bug 638379)
+    if (srcLen == -1) {
+      decoder->Reset();
+    } else {
+      data += srcLen + 1;
+      length -= srcLen + 1;
+      aOutput.Append(static_cast<PRUnichar>(0xFFFD));
+    }
   }
 
   nsMemory::Free(ustr);
   return rv;
 }
 
 /* static */
 bool
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -609,17 +609,17 @@ nsCORSListenerProxy::OnStopRequest(nsIRe
   mNewRedirectChannel = nullptr;
   return rv;
 }
 
 NS_IMETHODIMP
 nsCORSListenerProxy::OnDataAvailable(nsIRequest* aRequest,
                                      nsISupports* aContext, 
                                      nsIInputStream* aInputStream,
-                                     uint32_t aOffset,
+                                     uint64_t aOffset,
                                      uint32_t aCount)
 {
   if (!mRequestApproved) {
     return NS_ERROR_DOM_BAD_URI;
   }
   return mOuterListener->OnDataAvailable(aRequest, aContext, aInputStream,
                                          aOffset, aCount);
 }
@@ -1001,17 +1001,17 @@ nsCORSPreflightListener::OnStopRequest(n
 }
 
 /** nsIStreamListener methods **/
 
 NS_IMETHODIMP
 nsCORSPreflightListener::OnDataAvailable(nsIRequest *aRequest,
                                          nsISupports *ctxt,
                                          nsIInputStream *inStr,
-                                         uint32_t sourceOffset,
+                                         uint64_t sourceOffset,
                                          uint32_t count)
 {
   uint32_t totalRead;
   return inStr->ReadSegments(NS_DiscardSegment, nullptr, count, &totalRead);
 }
 
 NS_IMETHODIMP
 nsCORSPreflightListener::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -281,24 +281,27 @@ ReadFuncBinaryString(nsIInputStream* in,
 
   return NS_OK;
 }
 
 nsresult
 nsDOMFileReader::DoOnDataAvailable(nsIRequest *aRequest,
                                    nsISupports *aContext,
                                    nsIInputStream *aInputStream,
-                                   uint32_t aOffset,
+                                   uint64_t aOffset,
                                    uint32_t aCount)
 {
   if (mDataFormat == FILE_AS_BINARY) {
     //Continuously update our binary string as data comes in
     NS_ASSERTION(mResult.Length() == aOffset,
                  "unexpected mResult length");
     uint32_t oldLen = mResult.Length();
+    if (uint64_t(oldLen) + aCount > PR_UINT32_MAX)
+      return NS_ERROR_OUT_OF_MEMORY;
+
     PRUnichar *buf = nullptr;
     mResult.GetMutableData(&buf, oldLen + aCount, fallible_t());
     NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
 
     uint32_t bytesRead = 0;
     aInputStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount,
                                &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
@@ -306,16 +309,20 @@ nsDOMFileReader::DoOnDataAvailable(nsIRe
   else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     uint32_t bytesRead = 0;
     aInputStream->Read((char*)JS_GetArrayBufferData(mResultArrayBuffer, NULL) + aOffset,
                        aCount, &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
   }
   else {
     //Update memory buffer to reflect the contents of the file
+    if (aOffset + aCount > PR_UINT32_MAX) {
+      // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
     mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
     NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
 
     uint32_t bytesRead = 0;
     aInputStream->Read(mFileData + aOffset, aCount, &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
 
     mDataLen += aCount;
--- a/content/base/src/nsDOMFileReader.h
+++ b/content/base/src/nsDOMFileReader.h
@@ -52,17 +52,17 @@ public:
                         uint32_t argc, jsval* argv);
 
   // FileIOObject overrides
   NS_IMETHOD DoAbort(nsAString& aEvent);
   NS_IMETHOD DoOnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
                              nsresult aStatus, nsAString& aSuccessEvent,
                              nsAString& aTerminationEvent);
   NS_IMETHOD DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
-                               nsIInputStream* aInputStream, uint32_t aOffset,
+                               nsIInputStream* aInputStream, uint64_t aOffset,
                                uint32_t aCount);
 
   nsresult Init();
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsDOMFileReader,
                                                          FileIOObject)
   void RootResultArrayBuffer();
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1018,17 +1018,17 @@ nsExternalResourceMap::PendingLoad::Setu
   newLoadGroup.forget(aLoadGroup);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsExternalResourceMap::PendingLoad::OnDataAvailable(nsIRequest* aRequest,
                                                     nsISupports* aContext,
                                                     nsIInputStream* aStream,
-                                                    uint32_t aOffset,
+                                                    uint64_t aOffset,
                                                     uint32_t aCount)
 {
   NS_PRECONDITION(mTargetListener, "Shouldn't be getting called!");
   if (mDisplayDocument->ExternalResourceMap().HaveShutDown()) {
     return NS_BINDING_ABORTED;
   }
   return mTargetListener->OnDataAvailable(aRequest, aContext, aStream, aOffset,
                                           aCount);
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -532,17 +532,17 @@ nsEventSource::StreamReaderFunc(nsIInput
   *aWriteCount = aCount;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventSource::OnDataAvailable(nsIRequest *aRequest,
                                nsISupports *aContext,
                                nsIInputStream *aInputStream,
-                               uint32_t aOffset,
+                               uint64_t aOffset,
                                uint32_t aCount)
 {
   NS_ENSURE_ARG_POINTER(aInputStream);
 
   nsresult rv = CheckHealthOfRequestCallback(aRequest);
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t totalRead;
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -86,16 +86,20 @@
 #include "nsIAppsService.h"
 
 #include "jsapi.h"
 #include "nsHTMLIFrameElement.h"
 #include "nsSandboxFlags.h"
 
 #include "mozilla/dom/StructuredCloneUtils.h"
 
+#ifdef MOZ_XUL
+#include "nsXULPopupManager.h"
+#endif
+
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 typedef FrameMetrics::ViewID ViewID;
 
 class nsAsyncDocShellDestroyer : public nsRunnable
 {
@@ -301,16 +305,17 @@ nsFrameLoader::nsFrameLoader(Element* aO
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
   , mDelayRemoteDialogs(false)
   , mRemoteBrowserShown(false)
   , mRemoteFrame(false)
   , mClipSubdocument(true)
   , mClampScrollPosition(true)
   , mRemoteBrowserInitialized(false)
+  , mObservingOwnerContent(false)
   , mCurrentRemoteFrame(nullptr)
   , mRemoteBrowser(nullptr)
   , mRenderMode(RENDER_MODE_DEFAULT)
   , mEventMode(EVENT_MODE_NORMAL_DISPATCH)
 {
 }
 
 nsFrameLoader*
@@ -652,52 +657,47 @@ SetTreeOwnerAndChromeEventHandlerOnDocsh
     aItem->GetChildAt(i, getter_AddRefs(item));
     SetTreeOwnerAndChromeEventHandlerOnDocshellTree(item, aOwner, aHandler);
   }
 }
 
 /**
  * Set the type of the treeitem and hook it up to the treeowner.
  * @param aItem the treeitem we're working with
- * @param aOwningContent the content node that owns aItem
  * @param aTreeOwner the relevant treeowner; might be null
  * @param aParentType the nsIDocShellTreeItem::GetType of our parent docshell
  * @param aParentNode if non-null, the docshell we should be added as a child to
  *
  * @return whether aItem is top-level content
  */
-static bool
-AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, nsIContent* aOwningContent,
-                       nsIDocShellTreeOwner* aOwner, int32_t aParentType,
-                       nsIDocShellTreeNode* aParentNode)
+bool
+nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
+                                      nsIDocShellTreeOwner* aOwner,
+                                      int32_t aParentType,
+                                      nsIDocShellTreeNode* aParentNode)
 {
   NS_PRECONDITION(aItem, "Must have docshell treeitem");
-  NS_PRECONDITION(aOwningContent, "Must have owning content");
+  NS_PRECONDITION(mOwnerContent, "Must have owning content");
   
   nsAutoString value;
   bool isContent = false;
-
-  if (aOwningContent->IsXUL()) {
-      aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
-  } else {
-      aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::mozframetype, value);
-  }
+  mOwnerContent->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
 
   // we accept "content" and "content-xxx" values.
   // at time of writing, we expect "xxx" to be "primary" or "targetable", but
   // someday it might be an integer expressing priority or something else.
 
   isContent = value.LowerCaseEqualsLiteral("content") ||
     StringBeginsWith(value, NS_LITERAL_STRING("content-"),
                      nsCaseInsensitiveStringComparator());
 
   // Force mozbrowser frames to always be typeContent, even if the
   // mozbrowser interfaces are disabled.
   nsCOMPtr<nsIDOMMozBrowserFrame> mozbrowser =
-    do_QueryInterface(aOwningContent);
+    do_QueryInterface(mOwnerContent);
   if (mozbrowser) {
     bool isMozbrowser = false;
     mozbrowser->GetMozbrowser(&isMozbrowser);
     isContent |= isMozbrowser;
   }
 
   if (isContent) {
     // The web shell's type is content.
@@ -720,16 +720,18 @@ AddTreeItemToTreeOwner(nsIDocShellTreeIt
   if (aParentType == nsIDocShellTreeItem::typeChrome && isContent) {
     retval = true;
 
     bool is_primary = value.LowerCaseEqualsLiteral("content-primary");
 
     if (aOwner) {
       bool is_targetable = is_primary ||
         value.LowerCaseEqualsLiteral("content-targetable");
+      mOwnerContent->AddMutationObserver(this);
+      mObservingOwnerContent = true;
       aOwner->ContentShellAdded(aItem, is_primary, is_targetable, value);
     }
   }
 
   return retval;
 }
 
 static bool
@@ -1200,36 +1202,38 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   otherParentItem->AddChild(ourTreeItem);
 
   // Restore the correct treeowners
   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourTreeItem, otherOwner,
                                                   otherChromeEventHandler);
   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherTreeItem, ourOwner,
                                                   ourChromeEventHandler);
 
-  AddTreeItemToTreeOwner(ourTreeItem, otherContent, otherOwner,
-                         otherParentType, nullptr);
-  AddTreeItemToTreeOwner(otherTreeItem, ourContent, ourOwner, ourParentType,
-                         nullptr);
+  // Switch the owner content before we start calling AddTreeItemToTreeOwner.
+  // Note that we rely on this to deal with setting mObservingOwnerContent to
+  // false and calling RemoveMutationObserver as needed.
+  SetOwnerContent(otherContent);
+  aOther->SetOwnerContent(ourContent);
+
+  AddTreeItemToTreeOwner(ourTreeItem, otherOwner, otherParentType, nullptr);
+  aOther->AddTreeItemToTreeOwner(otherTreeItem, ourOwner, ourParentType,
+                                 nullptr);
 
   // SetSubDocumentFor nulls out parent documents on the old child doc if a
   // new non-null document is passed in, so just go ahead and remove both
   // kids before reinserting in the parent subdoc maps, to avoid
   // complications.
   ourParentDocument->SetSubDocumentFor(ourContent, nullptr);
   otherParentDocument->SetSubDocumentFor(otherContent, nullptr);
   ourParentDocument->SetSubDocumentFor(ourContent, otherChildDocument);
   otherParentDocument->SetSubDocumentFor(otherContent, ourChildDocument);
 
   ourWindow->SetFrameElementInternal(otherFrameElement);
   otherWindow->SetFrameElementInternal(ourFrameElement);
 
-  SetOwnerContent(otherContent);
-  aOther->SetOwnerContent(ourContent);
-
   nsRefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
   nsRefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
   // Swap pointers in child message managers.
   if (mChildMessageManager) {
     nsInProcessTabChildGlobal* tabChild =
       static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
     tabChild->SetOwner(otherContent);
     tabChild->SetChromeMessageManager(otherMessageManager);
@@ -1378,16 +1382,20 @@ nsFrameLoader::GetDepthTooGreat(bool* aD
 {
   *aDepthTooGreat = mDepthTooGreat;
   return NS_OK;
 }
 
 void
 nsFrameLoader::SetOwnerContent(Element* aContent)
 {
+  if (mObservingOwnerContent) {
+    mObservingOwnerContent = false;
+    mOwnerContent->RemoveMutationObserver(this);
+  }
   mOwnerContent = aContent;
   if (RenderFrameParent* rfp = GetCurrentRemoteFrame()) {
     rfp->OwnerContentChanged(aContent);
   }
 }
 
 bool
 nsFrameLoader::OwnerIsBrowserFrame()
@@ -1554,18 +1562,18 @@ nsFrameLoader::MaybeCreateDocShell()
     parentAsItem->GetItemType(&parentType);
 
     // XXXbz why is this in content code, exactly?  We should handle
     // this some other way.....  Not sure how yet.
     nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
     parentAsItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
     NS_ENSURE_STATE(parentTreeOwner);
     mIsTopLevelContent =
-      AddTreeItemToTreeOwner(docShellAsItem, mOwnerContent, parentTreeOwner,
-                             parentType, parentAsNode);
+      AddTreeItemToTreeOwner(docShellAsItem, parentTreeOwner, parentType,
+                             parentAsNode);
 
     // Make sure all shells have links back to the content element
     // in the nearest enclosing chrome shell.
     nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
 
     if (parentType == nsIDocShellTreeItem::typeChrome) {
       // Our parent shell is a chrome shell. It is therefore our nearest
       // enclosing chrome shell.
@@ -2399,8 +2407,83 @@ nsFrameLoader::SetDetachedSubdocView(nsI
 
 nsIView*
 nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
 {
   NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
   return mDetachedSubdocViews;
 }
 
+/* virtual */ void
+nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
+                                mozilla::dom::Element* aElement,
+                                int32_t      aNameSpaceID,
+                                nsIAtom*     aAttribute,
+                                int32_t      aModType)
+{
+  MOZ_ASSERT(mObservingOwnerContent);
+  // TODO: Implement ContentShellAdded for remote browsers (bug 658304)
+  MOZ_ASSERT(!mRemoteBrowser);
+
+  if (aNameSpaceID != kNameSpaceID_None || aAttribute != TypeAttrName()) {
+    return;
+  }
+
+  if (aElement != mOwnerContent) {
+    return;
+  }
+
+  // Note: This logic duplicates a lot of logic in
+  // MaybeCreateDocshell.  We should fix that.
+
+  // Notify our enclosing chrome that our type has changed.  We only do this
+  // if our parent is chrome, since in all other cases we're random content
+  // subframes and the treeowner shouldn't worry about us.
+
+  nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
+  if (!docShellAsItem) {
+    return;
+  }
+
+  nsCOMPtr<nsIDocShellTreeItem> parentItem;
+  docShellAsItem->GetParent(getter_AddRefs(parentItem));
+  if (!parentItem) {
+    return;
+  }
+
+  int32_t parentType;
+  parentItem->GetItemType(&parentType);
+
+  if (parentType != nsIDocShellTreeItem::typeChrome) {
+    return;
+  }
+
+  nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
+  parentItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
+  if (!parentTreeOwner) {
+    return;
+  }
+
+  nsAutoString value;
+  aElement->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
+
+  bool is_primary = value.LowerCaseEqualsLiteral("content-primary");
+
+#ifdef MOZ_XUL
+  // when a content panel is no longer primary, hide any open popups it may have
+  if (!is_primary) {
+    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+    if (pm)
+      pm->HidePopupsInDocShell(docShellAsItem);
+  }
+#endif
+
+  parentTreeOwner->ContentShellRemoved(docShellAsItem);
+  if (value.LowerCaseEqualsLiteral("content") ||
+      StringBeginsWith(value, NS_LITERAL_STRING("content-"),
+                       nsCaseInsensitiveStringComparator())) {
+    bool is_targetable = is_primary ||
+      value.LowerCaseEqualsLiteral("content-targetable");
+
+    parentTreeOwner->ContentShellAdded(docShellAsItem, is_primary,
+                                       is_targetable, value);
+  }
+}
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -17,23 +17,27 @@
 #include "nsPoint.h"
 #include "nsSize.h"
 #include "nsIURI.h"
 #include "nsAutoPtr.h"
 #include "nsFrameMessageManager.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Attributes.h"
 #include "FrameMetrics.h"
+#include "nsStubMutationObserver.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsIView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class nsITabParent;
+class nsIDocShellTreeItem;
+class nsIDocShellTreeOwner;
+class nsIDocShellTreeNode;
 
 namespace mozilla {
 namespace dom {
 class PBrowserParent;
 class TabParent;
 }
 
 namespace layout {
@@ -130,17 +134,18 @@ private:
   nsresult Update(const ViewConfig& aConfig);
 
   ViewID mScrollId;
   ViewConfig mConfig;
 };
 
 
 class nsFrameLoader MOZ_FINAL : public nsIFrameLoader,
-                                public nsIContentViewManager
+                                public nsIContentViewManager,
+                                public nsStubMutationObserver
 {
   friend class AutoResetInShow;
   typedef mozilla::dom::PBrowserParent PBrowserParent;
   typedef mozilla::dom::TabParent TabParent;
   typedef mozilla::layout::RenderFrameParent RenderFrameParent;
 
 protected:
   nsFrameLoader(mozilla::dom::Element* aOwner, bool aNetworkCreated);
@@ -161,16 +166,17 @@ public:
 
   static nsFrameLoader* Create(mozilla::dom::Element* aOwner,
                                bool aNetworkCreated);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader)
   NS_DECL_NSIFRAMELOADER
   NS_DECL_NSICONTENTVIEWMANAGER
+  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI);
   nsresult ReallyStartLoading();
   void Finalize();
   nsIDocShell* GetExistingDocShell() { return mDocShell; }
   nsIDOMEventTarget* GetTabChildGlobalAsEventTarget();
   nsresult CreateStaticClone(nsIFrameLoader* aDest);
 
   /**
@@ -332,19 +338,29 @@ private:
   nsresult ReallyStartLoadingInternal();
 
   // Return true if remote browser created; nothing else to do
   bool TryRemoteBrowser();
 
   // Tell the remote browser that it's now "virtually visible"
   bool ShowRemoteFrame(const nsIntSize& size);
 
+  bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
+                              nsIDocShellTreeOwner* aOwner,
+                              int32_t aParentType,
+                              nsIDocShellTreeNode* aParentNode);
+
+  nsIAtom* TypeAttrName() const {
+    return mOwnerContent->IsXUL() ? nsGkAtoms::type : nsGkAtoms::mozframetype;
+  }
+
   nsCOMPtr<nsIDocShell> mDocShell;
   nsCOMPtr<nsIURI> mURIToLoad;
   mozilla::dom::Element* mOwnerContent; // WEAK
+
 public:
   // public because a callback needs these.
   nsRefPtr<nsFrameMessageManager> mMessageManager;
   nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
 private:
   // Stores the root view of the subdocument while the subdocument is being
   // reframed. Used to restore the presentation after reframing.
   nsIView* mDetachedSubdocViews;
@@ -368,16 +384,17 @@ private:
   bool mNetworkCreated : 1;
 
   bool mDelayRemoteDialogs : 1;
   bool mRemoteBrowserShown : 1;
   bool mRemoteFrame : 1;
   bool mClipSubdocument : 1;
   bool mClampScrollPosition : 1;
   bool mRemoteBrowserInitialized : 1;
+  bool mObservingOwnerContent : 1;
 
   // XXX leaking
   nsCOMPtr<nsIObserver> mChildHost;
   RenderFrameParent* mCurrentRemoteFrame;
   TabParent* mRemoteBrowser;
 
   // See nsIFrameLoader.idl.  Short story, if !(mRenderMode &
   // RENDER_MODE_ASYNC_SCROLL), all the fields below are ignored in
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -953,18 +953,17 @@ nsFrameScriptExecutor::InitTabChildGloba
                     (allowXML ? JSOPTION_ALLOW_XML : 0));
   JS_SetVersion(cx, JSVERSION_LATEST);
   JS_SetErrorReporter(cx, ContentScriptErrorReporter);
 
   xpc_LocalizeContext(cx);
 
   JSAutoRequest ar(cx);
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
-  const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
-                         nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
+  const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES;
 
   
   JS_SetContextPrivate(cx, aScope);
 
   nsresult rv =
     xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal,
                                          flags, getter_AddRefs(mGlobal));
   NS_ENSURE_SUCCESS(rv, false);
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -682,53 +682,47 @@ nsObjectLoadingContent::~nsObjectLoading
     StopPluginInstance();
   }
   DestroyImageLoadingContent();
 }
 
 nsresult
 nsObjectLoadingContent::InstantiatePluginInstance()
 {
-  if (mType != eType_Plugin || mIsLoading) {
-    LOG(("OBJLC [%p]: Not instantiating loading or non-plugin object, type %u",
-         this, mType));
+  if (mInstanceOwner || mType != eType_Plugin || mIsLoading || mInstantiating) {
+    return NS_OK;
+  }
+  
+  nsCOMPtr<nsIContent> thisContent =
+    do_QueryInterface(static_cast<nsIImageLoadingContent *>(this));
+
+  // Flush layout so that the frame is created if possible and the plugin is
+  // initialized with the latest information.
+  nsIDocument* doc = thisContent->GetCurrentDoc();
+  
+  if (!doc || !InActiveDocument(thisContent)) {
+    NS_ERROR("Shouldn't be calling "
+             "InstantiatePluginInstance without an active document");
+    return NS_ERROR_FAILURE;
+  }
+  doc->FlushPendingNotifications(Flush_Layout);
+  
+  if (!thisContent->GetPrimaryFrame()) {
+    LOG(("OBJLC [%p]: Not instantiating plugin with no frame", this));
     return NS_OK;
   }
 
-  // Don't do anything if we already have an active instance.
-  if (mInstanceOwner) {
-    return NS_OK;
-  }
-
-  // Don't allow re-entry into initialization code.
-  if (mInstantiating) {
-    return NS_OK;
-  }
   mInstantiating = true;
   AutoSetInstantiatingToFalse autoInstantiating(this);
 
   // Instantiating an instance can result in script execution, which
   // can destroy this DOM object. Don't allow that for the scope
   // of this method.
   nsCOMPtr<nsIObjectLoadingContent> kungFuDeathGrip = this;
 
-  nsCOMPtr<nsIContent> thisContent =
-    do_QueryInterface(static_cast<nsIImageLoadingContent *>(this));
-  // Flush layout so that the plugin is initialized with the latest information.
-  nsIDocument* doc = thisContent->GetCurrentDoc();
-  if (!doc) {
-    return NS_ERROR_FAILURE;
-  }
-  if (!InActiveDocument(thisContent)) {
-    NS_ERROR("Shouldn't be calling "
-             "InstantiatePluginInstance in an inactive document");
-    return NS_ERROR_FAILURE;
-  }
-  doc->FlushPendingNotifications(Flush_Layout);
-
   nsresult rv = NS_ERROR_FAILURE;
   nsRefPtr<nsPluginHost> pluginHost =
     already_AddRefed<nsPluginHost>(nsPluginHost::GetInst());
 
   if (!pluginHost) {
     NS_NOTREACHED("No pluginhost");
     return NS_ERROR_FAILURE;
   }
@@ -876,17 +870,17 @@ nsObjectLoadingContent::OnStopRequest(ns
 }
 
 
 // nsIStreamListener
 NS_IMETHODIMP
 nsObjectLoadingContent::OnDataAvailable(nsIRequest *aRequest,
                                         nsISupports *aContext,
                                         nsIInputStream *aInputStream,
-                                        uint32_t aOffset, uint32_t aCount)
+                                        uint64_t aOffset, uint32_t aCount)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
   if (aRequest != mChannel) {
     return NS_BINDING_ABORTED;
   }
 
   if (mFinalListener) {
@@ -1724,16 +1718,24 @@ nsObjectLoadingContent::LoadObject(bool 
           break;
         }
 
         // Force a sync state change now, we need the frame created
         NotifyStateChanged(oldType, oldState, true, aNotify);
         oldType = mType;
         oldState = ObjectState();
 
+        if (!thisContent->GetPrimaryFrame()) {
+          // We're un-rendered, and can't instantiate a plugin. HasNewFrame will
+          // re-start us when we can proceed.
+          LOG(("OBJLC [%p]: Aborting load - plugin-type, but no frame", this));
+          CloseChannel();
+          break;
+        }
+        
         rv = pluginHost->NewEmbeddedPluginStreamListener(mURI, this, nullptr,
                                                          getter_AddRefs(mFinalListener));
         if (NS_SUCCEEDED(rv)) {
           // Note that LoadObject is called from mChannel's OnStartRequest
           // when loading with a channel
 
           mSrcStreamLoading = true;
           rv = mFinalListener->OnStartRequest(mChannel, nullptr);
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -269,17 +269,17 @@ nsMultipartProxyListener::OnStopRequest(
 }
 
 /** nsIStreamListener methods **/
 
 NS_IMETHODIMP
 nsMultipartProxyListener::OnDataAvailable(nsIRequest *aRequest,
                                           nsISupports *ctxt,
                                           nsIInputStream *inStr,
-                                          uint32_t sourceOffset,
+                                          uint64_t sourceOffset,
                                           uint32_t count)
 {
   return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset,
                                         count);
 }
 
 /////////////////////////////////////////////
 
@@ -1920,17 +1920,17 @@ bool nsXMLHttpRequest::CreateDOMFile(nsI
   }
   return fromFile;
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::OnDataAvailable(nsIRequest *request,
                                   nsISupports *ctxt,
                                   nsIInputStream *inStr,
-                                  uint32_t sourceOffset,
+                                  uint64_t sourceOffset,
                                   uint32_t count)
 {
   NS_ENSURE_ARG_POINTER(inStr);
 
   NS_ABORT_IF_FALSE(mContext.get() == ctxt,"start context different from OnDataAvailable context");
 
   mProgressSinceLastProgressEvent = true;
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/0px-size-font-shadow.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<body>
+<canvas id="canv" width="5" height="5"></canvas>
+<script>
+var canv = document.getElementById("canv");
+var ctx = canv.getContext("2d");
+
+ctx.fillStyle = "red";
+// 0 size font shouldn't assert!
+ctx.font = "0px Arial";
+ctx.shadowColor = '#f00';
+ctx.shadowBlur = 4;
+ctx.fillText("A", 0, 0);
+document.documentElement.className = "";
+</script>
+</body>
+</html>
--- a/content/canvas/crashtests/crashtests.list
+++ b/content/canvas/crashtests/crashtests.list
@@ -1,14 +1,15 @@
 load 360293-1.html
 load 421715-1.html
 load 553938-1.html
 load 647480.html
 load 727547.html
 load 0px-size-font-667225.html
+load 0px-size-font-shadow.html
 load texImage2D.html
 load 729116.html
 load 745699-1.html
 load 746813-1.html
 # this test crashes in a bunch places still
 #load 745818-large-source.html
 load 743499-negative-size.html
 load 767337-1.html
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -4316,32 +4316,38 @@ static uint8_t g2DContextLayerUserData;
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                            CanvasLayer *aOldLayer,
                                            LayerManager *aManager)
 {
     // If we don't have anything to draw, don't bother.
     if (!mValid || !mSurface || mSurface->CairoStatus() || !mThebes ||
         !mSurfaceCreated) {
+        // No DidTransactionCallback will be received, so mark the context clean
+        // now so future invalidations will be dispatched.
+        MarkContextClean();
         return nullptr;
     }
 
     if (!mResetLayer && aOldLayer) {
         CanvasRenderingContext2DUserData* userData =
             static_cast<CanvasRenderingContext2DUserData*>(
                     aOldLayer->GetUserData(&g2DContextLayerUserData));
         if (userData && userData->IsForContext(this)) {
             NS_ADDREF(aOldLayer);
             return aOldLayer;
         }
     }
 
     nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
     if (!canvasLayer) {
         NS_WARNING("CreateCanvasLayer returned null!");
+        // No DidTransactionCallback will be received, so mark the context clean
+        // now so future invalidations will be dispatched.
+        MarkContextClean();
         return nullptr;
     }
     CanvasRenderingContext2DUserData *userData = nullptr;
     if (aBuilder->IsPaintingToWindow()) {
       // Make the layer tell us whenever a transaction finishes (including
       // the current transaction), so we can clear our invalidation state and
       // start invalidating again. We need to do this for the layer that is
       // being painted to a window (there shouldn't be more than one at a time,
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -3211,16 +3211,26 @@ nsCanvasRenderingContext2DAzure::DrawOrM
     }
 
     isRTL = canvasStyle->GetStyleVisibility()->mDirection ==
       NS_STYLE_DIRECTION_RTL;
   } else {
     isRTL = GET_BIDI_OPTION_DIRECTION(document->GetBidiOptions()) == IBMBIDI_TEXTDIRECTION_RTL;
   }
 
+  gfxFontGroup* currentFontStyle = GetCurrentFontStyle();
+  NS_ASSERTION(currentFontStyle, "font group is null");
+
+  if (currentFontStyle->GetStyle()->size == 0.0F) {
+    if (aWidth) {
+      *aWidth = 0;
+    }
+    return NS_OK;
+  }
+
   const ContextState &state = CurrentState();
 
   // This is only needed to know if we can know the drawing bounding box easily.
   bool doDrawShadow = aOp == TEXT_DRAW_OPERATION_FILL && NeedToDrawShadow();
 
   nsCanvasBidiProcessorAzure processor;
 
   GetAppUnitsValues(&processor.mAppUnitsPerDevPixel, nullptr);
@@ -3229,21 +3239,18 @@ nsCanvasRenderingContext2DAzure::DrawOrM
     new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
   Matrix matrix = mTarget->GetTransform();
   processor.mThebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32));
   processor.mCtx = this;
   processor.mOp = aOp;
   processor.mBoundingBox = gfxRect(0, 0, 0, 0);
   processor.mDoMeasureBoundingBox = doDrawShadow || !mIsEntireFrameInvalid;
   processor.mState = &CurrentState();
+  processor.mFontgrp = currentFontStyle;
     
-
-  processor.mFontgrp = GetCurrentFontStyle();
-  NS_ASSERTION(processor.mFontgrp, "font group is null");
-
   nscoord totalWidthCoord;
 
   // calls bidi algo twice since it needs the full text width and the
   // bounding boxes before rendering anything
   nsBidi bidiEngine;
   rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
                                     textToDraw.Length(),
                                     isRTL ? NSBIDI_RTL : NSBIDI_LTR,
@@ -4621,16 +4628,19 @@ nsCanvasRenderingContext2DAzure::SetMozI
 static uint8_t g2DContextLayerUserData;
 
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                                 CanvasLayer *aOldLayer,
                                                 LayerManager *aManager)
 {
   if (!mValid) {
+    // No DidTransactionCallback will be received, so mark the context clean
+    // now so future invalidations will be dispatched.
+    MarkContextClean();
     return nullptr;
   }
 
   if (mTarget) {
     mTarget->Flush();
   }
 
   if (!mResetLayer && aOldLayer) {
@@ -4641,16 +4651,19 @@ nsCanvasRenderingContext2DAzure::GetCanv
       NS_ADDREF(aOldLayer);
       return aOldLayer;
     }
   }
 
   nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
   if (!canvasLayer) {
     NS_WARNING("CreateCanvasLayer returned null!");
+    // No DidTransactionCallback will be received, so mark the context clean
+    // now so future invalidations will be dispatched.
+    MarkContextClean();
     return nullptr;
   }
   CanvasRenderingContext2DUserDataAzure *userData = nullptr;
   // Make the layer tell us whenever a transaction finishes (including
   // the current transaction), so we can clear our invalidation state and
   // start invalidating again. We need to do this for all layers since
   // callers of DrawWindow may be expecting to receive normal invalidation
   // notifications after this paint.
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -308,16 +308,21 @@ public:
 #endif
 
 #ifdef MOZ_MEDIA_PLUGINS
   static bool IsMediaPluginsEnabled();
   static bool IsMediaPluginsType(const nsACString& aType);
 #endif
 
   /**
+   * Get the mime type for this element.
+   */
+  void GetMimeType(nsCString& aMimeType);
+
+  /**
    * Called when a child source element is added to this media element. This
    * may queue a task to run the select resource algorithm if appropriate.
    */
   void NotifyAddedSource();
 
   /**
    * Called when there's been an error fetching the resource. This decides
    * whether it's appropriate to fire an error event.
@@ -867,11 +872,18 @@ protected:
   // The CORS mode when loading the media element
   mozilla::CORSMode mCORSMode;
 
   // True if the media has an audio track
   bool mHasAudio;
 
   // True if the media's channel's download has been suspended.
   bool mDownloadSuspendedByCache;
+
+  // The Content-Type for this media. When we are sniffing for the Content-Type,
+  // and we are recreating a channel after the initial load, we need that
+  // information to give it as a hint to the channel for it to bypass the
+  // sniffing phase, that would fail because sniffing only works when applied to
+  // the first bytes of the stream.
+  nsCString mMimeType;
 };
 
 #endif
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -1055,19 +1055,34 @@ nsHTMLInputElement::SetValue(const nsASt
       const PRUnichar *name = PromiseFlatString(aValue).get();
       return MozSetFileNameArray(&name, 1);
     }
     else {
       ClearFiles(true);
     }
   }
   else {
-    SetValueInternal(aValue, false, true);
     if (IsSingleLineTextControl(false)) {
-      GetValueInternal(mFocusedValue);
+      // If the value has been set by a script, we basically want to keep the
+      // current change event state. If the element is ready to fire a change
+      // event, we should keep it that way. Otherwise, we should make sure the
+      // element will not fire any event because of the script interaction.
+      //
+      // NOTE: this is currently quite expensive work (too much string
+      // manipulation). We should probably optimize that.
+      nsAutoString currentValue;
+      GetValueInternal(currentValue);
+
+      SetValueInternal(aValue, false, true);
+
+      if (mFocusedValue.Equals(currentValue)) {
+        GetValueInternal(mFocusedValue);
+      }
+    } else {
+      SetValueInternal(aValue, false, true);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLInputElement::GetList(nsIDOMHTMLElement** aValue)
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -353,19 +353,22 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaL
                                                                    nsresult aStatus)
 {
   if (mNextListener) {
     return mNextListener->OnStopRequest(aRequest, aContext, aStatus);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
-                                                                     nsIInputStream* aStream, uint32_t aOffset,
-                                                                     uint32_t aCount)
+NS_IMETHODIMP
+nsHTMLMediaElement::MediaLoadListener::OnDataAvailable(nsIRequest* aRequest,
+                                                       nsISupports* aContext,
+                                                       nsIInputStream* aStream,
+                                                       uint64_t aOffset,
+                                                       uint32_t aCount)
 {
   if (!mNextListener) {
     NS_ERROR("Must have a chained listener; OnStartRequest should have canceled this request");
     return NS_BINDING_ABORTED;
   }
   return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount);
 }
 
@@ -1029,16 +1032,21 @@ nsresult nsHTMLMediaElement::LoadResourc
 
   // Set the media element's CORS mode only when loading a resource
   mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
 
   nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc);
   if (other) {
     // Clone it.
     nsresult rv = InitializeDecoderAsClone(other->mDecoder);
+    // Get the mimetype from the element we clone, since we will not get it via
+    // the channel, and we won't be able to sniff for it, because we will not
+    // open a channel to get the beginning of the media (it is likely to already
+    // be in the cache).
+    mMimeType = other->mMimeType;
     if (NS_SUCCEEDED(rv))
       return rv;
   }
 
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_MEDIA,
                                           mLoadingSrc,
                                           NodePrincipal(),
@@ -1067,17 +1075,18 @@ nsresult nsHTMLMediaElement::LoadResourc
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_MEDIA);
   }
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewChannel(getter_AddRefs(channel),
                      mLoadingSrc,
                      nullptr,
                      loadGroup,
                      nullptr,
-                     nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY,
+                     nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
+                     nsIChannel::LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN,
                      channelPolicy);
   NS_ENSURE_SUCCESS(rv,rv);
 
   // The listener holds a strong reference to us.  This creates a
   // reference cycle, once we've set mChannel, which is manually broken
   // in the listener's OnStartRequest method after it is finished with
   // the element. The cycle will also be broken if we get a shutdown
   // notification before OnStartRequest fires.  Necko guarantees that
@@ -2428,29 +2437,31 @@ nsresult nsHTMLMediaElement::InitializeD
 
 nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
                                                          nsIStreamListener **aListener)
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
   NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder");
 
   nsAutoCString mimeType;
-  aChannel->GetContentType(mimeType);
-
-  nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mimeType);
+
+  aChannel->GetContentType(mMimeType);
+  NS_ASSERTION(!mMimeType.IsEmpty(), "We should have the Content-Type.");
+
+  nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mMimeType);
   if (!decoder) {
     nsAutoString src;
     GetCurrentSrc(src);
-    NS_ConvertUTF8toUTF16 mimeUTF16(mimeType);
+    NS_ConvertUTF8toUTF16 mimeUTF16(mMimeType);
     const PRUnichar* params[] = { mimeUTF16.get(), src.get() };
     ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params));
     return NS_ERROR_FAILURE;
   }
 
-  LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
+  LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mMimeType.get()));
 
   MediaResource* resource = MediaResource::Create(decoder, aChannel);
   if (!resource)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // stream successfully created, the stream now owns the channel.
   mChannel = nullptr;
 
@@ -3523,14 +3534,19 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMoz
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there is no end fragment, or the fragment end is greater than the
   // duration, return the duration.
   *aTime = (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd;
   return NS_OK;
 }
 
+void nsHTMLMediaElement::GetMimeType(nsCString& aMimeType)
+{
+  aMimeType = mMimeType;
+}
+
 void nsHTMLMediaElement::NotifyAudioAvailableListener()
 {
   if (mDecoder) {
     mDecoder->NotifyAudioAvailableListener();
   }
 }
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -540,18 +540,32 @@ nsHTMLTextAreaElement::SetValueInternal(
   mState.SetValue(aValue, aUserInput, true);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsHTMLTextAreaElement::SetValue(const nsAString& aValue)
 {
+  // If the value has been set by a script, we basically want to keep the
+  // current change event state. If the element is ready to fire a change
+  // event, we should keep it that way. Otherwise, we should make sure the
+  // element will not fire any event because of the script interaction.
+  //
+  // NOTE: this is currently quite expensive work (too much string
+  // manipulation). We should probably optimize that.
+  nsAutoString currentValue;
+  GetValueInternal(currentValue, true);
+
   SetValueInternal(aValue, false);
-  GetValueInternal(mFocusedValue, true);
+
+  if (mFocusedValue.Equals(currentValue)) {
+    GetValueInternal(mFocusedValue, true);
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsHTMLTextAreaElement::SetUserInput(const nsAString& aValue)
 {
   if (!nsContentUtils::IsCallerTrustedForWrite()) {
     return NS_ERROR_DOM_SECURITY_ERR;
--- a/content/html/content/test/forms/test_change_event.html
+++ b/content/html/content/test/forms/test_change_event.html
@@ -101,23 +101,49 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     //focus and blur text input
     input = document.getElementById("input_text");
     input.focus();
     synthesizeKey("f", {});
     input.blur();
     is(textInputChange[0], 2, "text input element should have dispatched change event (2).");
 
+    // value being set while focused
+    input.focus();
+    input.value = 'foo';
+    input.blur();
+    is(textInputChange[0], 2, "text input element should not have dispatched change event (2).");
+
+    // value being set while focused after being modified manually
+    input.focus();
+    synthesizeKey("f", {});
+    input.value = 'bar';
+    input.blur();
+    is(textInputChange[0], 3, "text input element should have dispatched change event (3).");
+
     //focus and blur textarea
     var textarea = document.getElementById("textarea");
     textarea.focus();
     synthesizeKey("f", {});
     textarea.blur();
     is(textareaChange, 1, "Textarea element should have dispatched change event.");
 
+    // value being set while focused
+    textarea.focus();
+    textarea.value = 'foo';
+    textarea.blur();
+    is(textareaChange, 1, "textarea should not have dispatched change event (1).");
+
+    // value being set while focused after being modified manually
+    textarea.focus();
+    synthesizeKey("f", {});
+    textarea.value = 'bar';
+    textarea.blur();
+    is(textareaChange, 2, "textearea should have dispatched change event (2).");
+
     //Non-text input tests:
     for (var i = 0; i < NonTextInputTypes.length; ++i) {
       //button, submit, image and reset input type tests.
       if (i < 4) {
         input = document.getElementById("input_" + NonTextInputTypes[i]);
         input.focus();
         input.click();
         is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element");
--- a/content/html/document/src/MediaDocument.cpp
+++ b/content/html/document/src/MediaDocument.cpp
@@ -72,17 +72,17 @@ MediaDocumentStreamListener::OnStopReque
 
   return rv;
 }
 
 NS_IMETHODIMP
 MediaDocumentStreamListener::OnDataAvailable(nsIRequest* request,
                                              nsISupports *ctxt,
                                              nsIInputStream *inStr,
-                                             uint32_t sourceOffset,
+                                             uint64_t sourceOffset,
                                              uint32_t count)
 {
   if (mNextStream) {
     return mNextStream->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
   }
 
   return NS_OK;
 }
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1241,17 +1241,20 @@ nsHTMLDocument::GetCookie(nsAString& aCo
       // Document's principal is not a codebase (may be system), so
       // can't set cookies
 
       return NS_OK;
     }
 
     nsXPIDLCString cookie;
     service->GetCookieString(codebaseURI, mChannel, getter_Copies(cookie));
-    CopyASCIItoUTF16(cookie, aCookie);
+    // CopyUTF8toUTF16 doesn't handle error
+    // because it assumes that the input is valid.
+    nsContentUtils::ConvertStringFromCharset(NS_LITERAL_CSTRING("utf-8"),
+                                             cookie, aCookie);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::SetCookie(const nsAString& aCookie)
 {
@@ -1280,17 +1283,17 @@ nsHTMLDocument::SetCookie(const nsAStrin
 
     if (!codebaseURI) {
       // Document's principal is not a codebase (may be system), so
       // can't set cookies
 
       return NS_OK;
     }
 
-    NS_LossyConvertUTF16toASCII cookie(aCookie);
+    NS_ConvertUTF16toUTF8 cookie(aCookie);
     service->SetCookieString(codebaseURI, prompt, cookie.get(), mChannel);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
--- a/content/html/document/test/Makefile.in
+++ b/content/html/document/test/Makefile.in
@@ -67,16 +67,18 @@ MOCHITEST_FILES = 	test_bug1682.html \
 		test_bug499092.html \
 		bug499092.xml \
 		bug499092.html \
 		test_bug512367.html \
 		test_bug571981.html \
 		test_bug677495.html \
 		test_bug677495-1.html \
 		test_bug741266.html \
+		test_non-ascii-cookie.html \
+		test_non-ascii-cookie.html^headers^ \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 MOCHITEST_BROWSER_FILES = \
 		browser_bug592641.js \
 		bug592641_img.jpg \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/test_non-ascii-cookie.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=784367
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for non-ASCII document.cookie</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=784367">Mozilla Bug 784367</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for non-ASCII document.cookie **/
+var c = document.cookie;
+is(document.cookie, 'abc=012©ABC\ufffdDEF', "document.cookie should be decoded as UTF-8");
+var newCookie = 'def=∼≩≭≧∯≳≲≣∽≸≸∺≸∠≯≮≥≲≲≯≲∽≡≬≥≲≴∨∱∩∾';
+document.cookie = newCookie;
+is(document.cookie, c + '; ' + newCookie, "document.cookie should be encoded as UTF-8");
+var date1 = new Date();
+date1.setTime(0);
+document.cookie = newCookie + 'def=;expires=' + date1.toGMTString();
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/test_non-ascii-cookie.html^headers^
@@ -0,0 +1,1 @@
+Set-Cookie: abc=012©ABC©DEF
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -82,17 +82,17 @@ ChannelMediaResource::Listener::OnStopRe
     return NS_OK;
   return mResource->OnStopRequest(aRequest, aStatus);
 }
 
 nsresult
 ChannelMediaResource::Listener::OnDataAvailable(nsIRequest* aRequest,
                                                 nsISupports* aContext,
                                                 nsIInputStream* aStream,
-                                                uint32_t aOffset,
+                                                uint64_t aOffset,
                                                 uint32_t aCount)
 {
   if (!mResource)
     return NS_OK;
   return mResource->OnDataAvailable(aRequest, aStream, aCount);
 }
 
 nsresult
@@ -699,22 +699,34 @@ ChannelMediaResource::RecreateChannel()
   nsHTMLMediaElement* element = mDecoder->GetMediaElement();
   if (!element) {
     // The decoder is being shut down, so don't bother opening a new channel
     return NS_OK;
   }
   nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup();
   NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER);
 
-  return NS_NewChannel(getter_AddRefs(mChannel),
-                       mURI,
-                       nullptr,
-                       loadGroup,
-                       nullptr,
-                       loadFlags);
+  nsresult rv = NS_NewChannel(getter_AddRefs(mChannel),
+                              mURI,
+                              nullptr,
+                              loadGroup,
+                              nullptr,
+                              loadFlags);
+
+  // We have cached the Content-Type, which should not change. Give a hint to
+  // the channel to avoid a sniffing failure, which would be expected because we
+  // are probably seeking in the middle of the bitstream, and sniffing relies
+  // on the presence of a magic number at the beginning of the stream.
+  nsAutoCString contentType;
+  element->GetMimeType(contentType);
+  NS_ASSERTION(!contentType.IsEmpty(),
+      "When recreating a channel, we should know the Content-Type.");
+  mChannel->SetContentType(contentType);
+
+  return rv;
 }
 
 void
 ChannelMediaResource::DoNotifyDataReceived()
 {
   mDataReceivedEvent.Revoke();
   mDecoder->NotifyBytesDownloaded();
 }
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -122,16 +122,18 @@ MOCHITEST_FILES = \
 		test_autoplay_contentEditable.html \
 		test_buffered.html \
 		test_bug448534.html \
 		test_bug463162.xhtml \
 		test_decoder_disable.html \
 		test_media_selection.html \
 		test_playback.html \
 		test_seekLies.html \
+		test_media_sniffer.html \
+		contentType.sjs \
 		$(NULL)
 
 $(warning test_error_in_video_document.html is disabled for intermittent failures. Bug 608634)
 
 # Disabled on Windows for frequent intermittent failures
 ifneq ($(OS_ARCH), WINNT)
 MOCHITEST_FILES += \
 		test_streams_element_capture.html \
@@ -207,16 +209,19 @@ MOCHITEST_FILES += \
 		seek.yuv \
 		short-video.ogv \
 		small-shot.ogg \
 		sound.ogg \
 		spacestorm-1000Hz-100ms.ogg \
 		video-overhang.ogg \
 		file_a4_tone.ogg \
 		detodos.opus \
+		short.mp4 \
+		notags.mp3 \
+		id3tags.mp3 \
 		$(NULL)
 
 # Wave sample files
 MOCHITEST_FILES += \
 		big.wav \
 		bogus.wav \
 		r11025_msadpcm_c1.wav \
 		r11025_s16_c1.wav \
new file mode 100644
--- /dev/null
+++ b/content/media/test/contentType.sjs
@@ -0,0 +1,77 @@
+// Parse the query string, and give us the value for a certain key, or false if
+// it does not exist.
+function parseQuery(request, key) {
+  var params = request.queryString.split('?')[0].split('&');
+  for (var j = 0; j < params.length; ++j) {
+    var p = params[j];
+    if (p == key)
+      return true;
+    if (p.indexOf(key + "=") == 0)
+      return p.substring(key.length + 1);
+    if (p.indexOf("=") < 0 && key == "")
+      return p;
+  }
+  return false;
+}
+
+function handleRequest(request, response) {
+  try {
+    // Get the filename to send back.
+    var filename = parseQuery(request, "file");
+
+    const CC = Components.Constructor;
+    const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
+                                  "nsIBinaryOutputStream",
+                                  "setOutputStream");
+    var file = Components.classes["@mozilla.org/file/directory_service;1"].
+      getService(Components.interfaces.nsIProperties).
+      get("CurWorkD", Components.interfaces.nsILocalFile);
+    var fis  = Components.classes['@mozilla.org/network/file-input-stream;1'].
+      createInstance(Components.interfaces.nsIFileInputStream);
+    var bis  = Components.classes["@mozilla.org/binaryinputstream;1"].
+      createInstance(Components.interfaces.nsIBinaryInputStream);
+    var paths = "tests/content/media/test/" + filename;
+    dump(paths + '\n');
+    var split = paths.split("/");
+    for(var i = 0; i < split.length; ++i) {
+      file.append(split[i]);
+    }
+    fis.init(file, -1, -1, false);
+
+    // handle range requests
+    var partialstart = 0,
+        partialend = file.fileSize - 1;
+    if (request.hasHeader("Range")) {
+      var range = request.getHeader("Range");
+      var parts = range.replace(/bytes=/, "").split("-");
+      var partialstart = parts[0];
+      var partialend = parts[1];
+      if (!partialend.length) {
+        partialend = file.fileSize - 1;
+      }
+      response.setStatusLine(request.httpVersion, 206, "Partial Content");
+      var contentRange = "bytes " + partialstart + "-" + partialend + "/" + file.fileSize;
+      response.setHeader("Content-Range", contentRange);
+    }
+
+    fis.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, partialstart);
+    bis.setInputStream(fis);
+
+    var sendContentType = parseQuery(request, "nomime");
+    if (sendContentType == false) {
+      var contentType = parseQuery(request, "type");
+      if (contentType == false) {
+        // This should not happen.
+        dump("No type specified without having \'nomime\' in parameters.");
+        return;
+      }
+      response.setHeader("Content-Type", contentType, false);
+    }
+    response.setHeader("Content-Length", ""+bis.available(), false);
+
+    var bytes = bis.readBytes(bis.available());
+    response.write(bytes, bytes.length);
+  } catch (e) {
+    dump ("ERROR : " + e + "\n");
+  }
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bad506cf185478c9c903793d11d95f278148e007
GIT binary patch
literal 3530
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
E0HD#jxc~qF
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -151,16 +151,29 @@ var gPlayTests = [
   { name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 },
 
   { name:"gizmo.mp4", type:"video/mp4", duration:5.0 },
 
   // Invalid file
   { name:"bogus.duh", type:"bogus/duh", duration:Number.NaN }
 ];
 
+// A file for each type we can support.
+var gSnifferTests = [
+  { name:"big.wav", type:"audio/x-wav", duration:9.278981, size:102444 },
+  { name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233, size:28942 },
+  { name:"seek.webm", type:"video/webm", duration:3.966, size:215529 },
+  { name:"short.mp4", type:"video/mp4", duration:0.2, size:29435},
+  // A mp3 file without id3 tags.
+  { name:"notags.mp3", type:"audio/mpeg", duration:0.28, size:2506},
+  // A mp3 file with id3 tags.
+  { name:"id3tags.mp3", type:"audio/mpeg", duration:0.28, size:3530},
+  { name:"bogus.duh", type:"bogus/duh" }
+];
+
 // Converts a path/filename to a file:// URI which we can load from disk.
 // Optionally checks whether the file actually exists on disk at the location
 // we've specified.
 function fileUriToSrc(path, mustExist) {
   // android mochitest doesn't support file://
   if (navigator.appVersion.indexOf("Android") != -1)
     return path;
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7f298131aa437897eb7ff41b64ddc452ec2a0ef8
GIT binary patch
literal 2506
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
H|AT)6tPzX8
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0b9870bdcb500389b78a84e7feb6cce31fd828b4
GIT binary patch
literal 29435
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
MRG|T@ofi2215^f=E&u=k
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_media_sniffer.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: mozStopDownload</title>
+  <meta charset='utf-8'>
+  <script type="text/javascript" src="/MochiKit/Base.js"></script>
+  <script type="text/javascript" src="/MochiKit/DOM.js"></script>
+  <script type="text/javascript" src="/MochiKit/Style.js"></script>
+  <script type="text/javascript" src="/MochiKit/Signal.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+var manager = new MediaTestManager;
+
+function finish_test(element) {
+  if (element.parentNode)
+    element.parentNode.removeChild(element);
+  manager.finished(element.token);
+}
+
+function onApplicationOctetStreamLoaded(e) {
+  var t = e.target;
+  t.removeEventListener('loadedmetadata', onApplicationOctetStreamLoaded);
+  ok(true, "The media loads when served with application/octet-stream.");
+  finish_test(t);
+}
+
+function checkApplicationOctetStream(t) {
+  t.src = t.src.replace("&nomime", "&type=application/octet-stream");
+  t.addEventListener("loadedmetadata", onApplicationOctetStreamLoaded);
+}
+
+function onmetadataloaded(e) {
+  var t = e.target;
+  t.removeEventListener('loadedmetadata', onmetadataloaded)
+  ok(true, "The media loads when served without a Content-Type.");
+  checkApplicationOctetStream(t);
+}
+
+function onerror(e) {
+  var t = e.target;
+  t.removeEventListener('error', onerror);
+  ok(false, "The media could not be loaded." + t.src + "\n");
+  finish_test(t);
+}
+
+function startTest(test, token) {
+  var elemType = /^audio/.test(test.type) ? "audio" : "video";
+  var element = document.createElement(elemType);
+  // This .sjs file serve the media file without Content-Type header, or with a
+  // specific Content-Type header.
+  element.src = 'contentType.sjs?file=' + test.name + "&nomime";
+  element.token = token;
+  element.controls = true;
+  element.preload = "metadata";
+  document.body.appendChild(element);
+  manager.started(token);
+  element.addEventListener("loadedmetadata", onmetadataloaded);
+  element.addEventListener("error", onerror);
+}
+
+manager.runTests(gSnifferTests, startTest);
+</script>
+</pre>
+</body>
+</html>
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -228,18 +228,19 @@ nsXBLStreamListener::~nsXBLStreamListene
 {
   for (uint32_t i = 0; i < mBindingRequests.Length(); i++) {
     nsXBLBindingRequest* req = mBindingRequests.ElementAt(i);
     nsXBLBindingRequest::Destroy(nsXBLService::GetInstance()->mPool, req);
   }
 }
 
 NS_IMETHODIMP
-nsXBLStreamListener::OnDataAvailable(nsIRequest *request, nsISupports* aCtxt, nsIInputStream* aInStr, 
-                                     uint32_t aSourceOffset, uint32_t aCount)
+nsXBLStreamListener::OnDataAvailable(nsIRequest *request, nsISupports* aCtxt,
+                                     nsIInputStream* aInStr, 
+                                     uint64_t aSourceOffset, uint32_t aCount)
 {
   if (mInner)
     return mInner->OnDataAvailable(request, aCtxt, aInStr, aSourceOffset, aCount);
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsXBLStreamListener::OnStartRequest(nsIRequest* request, nsISupports* aCtxt)
--- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
+++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
@@ -218,17 +218,17 @@ NS_IMETHODIMP
 txStylesheetSink::DidBuildModel(bool aTerminated)
 {  
     return mCompiler->doneLoading();
 }
 
 NS_IMETHODIMP
 txStylesheetSink::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
                                   nsIInputStream *aInputStream,
-                                  uint32_t aOffset, uint32_t aCount)
+                                  uint64_t aOffset, uint32_t aCount)
 {
     if (!mCheckedForXML) {
         nsCOMPtr<nsIParser> parser = do_QueryInterface(aContext);
         nsCOMPtr<nsIDTD> dtd;
         parser->GetDTD(getter_AddRefs(dtd));
         if (dtd) {
             mCheckedForXML = true;
             if (!(dtd->GetType() & NS_IPARSER_FLAG_XML)) {
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -4495,17 +4495,17 @@ nsXULDocument::CachedChromeStreamListene
     return mDocument->OnPrototypeLoadDone(true);
 }
 
 
 NS_IMETHODIMP
 nsXULDocument::CachedChromeStreamListener::OnDataAvailable(nsIRequest *request,
                                                            nsISupports* aContext,
                                                            nsIInputStream* aInStr,
-                                                           uint32_t aSourceOffset,
+                                                           uint64_t aSourceOffset,
                                                            uint32_t aCount)
 {
     NS_NOTREACHED("CachedChromeStream doesn't receive data");
     return NS_ERROR_UNEXPECTED;
 }
 
 //----------------------------------------------------------------------
 //
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -434,17 +434,17 @@ NS_IMPL_ISUPPORTS4(nsPingListener, nsISt
 NS_IMETHODIMP
 nsPingListener::OnStartRequest(nsIRequest *request, nsISupports *context)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPingListener::OnDataAvailable(nsIRequest *request, nsISupports *context,
-                                nsIInputStream *stream, uint32_t offset,
+                                nsIInputStream *stream, uint64_t offset,
                                 uint32_t count)
 {
   uint32_t result;
   return stream->ReadSegments(NS_DiscardSegment, nullptr, count, &result);
 }
 
 NS_IMETHODIMP
 nsPingListener::OnStopRequest(nsIRequest *request, nsISupports *context,
@@ -6659,36 +6659,27 @@ nsDocShell::EnsureContentViewer()
 {
     if (mContentViewer)
         return NS_OK;
     if (mIsBeingDestroyed)
         return NS_ERROR_FAILURE;
 
     NS_TIME_FUNCTION;
 
-    nsIPrincipal* principal = nullptr;
     nsCOMPtr<nsIURI> baseURI;
-
-    nsCOMPtr<nsPIDOMWindow> piDOMWindow(do_QueryInterface(mScriptGlobal));
-    if (piDOMWindow) {
-        principal = piDOMWindow->GetOpenerScriptPrincipal();
-    }
-
-    if (!principal) {
-        principal = GetInheritedPrincipal(false);
-        nsCOMPtr<nsIDocShellTreeItem> parentItem;
-        GetSameTypeParent(getter_AddRefs(parentItem));
-        if (parentItem) {
-            nsCOMPtr<nsPIDOMWindow> domWin = do_GetInterface(GetAsSupports(this));
-            if (domWin) {
-                nsCOMPtr<nsIContent> parentContent =
-                    do_QueryInterface(domWin->GetFrameElementInternal());
-                if (parentContent) {
-                    baseURI = parentContent->GetBaseURI();
-                }
+    nsIPrincipal* principal = GetInheritedPrincipal(false);
+    nsCOMPtr<nsIDocShellTreeItem> parentItem;
+    GetSameTypeParent(getter_AddRefs(parentItem));
+    if (parentItem) {
+        nsCOMPtr<nsPIDOMWindow> domWin = do_GetInterface(GetAsSupports(this));
+        if (domWin) {
+            nsCOMPtr<nsIContent> parentContent =
+                do_QueryInterface(domWin->GetFrameElementInternal());
+            if (parentContent) {
+                baseURI = parentContent->GetBaseURI();
             }
         }
     }
 
     nsresult rv = CreateAboutBlankContentViewer(principal, baseURI);
 
     if (NS_SUCCEEDED(rv)) {
         nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(this)));
--- a/docshell/base/nsIMarkupDocumentViewer.idl
+++ b/docshell/base/nsIMarkupDocumentViewer.idl
@@ -122,9 +122,17 @@ interface nsIMarkupDocumentViewer : nsIS
   attribute long minFontSize;
 
   /**
    * Append |this| and all of its descendants to the given array,
    * in depth-first pre-order traversal.
    */
   [noscript] void appendSubtree(in nsIMarkupDocumentViewerTArray array);
 
+  /**
+   * Set the maximum line width for the document.
+   * NOTE: This will generate a reflow!
+   *
+   * @param maxLineWidth The maximum width of any line boxes on the page,
+   *        in CSS pixels.
+   */
+  void changeMaxLineBoxWidth(in int32_t maxLineBoxWidth);
 };
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -39,16 +39,17 @@ PARALLEL_DIRS = \
   interfaces/smil \
   interfaces/apps \
   $(NULL)
 
 PARALLEL_DIRS += \
   apps \
   base \
   activities \
+  bindings \
   battery \
   browser-element \
   contacts \
   alarm \
   devicestorage \
   file \
   media \
   messages \
@@ -85,22 +86,16 @@ PARALLEL_DIRS += \
 endif
 
 ifdef MOZ_PAY
 PARALLEL_DIRS += \
   payment \
   $(NULL)
 endif
 
-# Not in PARALLEL_DIRS because we need to make sure it builds before
-# bindings/test, which builds from TEST_DIRS, which gets appended to DIRS.
-DIRS = \
-  bindings \
-  $(NULL)
-
 # bindings/test is here, because it needs to build after bindings/, and
 # we build subdirectories before ourselves.
 TEST_DIRS += \
   tests \
   imptests \
   bindings/test \
   $(NULL)
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -524,18 +524,18 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "BluetoothPropertyEvent.h"
 #endif
 
 #include "nsIDOMNavigatorSystemMessages.h"
 
 #include "mozilla/dom/Activity.h"
 
 #include "DOMCameraManager.h"
-#include "CameraControl.h"
-#include "CameraCapabilities.h"
+#include "DOMCameraControl.h"
+#include "DOMCameraCapabilities.h"
 
 #include "DOMError.h"
 #include "DOMRequest.h"
 #include "nsIOpenWindowEventDetail.h"
 #include "nsIDOMGlobalObjectConstructor.h"
 
 #include "DOMFileHandle.h"
 #include "FileRequest.h"
@@ -4634,17 +4634,18 @@ nsDOMClassInfo::Init()
   // Non-proxy bindings
   mozilla::dom::Register(nameSpaceManager);
 
   // This needs to happen after the call to mozilla::dom::Register, because we
   // overwrite some values.
   mozilla::dom::oldproxybindings::Register(nameSpaceManager);
 
   if (!AzureCanvasEnabled()) {
-    nameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING("CanvasRenderingContext2D"), NULL);
+    nameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING("CanvasRenderingContext2D"),
+                                                 nullptr, nullptr);
   }
 
   sIsInitialized = true;
 
   return NS_OK;
 }
 
 // static
@@ -6785,16 +6786,20 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
     mozilla::dom::DefineInterface define =
       name_struct->mDefineDOMInterface;
     if (define) {
       if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
           !ConstructorEnabled(name_struct, aWin)) {
         return NS_OK;
       }
 
+      if (name_struct->mPrefEnabled && !(*name_struct->mPrefEnabled)()) {
+        return NS_OK;
+      }
+
       if (mozilla::dom::DefineConstructor(cx, obj, define, &rv)) {
         *did_resolve = NS_SUCCEEDED(rv);
 
         return rv;
       }
     }
   }
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1261,17 +1261,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArguments)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mPerformance, nsPerformance)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOuterWindow)
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
 
   for (nsTimeout* timeout = tmp->FirstTimeout();
        tmp->IsTimeout(timeout);
        timeout = timeout->Next()) {
     cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(nsTimeout));
   }
@@ -1311,17 +1310,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPerformance)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder)
   if (tmp->mOuterWindow) {
     static_cast<nsGlobalWindow*>(tmp->mOuterWindow.get())->MaybeClearInnerWindow(tmp);
     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOuterWindow)
   }
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal)
   if (tmp->mListenerManager) {
     tmp->mListenerManager->Disconnect();
     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager)
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLocalStorage)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSessionStorage)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal)
@@ -1459,104 +1457,106 @@ nsGlobalWindow::GetGlobalJSObject()
 }
 
 bool
 nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
 {
   // We reuse the inner window when:
   // a. We are currently at our original document.
   // b. At least one of the following conditions are true:
-  // -- We are not currently a content window (i.e., we're currently a chrome
-  //    window).
   // -- The new document is the same as the old document. This means that we're
   //    getting called from document.open().
   // -- The new document has the same origin as what we have loaded right now.
 
   if (!mDoc || !aNewDocument) {
     return false;
   }
 
   if (!mDoc->IsInitialDocument()) {
     return false;
   }
   
   NS_ASSERTION(NS_IsAboutBlank(mDoc->GetDocumentURI()),
                "How'd this happen?");
-  
+
   // Great, we're the original document, check for one of the other
   // conditions.
+
   if (mDoc == aNewDocument) {
     return true;
   }
 
   bool equal;
   if (NS_SUCCEEDED(mDoc->NodePrincipal()->Equals(aNewDocument->NodePrincipal(),
                                                  &equal)) &&
       equal) {
     // The origin is the same.
     return true;
   }
 
-  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(mDocShell));
-
-  if (treeItem) {
-    int32_t itemType = nsIDocShellTreeItem::typeContent;
-    treeItem->GetItemType(&itemType);
-
-    // If we're a chrome window, then we want to reuse the inner window.
-    return itemType == nsIDocShellTreeItem::typeChrome;
-  }
-
-  // No treeItem: don't reuse the current inner window.
   return false;
 }
 
 void
-nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal)
-{
-  FORWARD_TO_OUTER_VOID(SetOpenerScriptPrincipal, (aPrincipal));
-
+nsGlobalWindow::SetInitialPrincipalToSubject()
+{
+  FORWARD_TO_OUTER_VOID(SetInitialPrincipalToSubject, ());
+
+  // First, grab the subject principal. These methods never fail.
+  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+  nsCOMPtr<nsIPrincipal> newWindowPrincipal, systemPrincipal;
+  ssm->GetSubjectPrincipal(getter_AddRefs(newWindowPrincipal));
+  ssm->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
+  if (!newWindowPrincipal) {
+    newWindowPrincipal = systemPrincipal;
+  }
+
+  // Now, if we're about to use the system principal, make sure we're not using
+  // it for a content docshell.
+  if (newWindowPrincipal == systemPrincipal) {
+    int32_t itemType;
+    nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(GetDocShell());
+    nsresult rv = item->GetItemType(&itemType);
+    if (NS_FAILED(rv) || itemType != nsIDocShellTreeItem::typeChrome) {
+      newWindowPrincipal = nullptr;
+    }
+  }
+
+  // If there's an existing document, bail if it either:
   if (mDoc) {
-    if (!mDoc->IsInitialDocument()) {
-      // We have a document already, and it's not the original one.  Bail out.
-      // Do NOT set mOpenerScriptPrincipal in this case, just to be safe.
+    // (a) is not an initial about:blank document, or
+    if (!mDoc->IsInitialDocument())
       return;
-    }
+    // (b) already has the correct principal.
+    if (mDoc->NodePrincipal() == newWindowPrincipal)
+      return;
 
 #ifdef DEBUG
-    // We better have an about:blank document loaded at this point.  Otherwise,
-    // something is really weird.
+    // If we have a document loaded at this point, it had better be about:blank.
+    // Otherwise, something is really weird.
     nsCOMPtr<nsIURI> uri;
     mDoc->NodePrincipal()->GetURI(getter_AddRefs(uri));
     NS_ASSERTION(uri && NS_IsAboutBlank(uri) &&
                  NS_IsAboutBlank(mDoc->GetDocumentURI()),
                  "Unexpected original document");
 #endif
-
-    GetDocShell()->CreateAboutBlankContentViewer(aPrincipal);
-    mDoc->SetIsInitialDocument(true);
-
-    nsCOMPtr<nsIPresShell> shell;
-    GetDocShell()->GetPresShell(getter_AddRefs(shell));
-
-    if (shell && !shell->DidInitialReflow()) {
-      // Ensure that if someone plays with this document they will get
-      // layout happening.
-      nsRect r = shell->GetPresContext()->GetVisibleArea();
-      shell->InitialReflow(r.width, r.height);
-    }
-  }
-}
-
-nsIPrincipal*
-nsGlobalWindow::GetOpenerScriptPrincipal()
-{
-  FORWARD_TO_OUTER(GetOpenerScriptPrincipal, (), nullptr);
-
-  return mOpenerScriptPrincipal;
+  }
+
+  GetDocShell()->CreateAboutBlankContentViewer(newWindowPrincipal);
+  mDoc->SetIsInitialDocument(true);
+
+  nsCOMPtr<nsIPresShell> shell;
+  GetDocShell()->GetPresShell(getter_AddRefs(shell));
+
+  if (shell && !shell->DidInitialReflow()) {
+    // Ensure that if someone plays with this document they will get
+    // layout happening.
+    nsRect r = shell->GetPresContext()->GetVisibleArea();
+    shell->InitialReflow(r.width, r.height);
+  }
 }
 
 PopupControlState
 PushPopupControlState(PopupControlState aState, bool aForce)
 {
   PopupControlState oldState = gPopupControlState;
 
   if (aState < gPopupControlState || aForce) {
@@ -1692,43 +1692,33 @@ nsGlobalWindow::SetOuterObject(JSContext
  * Create a new global object that will be used for an inner window.
  * Return the native global and an nsISupports 'holder' that can be used
  * to manage the lifetime of it.
  */
 static nsresult
 CreateNativeGlobalForInner(JSContext* aCx,
                            nsGlobalWindow* aNewInner,
                            nsIURI* aURI,
-                           bool aIsChrome,
                            nsIPrincipal* aPrincipal,
                            JSObject** aNativeGlobal,
                            nsIXPConnectJSObjectHolder** aHolder)
 {
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(aNewInner);
   MOZ_ASSERT(aNewInner->IsInnerWindow());
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(aNativeGlobal);
   MOZ_ASSERT(aHolder);
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
-  uint32_t flags = aIsChrome ? nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT : 0;
-
-  nsCOMPtr<nsIPrincipal> systemPrincipal;
-  if (aIsChrome) {
-    nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-    ssm->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
-    MOZ_ASSERT(systemPrincipal);
-  }
 
   nsRefPtr<nsIXPConnectJSObjectHolder> jsholder;
   nsresult rv = xpc->InitClassesWithNewWrappedGlobal(
     aCx, static_cast<nsIScriptGlobalObject*>(aNewInner),
-    aIsChrome ? systemPrincipal.get() : aPrincipal, flags,
-    getter_AddRefs(jsholder));
+    aPrincipal, 0, getter_AddRefs(jsholder));
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(jsholder);
   jsholder->GetJSObject(aNativeGlobal);
   jsholder.forget(aHolder);
 
   // Set the location information for the new global, so that tools like
   // about:memory may use that information
@@ -1841,18 +1831,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
     currentInner->mNavigator->OnNavigation();
   }
 
   nsRefPtr<nsGlobalWindow> newInnerWindow;
   bool createdInnerWindow = false;
 
   bool thisChrome = IsChromeWindow();
 
-  bool isChrome = false;
-
   nsCxPusher cxPusher;
   if (!cxPusher.Push(cx)) {
     return NS_ERROR_FAILURE;
   }
 
   XPCAutoRequest ar(cx);
 
   nsCOMPtr<WindowStateHolder> wsh = do_QueryInterface(aState);
@@ -1877,27 +1865,34 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       return NS_ERROR_FAILURE;
     }
 
     // Inner windows are only reused for same-origin principals, but the principals
     // don't necessarily match exactly. Update the principal on the compartment to
     // match the new document.
     // NB: We don't just call currentInner->RefreshCompartmentPrincipals() here
     // because we haven't yet set its mDoc to aDocument.
-    JS_SetCompartmentPrincipals(js::GetObjectCompartment(currentInner->mJSObject),
+    JSCompartment *compartment = js::GetObjectCompartment(currentInner->mJSObject);
+#ifdef DEBUG
+    bool sameOrigin = false;
+    nsIPrincipal *existing =
+      nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment));
+    aDocument->NodePrincipal()->Equals(existing, &sameOrigin);
+    MOZ_ASSERT(sameOrigin);
+#endif
+    JS_SetCompartmentPrincipals(compartment,
                                 nsJSPrincipals::get(aDocument->NodePrincipal()));
   } else {
     if (aState) {
       newInnerWindow = wsh->GetInnerWindow();
       mInnerWindowHolder = wsh->GetInnerWindowHolder();
 
       NS_ASSERTION(newInnerWindow, "Got a state without inner window");
     } else if (thisChrome) {
       newInnerWindow = new nsGlobalChromeWindow(this);
-      isChrome = true;
     } else if (mIsModalContentWindow) {
       newInnerWindow = new nsGlobalModalWindow(this);
     } else {
       newInnerWindow = new nsGlobalWindow(this);
     }
 
     if (!aState) {
       // Freeze the outer window and null out the inner window so
@@ -1912,17 +1907,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
       mInnerWindow = nullptr;
 
       Freeze();
       mCreatingInnerWindow = true;
       // Every script context we are initialized with must create a
       // new global.
       rv = CreateNativeGlobalForInner(cx, newInnerWindow,
-                                      aDocument->GetDocumentURI(), isChrome,
+                                      aDocument->GetDocumentURI(),
                                       aDocument->NodePrincipal(),
                                       &newInnerWindow->mJSObject,
                                       getter_AddRefs(mInnerWindowHolder));
       NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerWindow->mJSObject && mInnerWindowHolder,
                    "Failed to get script global and holder");
 
       mCreatingInnerWindow = false;
       createdInnerWindow = true;
@@ -2513,17 +2508,17 @@ nsGlobalWindow::PreHandleEvent(nsEventCh
 
 bool
 nsGlobalWindow::DialogsAreBlocked(bool *aBeingAbused)
 {
   *aBeingAbused = false;
 
   nsGlobalWindow *topWindow = GetScriptableTop();
   if (!topWindow) {
-    NS_ERROR("DialogsAreBlocked() called without a top window?");
+    NS_ASSERTION(!mDocShell, "DialogsAreBlocked() called without a top window?");
     return true;
   }
 
   topWindow = topWindow->GetCurrentInnerWindowInternal();
   if (!topWindow) {
     return true;
   }
 
@@ -6800,19 +6795,21 @@ nsGlobalWindow::LeaveModalState(nsIDOMWi
         do_QueryInterface(topWin->GetExtantDocument());
       mSuspendedDoc->UnsuppressEventHandlingAndFireEvents(currentDoc == mSuspendedDoc);
       mSuspendedDoc = nullptr;
     }
   }
 
   if (aCallerWin) {
     nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aCallerWin));
-    nsIScriptContext *scx = sgo->GetContext();
-    if (scx)
-      scx->LeaveModalState();
+    if (sgo) {
+      nsIScriptContext *scx = sgo->GetContext();
+      if (scx)
+        scx->LeaveModalState();
+    }
   }
 
   if (mContext) {
     mContext->LeaveModalState();
   }
 
   // Remember the time of the last dialog quit.
   nsGlobalWindow *inner = topWin->GetCurrentInnerWindowInternal();
@@ -7647,19 +7644,21 @@ nsGlobalWindow::ActivateOrDeactivate(boo
   } else {
     // This is a workaround for the following problem:
     // When a window with an open sheet loses focus, only the sheet window
     // receives the NS_DEACTIVATE event. However, it's not the sheet that
     // should lose the active styling, but the containing top level window.
 
     // widgetListener should be a nsXULWindow
     nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
-    nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
-    nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
-    topLevelWindow = do_GetInterface(req);
+    if (listener) {
+      nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
+      nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
+      topLevelWindow = do_GetInterface(req);
+    }
   }
   if (topLevelWindow) {
     nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
     piWin->SetActive(aActivate);
   }
 }
 
 static bool
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -337,18 +337,17 @@ public:
 
   // nsPIDOMWindow
   virtual NS_HIDDEN_(nsPIDOMWindow*) GetPrivateRoot();
   virtual NS_HIDDEN_(void) ActivateOrDeactivate(bool aActivate);
   virtual NS_HIDDEN_(void) SetActive(bool aActive);
   virtual NS_HIDDEN_(void) SetIsBackground(bool aIsBackground);
   virtual NS_HIDDEN_(void) SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler);
 
-  virtual NS_HIDDEN_(void) SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal);
-  virtual NS_HIDDEN_(nsIPrincipal*) GetOpenerScriptPrincipal();
+  virtual NS_HIDDEN_(void) SetInitialPrincipalToSubject();
 
   virtual NS_HIDDEN_(PopupControlState) PushPopupControlState(PopupControlState state, bool aForce) const;
   virtual NS_HIDDEN_(void) PopPopupControlState(PopupControlState state) const;
   virtual NS_HIDDEN_(PopupControlState) GetPopupControlState() const;
 
   virtual NS_HIDDEN_(nsresult) SaveWindowState(nsISupports **aState);
   virtual NS_HIDDEN_(nsresult) RestoreWindowState(nsISupports *aState);
   virtual NS_HIDDEN_(void) SuspendTimeouts(uint32_t aIncrease = 1,
@@ -1009,18 +1008,16 @@ protected:
   nsGlobalWindowObserver*       mObserver;
 #ifndef MOZ_DISABLE_DOMCRYPTO
   nsCOMPtr<nsIDOMCrypto>        mCrypto;
 #endif
   nsCOMPtr<nsIDOMStorage>      mLocalStorage;
   nsCOMPtr<nsIDOMStorage>      mSessionStorage;
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
-  nsCOMPtr<nsIPrincipal> mOpenerScriptPrincipal; // strong; used to determine
-                                                 // whether to clear scope
 
   // These member variable are used only on inner windows.
   nsRefPtr<nsEventListenerManager> mListenerManager;
   // mTimeouts is generally sorted by mWhen, unless mTimeoutInsertionPoint is
   // non-null.  In that case, the dummy timeout pointed to by
   // mTimeoutInsertionPoint may have a later mWhen than some of the timeouts
   // that come after it.
   PRCList                       mTimeouts;
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -43,18 +43,18 @@ class nsIDocument;
 class nsIScriptTimeoutHandler;
 struct nsTimeout;
 template <class> class nsScriptObjectHolder;
 class nsXBLPrototypeHandler;
 class nsIArray;
 class nsPIWindowRoot;
 
 #define NS_PIDOMWINDOW_IID \
-{0x66660102, 0xd875, 0x47e2, \
-  {0xa1, 0xf7, 0x12, 0xbc, 0x83, 0xc9, 0x93, 0xa9}}
+{ 0x0c5763c6, 0x5e87, 0x4f6f, \
+  { 0xa2, 0xef, 0xcf, 0x4d, 0xeb, 0xd1, 0xbc, 0xc3 } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
@@ -275,24 +275,19 @@ public:
       }
 
       win = this;
     }
 
     return win->mIsHandlingResizeEvent;
   }
 
-  // Tell this window who opened it.  This only has an effect if there is
-  // either no document currently in the window or if the document is the
-  // original document this window came with (an about:blank document either
-  // preloaded into it when it was created, or created by
-  // CreateAboutBlankContentViewer()).
-  virtual void SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal) = 0;
-  // Ask this window who opened it.
-  virtual nsIPrincipal* GetOpenerScriptPrincipal() = 0;
+  // Set the window up with an about:blank document with the current subject
+  // principal.
+  virtual void SetInitialPrincipalToSubject() = 0;
 
   virtual PopupControlState PushPopupControlState(PopupControlState aState,
                                                   bool aForce) const = 0;
   virtual void PopPopupControlState(PopupControlState state) const = 0;
   virtual PopupControlState GetPopupControlState() const = 0;
 
   // Returns an object containing the window's state.  This also suspends
   // all running timeouts in the window.
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -776,18 +776,20 @@ nsScriptNameSpaceManager::Observe(nsISup
   // and NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID but we are safe without it.
   // See bug 600460.
 
   return NS_OK;
 }
 
 void
 nsScriptNameSpaceManager::RegisterDefineDOMInterface(const nsAFlatString& aName,
-    mozilla::dom::DefineInterface aDefineDOMInterface)
+    mozilla::dom::DefineInterface aDefineDOMInterface,
+    mozilla::dom::PrefEnabled aPrefEnabled)
 {
   nsGlobalNameStruct *s = AddToHash(&mGlobalNames, &aName);
   if (s) {
     if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
       s->mType = nsGlobalNameStruct::eTypeNewDOMBinding;
     }
     s->mDefineDOMInterface = aDefineDOMInterface;
+    s->mPrefEnabled = aPrefEnabled;
   }
 }
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -63,16 +63,17 @@ struct nsGlobalNameStruct
     nsIID mIID; // eTypeInterface, eTypeClassProto
     nsExternalDOMClassInfoData* mData; // eTypeExternalClassInfo
     ConstructorAlias* mAlias; // eTypeExternalConstructorAlias
     nsCID mCID; // All other types except eTypeNewDOMBinding
   };
 
   // For new style DOM bindings.
   mozilla::dom::DefineInterface mDefineDOMInterface;
+  mozilla::dom::PrefEnabled mPrefEnabled; // May be null if not pref controlled
 
 private:
 
   // copy constructor
 };
 
 
 class nsIScriptContext;
@@ -134,17 +135,18 @@ public:
                              const nsIID **aInterfaces,
                              uint32_t aScriptableFlags,
                              bool aHasClassInterface,
                              const nsCID *aConstructorCID);
 
   nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct);
 
   void RegisterDefineDOMInterface(const nsAFlatString& aName,
-    mozilla::dom::DefineInterface aDefineDOMInterface);
+    mozilla::dom::DefineInterface aDefineDOMInterface,
+    mozilla::dom::PrefEnabled aPrefEnabled);
 
 private:
   // Adds a new entry to the hash and returns the nsGlobalNameStruct
   // that aKey will be mapped to. If mType in the returned
   // nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
   // already existed.
   nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const nsAString *aKey,
                                 const PRUnichar **aClassName = nullptr);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -291,29 +291,27 @@ DOMInterfaces = {
 'OnlyForUseInConstructor' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 
 'TestIndexedGetterInterface' : {
         'headerFile': 'TestBindingHeader.h',
-        'register': False,
-        'infallible': [ 'length' ]
+        'register': False
         },
 
 'TestNamedGetterInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestIndexedAndNamedGetterInterface' : {
         'headerFile': 'TestBindingHeader.h',
-        'register': False,
-        'infallible': [ 'length' ]
+        'register': False
         },
 
 'TestIndexedSetterInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestNamedSetterInterface' : {
@@ -324,17 +322,16 @@ DOMInterfaces = {
 'TestIndexedAndNamedSetterInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False
         },
 
 'TestIndexedAndNamedGetterAndSetterInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False,
-        'infallible': [ 'length', '__stringifier' ],
         'binaryNames': { '__stringifier': 'Stringify' }
         },
 }
 
 # These are temporary, until they've been converted to use new DOM bindings
 def addExternalIface(iface, nativeType=None, headerFile=None):
     domInterface = {
         'concrete': False
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1333,16 +1333,34 @@ class CGDefineDOMInterfaceMethod(CGAbstr
             getter = "GetConstructorObject"
 
         return ("  JSObject* global = JS_GetGlobalForObject(aCx, aReceiver);\n" +
                 CheckPref(self.descriptor, "global", "*aEnabled", "false") + 
                 """
   *aEnabled = true;
   return !!%s(aCx, global, aReceiver);""" % (getter))
 
+class CGPrefEnabled(CGAbstractMethod):
+    """
+    A method for testing whether the preference controlling this
+    interface is enabled.  When it's not, the interface should not be
+    visible on the global.
+    """
+    def __init__(self, descriptor):
+        CGAbstractMethod.__init__(self, descriptor, 'PrefEnabled', 'bool', [])
+
+    def declare(self):
+        return CGAbstractMethod.declare(self)
+
+    def define(self):
+        return CGAbstractMethod.define(self)
+
+    def definition_body(self):
+        return "  return %s::PrefEnabled();" % self.descriptor.nativeType
+
 class CGIsMethod(CGAbstractMethod):
     def __init__(self, descriptor):
         args = [Argument('JSObject*', 'obj')]
         CGAbstractMethod.__init__(self, descriptor, 'Is', 'bool', args)
 
     def definition_body(self):
         # Non-proxy implementation would check
         #   js::GetObjectJSClass(obj) == &Class.mBase
@@ -2833,22 +2851,27 @@ def getRetvalDeclarationForType(returnTy
 def isResultAlreadyAddRefed(descriptor, extendedAttributes):
     # Default to already_AddRefed on the main thread, raw pointer in workers
     return not descriptor.workers and not 'resultNotAddRefed' in extendedAttributes
 
 class CGCallGenerator(CGThing):
     """
     A class to generate an actual call to a C++ object.  Assumes that the C++
     object is stored in a variable whose name is given by the |object| argument.
+
+    errorReport should be a CGThing for an error report or None if no
+    error reporting is needed.
     """
     def __init__(self, errorReport, arguments, argsPre, returnType,
                  extendedAttributes, descriptorProvider, nativeMethodName,
                  static, object="self", declareResult=True):
         CGThing.__init__(self)
 
+        assert errorReport is None or isinstance(errorReport, CGThing)
+
         isFallible = errorReport is not None
 
         resultAlreadyAddRefed = isResultAlreadyAddRefed(descriptorProvider,
                                                         extendedAttributes)
         (result, resultOutParam) = getRetvalDeclarationForType(returnType,
                                                                descriptorProvider,
                                                                resultAlreadyAddRefed)
 
@@ -2968,18 +2991,21 @@ class CGPerSignatureCall(CGThing):
 
     def isFallible(self):
         return not 'infallible' in self.extendedAttributes
 
     def wrap_return_value(self):
         isCreator = memberIsCreator(self.idlNode)
         if isCreator:
             # We better be returning addrefed things!
-            assert isResultAlreadyAddRefed(self.descriptor,
-                                           self.extendedAttributes)
+            assert(isResultAlreadyAddRefed(self.descriptor,
+                                           self.extendedAttributes) or
+                   # Workers use raw pointers for new-object return
+                   # values or something
+                   self.descriptor.workers)
 
         resultTemplateValues = { 'jsvalRef': '*vp', 'jsvalPtr': 'vp',
                                  'isCreator': isCreator}
         try:
             return wrapForType(self.returnType, self.descriptor,
                                resultTemplateValues)
         except MethodNotCreatorError, err:
             assert not isCreator
@@ -4820,18 +4846,19 @@ class CGDOMJSProxyHandler_obj_toString(C
         if stringifier:
             name = stringifier.identifier.name
             nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
             signature = stringifier.signatures()[0]
             returnType = signature[0]
             extendedAttributes = self.descriptor.getExtendedAttributes(stringifier)
             infallible = 'infallible' in extendedAttributes
             if not infallible:
-                error = ('ThrowMethodFailedWithDetails(cx, rv, "%s", "toString")\n' +
-                         "return NULL;") % self.descriptor.interface.identifier.name
+                error = CGGeneric(
+                    ('ThrowMethodFailedWithDetails(cx, rv, "%s", "toString");\n' +
+                     "return NULL;") % self.descriptor.interface.identifier.name)
             else:
                 error = None
             call = CGCallGenerator(error, [], "", returnType, extendedAttributes, self.descriptor, nativeName, False, object="UnwrapProxy(proxy)")
             return call.define() + """
 
 JSString* jsresult;
 return xpc_qsStringToJsstring(cx, result, &jsresult) ? jsresult : NULL;""" 
 
@@ -4985,16 +5012,21 @@ class CGDescriptor(CGThing):
             if descriptor.concrete and descriptor.proxy:
                 cgThings.append(CGResolveOwnProperty(descriptor))
                 cgThings.append(CGEnumerateOwnProperties(descriptor))
             cgThings.append(CGResolveProperty(descriptor, properties))
             cgThings.append(CGEnumerateProperties(descriptor, properties))
 
         if descriptor.interface.hasInterfaceObject():
             cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
+            if (not descriptor.interface.isExternal() and
+                # Workers stuff is never pref-controlled
+                not descriptor.workers and
+                descriptor.interface.getExtendedAttribute("PrefControlled") is not None):
+                cgThings.append(CGPrefEnabled(descriptor))
 
         if descriptor.interface.hasInterfacePrototypeObject():
             cgThings.append(CGNativePropertyHooks(descriptor))
 
         if descriptor.concrete:
             if descriptor.proxy:
                 cgThings.append(CGProxyIsProxy(descriptor))
                 cgThings.append(CGProxyUnwrap(descriptor))
@@ -5108,19 +5140,20 @@ class CGDictionary(CGThing):
         return (string.Template(
                 "struct ${selfName} ${inheritance}{\n"
                 "  ${selfName}() {}\n"
                 "  bool Init(JSContext* cx, const JS::Value& val);\n"
                 "\n" +
                 "\n".join(memberDecls) + "\n"
                 "private:\n"
                 "  // Disallow copy-construction\n"
-                "  ${selfName}(const ${selfName}&) MOZ_DELETE;\n"
-                "  static bool InitIds(JSContext* cx);\n"
-                "  static bool initedIds;\n" +
+                "  ${selfName}(const ${selfName}&) MOZ_DELETE;\n" +
+                # NOTE: jsids are per-runtime, so don't use them in workers
+                ("  static bool InitIds(JSContext* cx);\n"
+                 "  static bool initedIds;\n" if not self.workers else "") +
                 "\n".join("  static jsid " +
                           self.makeIdName(m.identifier.name) + ";" for
                           m in d.members) + "\n"
                 "};").substitute( { "selfName": self.makeClassName(d),
                                     "inheritance": inheritance }))
 
     def define(self):
         if not self.generatable:
@@ -5142,36 +5175,38 @@ class CGDictionary(CGThing):
         idinit = CGList(idinit, " ||\n")
         idinit = CGWrapper(idinit, pre="if (",
                            post=(") {\n"
                                  "  return false;\n"
                                  "}"),
                            reindent=True)
 
         return string.Template(
-            "bool ${selfName}::initedIds = false;\n" +
-            "\n".join("jsid ${selfName}::%s = JSID_VOID;" %
-                      self.makeIdName(m.identifier.name)
-                      for m in d.members) + "\n"
-            "\n"
-            "bool\n"
-            "${selfName}::InitIds(JSContext* cx)\n"
-            "{\n"
-            "  MOZ_ASSERT(!initedIds);\n"
-            "${idInit}\n"
-            "  initedIds = true;\n"
-            "  return true;\n"
-            "}\n"
-            "\n"
+            # NOTE: jsids are per-runtime, so don't use them in workers
+            ("bool ${selfName}::initedIds = false;\n" +
+             "\n".join("jsid ${selfName}::%s = JSID_VOID;" %
+                       self.makeIdName(m.identifier.name)
+                       for m in d.members) + "\n"
+             "\n"
+             "bool\n"
+             "${selfName}::InitIds(JSContext* cx)\n"
+             "{\n"
+             "  MOZ_ASSERT(!initedIds);\n"
+             "${idInit}\n"
+             "  initedIds = true;\n"
+             "  return true;\n"
+             "}\n"
+             "\n" if not self.workers else "") +
             "bool\n"
             "${selfName}::Init(JSContext* cx, const JS::Value& val)\n"
-            "{\n"
-            "  if (!initedIds && !InitIds(cx)) {\n"
-            "    return false;\n"
-            "  }\n"
+            "{\n" +
+            # NOTE: jsids are per-runtime, so don't use them in workers
+            ("  if (!initedIds && !InitIds(cx)) {\n"
+             "    return false;\n"
+             "  }\n" if not self.workers else "") +
             "${initParent}"
             "  JSBool found;\n"
             "  JS::Value temp;\n"
             "  bool isNull = val.isNullOrUndefined();\n"
             "  if (!isNull && !val.isObject()) {\n"
             "    return Throw<${isMainThread}>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
             "  }\n"
             "\n"
@@ -5221,39 +5256,54 @@ class CGDictionary(CGThing):
                          "holderName": "holder"}
         # We can't handle having a holderType here
         assert holderType is None
         if dealWithOptional:
             replacements["declName"] = "(" + replacements["declName"] + ".Value())"
         if member.defaultValue:
             replacements["haveValue"] = "found"
 
+        # NOTE: jsids are per-runtime, so don't use them in workers
+        if self.workers:
+            propName = member.identifier.name
+            propCheck = ('JS_HasProperty(cx, &val.toObject(), "%s", &found)' %
+                         propName)
+            propGet = ('JS_GetProperty(cx, &val.toObject(), "%s", &temp)' %
+                       propName)
+        else:
+            propId = self.makeIdName(member.identifier.name);
+            propCheck = ("JS_HasPropertyById(cx, &val.toObject(), %s, &found)" %
+                         propId)
+            propGet = ("JS_GetPropertyById(cx, &val.toObject(), %s, &temp)" %
+                       propId)
+
         conversionReplacements = {
-            "propId" : self.makeIdName(member.identifier.name),
             "prop": "(this->%s)" % member.identifier.name,
-            "convert": string.Template(templateBody).substitute(replacements)
+            "convert": string.Template(templateBody).substitute(replacements),
+            "propCheck": propCheck,
+            "propGet": propGet
             }
         conversion = ("if (isNull) {\n"
                       "  found = false;\n"
-                      "} else if (!JS_HasPropertyById(cx, &val.toObject(), ${propId}, &found)) {\n"
+                      "} else if (!${propCheck}) {\n"
                       "  return false;\n"
                       "}\n")
         if member.defaultValue:
             conversion += (
                 "if (found) {\n"
-                "  if (!JS_GetPropertyById(cx, &val.toObject(), ${propId}, &temp)) {\n"
+                "  if (!${propGet}) {\n"
                 "    return false;\n"
                 "  }\n"
                 "}\n"
                 "${convert}")
         else:
             conversion += (
                 "if (found) {\n"
                 "  ${prop}.Construct();\n"
-                "  if (!JS_GetPropertyById(cx, &val.toObject(), ${propId}, &temp)) {\n"
+                "  if (!${propGet}) {\n"
                 "    return false;\n"
                 "  }\n"
                 "${convert}\n"
                 "}")
             conversionReplacements["convert"] = CGIndenter(
                 CGGeneric(conversionReplacements["convert"])).define()
         
         return CGGeneric(
@@ -5278,22 +5328,26 @@ class CGDictionary(CGThing):
 class CGRegisterProtos(CGAbstractMethod):
     def __init__(self, config):
         CGAbstractMethod.__init__(self, None, 'Register', 'void',
                                   [Argument('nsScriptNameSpaceManager*', 'aNameSpaceManager')])
         self.config = config
 
     def _defineMacro(self):
        return """
-#define REGISTER_PROTO(_dom_class) \\
-  aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface);\n\n"""
+#define REGISTER_PROTO(_dom_class, _pref_check) \\
+  aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface, _pref_check);\n\n"""
     def _undefineMacro(self):
         return "\n#undef REGISTER_PROTO"
     def _registerProtos(self):
-        lines = ["REGISTER_PROTO(%s);" % desc.name
+        def getPrefCheck(desc):
+            if desc.interface.getExtendedAttribute("PrefControlled") is None:
+                return "nullptr"
+            return "%sBinding::PrefEnabled" % desc.name
+        lines = ["REGISTER_PROTO(%s, %s);" % (desc.name, getPrefCheck(desc))
                  for desc in self.config.getDescriptors(hasInterfaceObject=True,
                                                         isExternal=False,
                                                         workers=False,
                                                         register=True)]
         return '\n'.join(lines) + '\n'
     def definition_body(self):
         return self._defineMacro() + self._registerProtos() + self._undefineMacro()
 
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -260,17 +260,17 @@ class Descriptor(DescriptorProvider):
                 if config == '*':
                     iface = self.interface
                     while iface:
                         add('all', map(lambda m: m.name, iface.members), attribute)
                         iface = iface.parent
                 else:
                     add('all', [config], attribute)
 
-        for attribute in ['infallible', 'implicitJSContext', 'resultNotAddRefed']:
+        for attribute in ['implicitJSContext', 'resultNotAddRefed']:
             addExtendedAttribute(attribute, desc.get(attribute, {}))
 
         self.binaryNames = desc.get('binaryNames', {})
 
         # Build the prototype chain.
         self.prototypeChain = []
         parent = interface
         while parent:
@@ -285,43 +285,39 @@ class Descriptor(DescriptorProvider):
         # interface prototype object as they're going to use QI (on main thread)
         # or be passed as a JSObject (on worker threads).
         if self.interface.isExternal():
             return False
 
         return self.interface.hasInterfaceObject() or self.interface.hasInterfacePrototypeObject()
 
     def getExtendedAttributes(self, member, getter=False, setter=False):
-        def ensureValidInfallibleExtendedAttribute(attr):
+        def ensureValidThrowsExtendedAttribute(attr):
             assert(attr is None or attr is True or len(attr) == 1)
             if (attr is not None and attr is not True and
                 'Workers' not in attr and 'MainThread' not in attr):
-                raise TypeError("Unknown value for 'infallible': " + attr[0])
+                raise TypeError("Unknown value for 'Throws': " + attr[0])
+
+        def maybeAppendInfallibleToAttrs(attrs, throws):
+            ensureValidThrowsExtendedAttribute(throws)
+            if (throws is None or
+                (throws is not True and
+                 ('Workers' not in throws or not self.workers) and
+                 ('MainThread' not in throws or self.workers))):
+                attrs.append("infallible")
 
         name = member.identifier.name
         if member.isMethod():
             attrs = self.extendedAttributes['all'].get(name, [])
-            infallible = member.getExtendedAttribute("Infallible")
-            ensureValidInfallibleExtendedAttribute(infallible)
-            if (infallible is not None and
-                (infallible is True or
-                 ('Workers' in infallible and self.workers) or
-                 ('MainThread' in infallible and not self.workers))):
-                attrs.append("infallible")
+            throws = member.getExtendedAttribute("Throws")
+            maybeAppendInfallibleToAttrs(attrs, throws)
             return attrs
 
         assert member.isAttr()
         assert bool(getter) != bool(setter)
         key = 'getterOnly' if getter else 'setterOnly'
         attrs = self.extendedAttributes['all'].get(name, []) + self.extendedAttributes[key].get(name, [])
-        infallible = member.getExtendedAttribute("Infallible")
-        if infallible is None:
-            infallibleAttr = "GetterInfallible" if getter else "SetterInfallible"
-            infallible = member.getExtendedAttribute(infallibleAttr)
-
-        ensureValidInfallibleExtendedAttribute(infallible)
-        if (infallible is not None and
-            (infallible is True or
-             ('Workers' in infallible and self.workers) or
-             ('MainThread' in infallible and not self.workers))):
-            attrs.append("infallible")
-
+        throws = member.getExtendedAttribute("Throws")
+        if throws is None:
+            throwsAttr = "GetterThrows" if getter else "SetterThrows"
+            throws = member.getExtendedAttribute(throwsAttr)
+        maybeAppendInfallibleToAttrs(attrs, throws)
         return attrs
--- a/dom/bindings/GenerateCSS2PropertiesWebIDL.py
+++ b/dom/bindings/GenerateCSS2PropertiesWebIDL.py
@@ -3,17 +3,17 @@
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import sys
 import string
 
 propList = eval(sys.stdin.read())
 props = ""
 for [prop, pref] in propList:
-    extendedAttrs = ["TreatNullAs=EmptyString"]
+    extendedAttrs = ["Throws", "TreatNullAs=EmptyString"]
     if pref is not "":
         extendedAttrs.append("Pref=%s" % pref)
     if not prop.startswith("Moz"):
         prop = prop[0].lower() + prop[1:]
     # Unfortunately, even some of the getters here are fallible
     # (e.g. on nsComputedDOMStyle).
     props += "  [%s] attribute DOMString %s;\n" % (", ".join(extendedAttrs),
                                                    prop)
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -671,19 +671,21 @@ class IDLInterface(IDLObjectWithScope):
                 args = attrlist[0] if len(attrlist) else []
 
                 retType = IDLWrapperType(self.location, self)
                 
                 identifier = IDLUnresolvedIdentifier(self.location, "constructor",
                                                      allowForbidden=True)
 
                 method = IDLMethod(self.location, identifier, retType, args)
-                # Constructors are always Creators and never have any
-                # other extended attributes.
-                method.addExtendedAttributes(["Creator"])
+                # Constructors are always Creators and are always
+                # assumed to be able to throw (since there's no way to
+                # indicate otherwise) and never have any other
+                # extended attributes.
+                method.addExtendedAttributes([("Creator",), ("Throws",)])
                 method.resolve(self)
 
             self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
 
     def addImplementedInterface(self, implementedInterface):
         assert(isinstance(implementedInterface, IDLInterface))
         self.implementedInterfaces.add(implementedInterface)
 
@@ -731,16 +733,19 @@ class IDLInterface(IDLObjectWithScope):
         if otherInterface in self.implementedInterfaces:
             return self
         for iface in self.implementedInterfaces:
             loopPoint = iface.findInterfaceLoopPoint(otherInterface)
             if loopPoint:
                 return loopPoint
         return None
 
+    def getExtendedAttribute(self, name):
+        return self._extendedAttrDict.get(name, None)
+
 class IDLDictionary(IDLObjectWithScope):
     def __init__(self, location, parentScope, name, parent, members):
         assert isinstance(parentScope, IDLScope)
         assert isinstance(name, IDLUnresolvedIdentifier)
         assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
 
         self.parent = parent
         self._finished = False
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -45,19 +45,19 @@ class IndirectlyImplementedInterface : p
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_INDIRECTLY_IMPLEMENTED_INTERFACE_IID)
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
-  bool GetIndirectlyImplementedProperty(ErrorResult&);
-  void SetIndirectlyImplementedProperty(bool, ErrorResult&);
-  void IndirectlyImplementedMethod(ErrorResult&);
+  bool GetIndirectlyImplementedProperty();
+  void SetIndirectlyImplementedProperty(bool);
+  void IndirectlyImplementedMethod();
 };
 
 // IID for the TestExternalInterface
 #define NS_TEST_EXTERNAL_INTERFACE_IID \
 { 0xd5ba0c99, 0x9b1d, 0x4e71, \
  { 0x8a, 0x94, 0x56, 0x38, 0x6c, 0xa3, 0xda, 0x3d } }
 class TestExternalInterface : public nsISupports
 {
@@ -123,539 +123,513 @@ public:
   /*  static
   already_AddRefed<TestInterface> Constructor(nsISupports*,
                                               uint32_t, uint32_t,
                                               const TestInterfaceOrOnlyForUseInConstructor&,
                                               ErrorResult&);
   */
   
   // Integer types
-  int8_t GetReadonlyByte(ErrorResult&);
-  int8_t GetWritableByte(ErrorResult&);
-  void SetWritableByte(int8_t, ErrorResult&);
-  void PassByte(int8_t, ErrorResult&);
-  int8_t ReceiveByte(ErrorResult&);
-  void PassOptionalByte(const Optional<int8_t>&, ErrorResult&);
-  void PassOptionalByteWithDefault(int8_t, ErrorResult&);
-  void PassNullableByte(Nullable<int8_t>&, ErrorResult&);
-  void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&,
-                                ErrorResult&);
+  int8_t GetReadonlyByte();
+  int8_t GetWritableByte();
+  void SetWritableByte(int8_t);
+  void PassByte(int8_t);
+  int8_t ReceiveByte();
+  void PassOptionalByte(const Optional<int8_t>&);
+  void PassOptionalByteWithDefault(int8_t);
+  void PassNullableByte(Nullable<int8_t>&);
+  void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&);
 
-  int16_t GetReadonlyShort(ErrorResult&);
-  int16_t GetWritableShort(ErrorResult&);
-  void SetWritableShort(int16_t, ErrorResult&);
-  void PassShort(int16_t, ErrorResult&);
-  int16_t ReceiveShort(ErrorResult&);
-  void PassOptionalShort(const Optional<int16_t>&, ErrorResult&);
-  void PassOptionalShortWithDefault(int16_t, ErrorResult&);
+  int16_t GetReadonlyShort();
+  int16_t GetWritableShort();
+  void SetWritableShort(int16_t);
+  void PassShort(int16_t);
+  int16_t ReceiveShort();
+  void PassOptionalShort(const Optional<int16_t>&);
+  void PassOptionalShortWithDefault(int16_t);
 
-  int32_t GetReadonlyLong(ErrorResult&);
-  int32_t GetWritableLong(ErrorResult&);
-  void SetWritableLong(int32_t, ErrorResult&);
-  void PassLong(int32_t, ErrorResult&);
-  int16_t ReceiveLong(ErrorResult&);
-  void PassOptionalLong(const Optional<int32_t>&, ErrorResult&);
-  void PassOptionalLongWithDefault(int32_t, ErrorResult&);
+  int32_t GetReadonlyLong();
+  int32_t GetWritableLong();
+  void SetWritableLong(int32_t);
+  void PassLong(int32_t);
+  int16_t ReceiveLong();
+  void PassOptionalLong(const Optional<int32_t>&);
+  void PassOptionalLongWithDefault(int32_t);
 
-  int64_t GetReadonlyLongLong(ErrorResult&);
-  int64_t GetWritableLongLong(ErrorResult&);
-  void SetWritableLongLong(int64_t, ErrorResult&);
-  void PassLongLong(int64_t, ErrorResult&);
-  int64_t ReceiveLongLong(ErrorResult&);
-  void PassOptionalLongLong(const Optional<int64_t>&, ErrorResult&);
-  void PassOptionalLongLongWithDefault(int64_t, ErrorResult&);
+  int64_t GetReadonlyLongLong();
+  int64_t GetWritableLongLong();
+  void SetWritableLongLong(int64_t);
+  void PassLongLong(int64_t);
+  int64_t ReceiveLongLong();
+  void PassOptionalLongLong(const Optional<int64_t>&);
+  void PassOptionalLongLongWithDefault(int64_t);
 
-  uint8_t GetReadonlyOctet(ErrorResult&);
-  uint8_t GetWritableOctet(ErrorResult&);
-  void SetWritableOctet(uint8_t, ErrorResult&);
-  void PassOctet(uint8_t, ErrorResult&);
-  uint8_t ReceiveOctet(ErrorResult&);
-  void PassOptionalOctet(const Optional<uint8_t>&, ErrorResult&);
-  void PassOptionalOctetWithDefault(uint8_t, ErrorResult&);
+  uint8_t GetReadonlyOctet();
+  uint8_t GetWritableOctet();
+  void SetWritableOctet(uint8_t);
+  void PassOctet(uint8_t);
+  uint8_t ReceiveOctet();
+  void PassOptionalOctet(const Optional<uint8_t>&);
+  void PassOptionalOctetWithDefault(uint8_t);
 
-  uint16_t GetReadonlyUnsignedShort(ErrorResult&);
-  uint16_t GetWritableUnsignedShort(ErrorResult&);
-  void SetWritableUnsignedShort(uint16_t, ErrorResult&);
-  void PassUnsignedShort(uint16_t, ErrorResult&);
-  uint16_t ReceiveUnsignedShort(ErrorResult&);
-  void PassOptionalUnsignedShort(const Optional<uint16_t>&, ErrorResult&);
-  void PassOptionalUnsignedShortWithDefault(uint16_t, ErrorResult&);
+  uint16_t GetReadonlyUnsignedShort();
+  uint16_t GetWritableUnsignedShort();
+  void SetWritableUnsignedShort(uint16_t);
+  void PassUnsignedShort(uint16_t);
+  uint16_t ReceiveUnsignedShort();
+  void PassOptionalUnsignedShort(const Optional<uint16_t>&);
+  void PassOptionalUnsignedShortWithDefault(uint16_t);
 
-  uint32_t GetReadonlyUnsignedLong(ErrorResult&);
-  uint32_t GetWritableUnsignedLong(ErrorResult&);
-  void SetWritableUnsignedLong(uint32_t, ErrorResult&);
-  void PassUnsignedLong(uint32_t, ErrorResult&);
-  uint32_t ReceiveUnsignedLong(ErrorResult&);
-  void PassOptionalUnsignedLong(const Optional<uint32_t>&, ErrorResult&);
-  void PassOptionalUnsignedLongWithDefault(uint32_t, ErrorResult&);
+  uint32_t GetReadonlyUnsignedLong();
+  uint32_t GetWritableUnsignedLong();
+  void SetWritableUnsignedLong(uint32_t);
+  void PassUnsignedLong(uint32_t);
+  uint32_t ReceiveUnsignedLong();
+  void PassOptionalUnsignedLong(const Optional<uint32_t>&);
+  void PassOptionalUnsignedLongWithDefault(uint32_t);
 
-  uint64_t GetReadonlyUnsignedLongLong(ErrorResult&);
-  uint64_t GetWritableUnsignedLongLong(ErrorResult&);
-  void SetWritableUnsignedLongLong(uint64_t, ErrorResult&);
-  void PassUnsignedLongLong(uint64_t, ErrorResult&);
-  uint64_t ReceiveUnsignedLongLong(ErrorResult&);
-  void PassOptionalUnsignedLongLong(const Optional<uint64_t>&, ErrorResult&);
-  void PassOptionalUnsignedLongLongWithDefault(uint64_t, ErrorResult&);
+  uint64_t GetReadonlyUnsignedLongLong();
+  uint64_t GetWritableUnsignedLongLong();
+  void SetWritableUnsignedLongLong(uint64_t);
+  void PassUnsignedLongLong(uint64_t);
+  uint64_t ReceiveUnsignedLongLong();
+  void PassOptionalUnsignedLongLong(const Optional<uint64_t>&);
+  void PassOptionalUnsignedLongLongWithDefault(uint64_t);
 
   // Interface types
-  already_AddRefed<TestInterface> ReceiveSelf(ErrorResult&);
-  already_AddRefed<TestInterface> ReceiveNullableSelf(ErrorResult&);
-  TestInterface* ReceiveWeakSelf(ErrorResult&);
-  TestInterface* ReceiveWeakNullableSelf(ErrorResult&);
-  void PassSelf(TestInterface&, ErrorResult&);
-  void PassSelf2(NonNull<TestInterface>&, ErrorResult&);
-  void PassNullableSelf(TestInterface*, ErrorResult&);
-  already_AddRefed<TestInterface> GetNonNullSelf(ErrorResult&);
-  void SetNonNullSelf(TestInterface&, ErrorResult&);
-  already_AddRefed<TestInterface> GetNullableSelf(ErrorResult&);
-  void SetNullableSelf(TestInterface*, ErrorResult&);
-  void PassOptionalSelf(const Optional<TestInterface*> &, ErrorResult&);
-  void PassOptionalNonNullSelf(const Optional<NonNull<TestInterface> >&, ErrorResult&);
-  void PassOptionalSelfWithDefault(TestInterface*, ErrorResult&);
+  already_AddRefed<TestInterface> ReceiveSelf();
+  already_AddRefed<TestInterface> ReceiveNullableSelf();
+  TestInterface* ReceiveWeakSelf();
+  TestInterface* ReceiveWeakNullableSelf();
+  void PassSelf(TestInterface&);
+  void PassSelf2(NonNull<TestInterface>&);
+  void PassNullableSelf(TestInterface*);
+  already_AddRefed<TestInterface> GetNonNullSelf();
+  void SetNonNullSelf(TestInterface&);
+  already_AddRefed<TestInterface> GetNullableSelf();
+  void SetNullableSelf(TestInterface*);
+  void PassOptionalSelf(const Optional<TestInterface*> &);
+  void PassOptionalNonNullSelf(const Optional<NonNull<TestInterface> >&);
+  void PassOptionalSelfWithDefault(TestInterface*);
 
-  already_AddRefed<TestNonWrapperCacheInterface> ReceiveNonWrapperCacheInterface(ErrorResult&);
-  already_AddRefed<TestNonWrapperCacheInterface> ReceiveNullableNonWrapperCacheInterface(ErrorResult&);
-  void ReceiveNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&, ErrorResult&);
-  void ReceiveNullableNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&, ErrorResult&);
-  void ReceiveNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&, ErrorResult&);
-  void ReceiveNullableNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&, ErrorResult&);
+  already_AddRefed<TestNonWrapperCacheInterface> ReceiveNonWrapperCacheInterface();
+  already_AddRefed<TestNonWrapperCacheInterface> ReceiveNullableNonWrapperCacheInterface();
+  void ReceiveNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&);
+  void ReceiveNullableNonWrapperCacheInterfaceSequence(nsTArray<nsRefPtr<TestNonWrapperCacheInterface> >&);
+  void ReceiveNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&);
+  void ReceiveNullableNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&);
 
-  already_AddRefed<TestNonCastableInterface> ReceiveOther(ErrorResult&);
-  already_AddRefed<TestNonCastableInterface> ReceiveNullableOther(ErrorResult&);
-  TestNonCastableInterface* ReceiveWeakOther(ErrorResult&);
-  TestNonCastableInterface* ReceiveWeakNullableOther(ErrorResult&);
-  void PassOther(TestNonCastableInterface&, ErrorResult&);
-  void PassOther2(NonNull<TestNonCastableInterface>&, ErrorResult&);
-  void PassNullableOther(TestNonCastableInterface*, ErrorResult&);
-  already_AddRefed<TestNonCastableInterface> GetNonNullOther(ErrorResult&);
-  void SetNonNullOther(TestNonCastableInterface&, ErrorResult&);
-  already_AddRefed<TestNonCastableInterface> GetNullableOther(ErrorResult&);
-  void SetNullableOther(TestNonCastableInterface*, ErrorResult&);
-  void PassOptionalOther(const Optional<TestNonCastableInterface*>&, ErrorResult&);
-  void PassOptionalNonNullOther(const Optional<NonNull<TestNonCastableInterface> >&, ErrorResult&);
-  void PassOptionalOtherWithDefault(TestNonCastableInterface*, ErrorResult&);
+  already_AddRefed<TestNonCastableInterface> ReceiveOther();
+  already_AddRefed<TestNonCastableInterface> ReceiveNullableOther();
+  TestNonCastableInterface* ReceiveWeakOther();
+  TestNonCastableInterface* ReceiveWeakNullableOther();
+  void PassOther(TestNonCastableInterface&);
+  void PassOther2(NonNull<TestNonCastableInterface>&);
+  void PassNullableOther(TestNonCastableInterface*);
+  already_AddRefed<TestNonCastableInterface> GetNonNullOther();
+  void SetNonNullOther(TestNonCastableInterface&);
+  already_AddRefed<TestNonCastableInterface> GetNullableOther();
+  void SetNullableOther(TestNonCastableInterface*);
+  void PassOptionalOther(const Optional<TestNonCastableInterface*>&);
+  void PassOptionalNonNullOther(const Optional<NonNull<TestNonCastableInterface> >&);
+  void PassOptionalOtherWithDefault(TestNonCastableInterface*);
 
-  already_AddRefed<TestExternalInterface> ReceiveExternal(ErrorResult&);
-  already_AddRefed<TestExternalInterface> ReceiveNullableExternal(ErrorResult&);
-  TestExternalInterface* ReceiveWeakExternal(ErrorResult&);
-  TestExternalInterface* ReceiveWeakNullableExternal(ErrorResult&);
-  void PassExternal(TestExternalInterface*, ErrorResult&);
-  void PassExternal2(TestExternalInterface*, ErrorResult&);
-  void PassNullableExternal(TestExternalInterface*, ErrorResult&);
-  already_AddRefed<TestExternalInterface> GetNonNullExternal(ErrorResult&);
-  void SetNonNullExternal(TestExternalInterface*, ErrorResult&);
-  already_AddRefed<TestExternalInterface> GetNullableExternal(ErrorResult&);
-  void SetNullableExternal(TestExternalInterface*, ErrorResult&);
-  void PassOptionalExternal(const Optional<TestExternalInterface*>&, ErrorResult&);
-  void PassOptionalNonNullExternal(const Optional<TestExternalInterface*>&, ErrorResult&);
-  void PassOptionalExternalWithDefault(TestExternalInterface*, ErrorResult&);
+  already_AddRefed<TestExternalInterface> ReceiveExternal();
+  already_AddRefed<TestExternalInterface> ReceiveNullableExternal();
+  TestExternalInterface* ReceiveWeakExternal();
+  TestExternalInterface* ReceiveWeakNullableExternal();
+  void PassExternal(TestExternalInterface*);
+  void PassExternal2(TestExternalInterface*);
+  void PassNullableExternal(TestExternalInterface*);
+  already_AddRefed<TestExternalInterface> GetNonNullExternal();
+  void SetNonNullExternal(TestExternalInterface*);
+  already_AddRefed<TestExternalInterface> GetNullableExternal();
+  void SetNullableExternal(TestExternalInterface*);
+  void PassOptionalExternal(const Optional<TestExternalInterface*>&);
+  void PassOptionalNonNullExternal(const Optional<TestExternalInterface*>&);
+  void PassOptionalExternalWithDefault(TestExternalInterface*);
 
-  already_AddRefed<TestCallbackInterface> ReceiveCallbackInterface(ErrorResult&);
-  already_AddRefed<TestCallbackInterface> ReceiveNullableCallbackInterface(ErrorResult&);
-  TestCallbackInterface* ReceiveWeakCallbackInterface(ErrorResult&);
-  TestCallbackInterface* ReceiveWeakNullableCallbackInterface(ErrorResult&);
-  void PassCallbackInterface(TestCallbackInterface&, ErrorResult&);
-  void PassCallbackInterface2(OwningNonNull<TestCallbackInterface>, ErrorResult&);
-  void PassNullableCallbackInterface(TestCallbackInterface*, ErrorResult&);
-  already_AddRefed<TestCallbackInterface> GetNonNullCallbackInterface(ErrorResult&);
-  void SetNonNullCallbackInterface(TestCallbackInterface&, ErrorResult&);
-  already_AddRefed<TestCallbackInterface> GetNullableCallbackInterface(ErrorResult&);
-  void SetNullableCallbackInterface(TestCallbackInterface*, ErrorResult&);
-  void PassOptionalCallbackInterface(const Optional<nsRefPtr<TestCallbackInterface> >&, ErrorResult&);
-  void PassOptionalNonNullCallbackInterface(const Optional<OwningNonNull<TestCallbackInterface> >&, ErrorResult&);
-  void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*, ErrorResult&);
+  already_AddRefed<TestCallbackInterface> ReceiveCallbackInterface();
+  already_AddRefed<TestCallbackInterface> ReceiveNullableCallbackInterface();
+  TestCallbackInterface* ReceiveWeakCallbackInterface();
+  TestCallbackInterface* ReceiveWeakNullableCallbackInterface();
+  void PassCallbackInterface(TestCallbackInterface&);
+  void PassCallbackInterface2(OwningNonNull<TestCallbackInterface>);
+  void PassNullableCallbackInterface(TestCallbackInterface*);
+  already_AddRefed<TestCallbackInterface> GetNonNullCallbackInterface();
+  void SetNonNullCallbackInterface(TestCallbackInterface&);
+  already_AddRefed<TestCallbackInterface> GetNullableCallbackInterface();
+  void SetNullableCallbackInterface(TestCallbackInterface*);
+  void PassOptionalCallbackInterface(const Optional<nsRefPtr<TestCallbackInterface> >&);
+  void PassOptionalNonNullCallbackInterface(const Optional<OwningNonNull<TestCallbackInterface> >&);
+  void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*);
 
-  already_AddRefed<IndirectlyImplementedInterface> ReceiveConsequentialInterface(ErrorResult&);
-  void PassConsequentialInterface(IndirectlyImplementedInterface&, ErrorResult&);
+  already_AddRefed<IndirectlyImplementedInterface> ReceiveConsequentialInterface();
+  void PassConsequentialInterface(IndirectlyImplementedInterface&);
 
   // Sequence types
-  void ReceiveSequence(nsTArray<int32_t>&, ErrorResult&);
-  void ReceiveNullableSequence(Nullable< nsTArray<int32_t> >&, ErrorResult&);
-  void ReceiveSequenceOfNullableInts(nsTArray< Nullable<int32_t> >&, ErrorResult&);
-  void ReceiveNullableSequenceOfNullableInts(Nullable< nsTArray< Nullable<int32_t> > >&, ErrorResult&);
-  void PassSequence(const Sequence<int32_t> &, ErrorResult&);
-  void PassNullableSequence(const Nullable< Sequence<int32_t> >&, ErrorResult&);
-  void PassSequenceOfNullableInts(const Sequence<Nullable<int32_t> >&, ErrorResult&);
-  void PassOptionalSequenceOfNullableInts(const Optional<Sequence<Nullable<int32_t> > > &,
-                                          ErrorResult&);
-  void PassOptionalNullableSequenceOfNullableInts(const Optional<Nullable<Sequence<Nullable<int32_t> > > > &,
-                                                  ErrorResult&);
-  void ReceiveCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &,
-                                     ErrorResult&);
-  void ReceiveNullableCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &,
-                                             ErrorResult&);
-  void ReceiveCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&,
-                                             ErrorResult&);
-  void ReceiveNullableCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&,
-                                             ErrorResult&);
-  void ReceiveWeakCastableObjectSequence(nsTArray<TestInterface*> &,
-                                         ErrorResult&);
-  void ReceiveWeakNullableCastableObjectSequence(nsTArray<TestInterface*> &,
-                                                 ErrorResult&);
-  void ReceiveWeakCastableObjectNullableSequence(Nullable< nsTArray<TestInterface*> >&,
-                                                 ErrorResult&);
-  void ReceiveWeakNullableCastableObjectNullableSequence(Nullable< nsTArray<TestInterface*> >&,
-                                                         ErrorResult&);
-  void PassCastableObjectSequence(const Sequence< OwningNonNull<TestInterface> >&,
-                                  ErrorResult&);
-  void PassNullableCastableObjectSequence(const Sequence< nsRefPtr<TestInterface> > &,
-                                          ErrorResult&);
-  void PassCastableObjectNullableSequence(const Nullable< Sequence< OwningNonNull<TestInterface> > >&,
-                                          ErrorResult&);
-  void PassNullableCastableObjectNullableSequence(const Nullable< Sequence< nsRefPtr<TestInterface> > >&,
-                                                  ErrorResult&);
-  void PassOptionalSequence(const Optional<Sequence<int32_t> >&,
-                            ErrorResult&);
-  void PassOptionalNullableSequence(const Optional<Nullable<Sequence<int32_t> > >&,
-                                    ErrorResult&);
-  void PassOptionalNullableSequenceWithDefaultValue(const Nullable< Sequence<int32_t> >&,
-                                                    ErrorResult&);
-  void PassOptionalObjectSequence(const Optional<Sequence<OwningNonNull<TestInterface> > >&,
-                                  ErrorResult&);
+  void ReceiveSequence(nsTArray<int32_t>&);
+  void ReceiveNullableSequence(Nullable< nsTArray<int32_t> >&);
+  void ReceiveSequenceOfNullableInts(nsTArray< Nullable<int32_t> >&);
+  void ReceiveNullableSequenceOfNullableInts(Nullable< nsTArray< Nullable<int32_t> > >&);
+  void PassSequence(const Sequence<int32_t> &);
+  void PassNullableSequence(const Nullable< Sequence<int32_t> >&);
+  void PassSequenceOfNullableInts(const Sequence<Nullable<int32_t> >&);
+  void PassOptionalSequenceOfNullableInts(const Optional<Sequence<Nullable<int32_t> > > &);
+  void PassOptionalNullableSequenceOfNullableInts(const Optional<Nullable<Sequence<Nullable<int32_t> > > > &);
+  void ReceiveCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &);
+  void ReceiveNullableCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &);
+  void ReceiveCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&);
+  void ReceiveNullableCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&);
+  void ReceiveWeakCastableObjectSequence(nsTArray<TestInterface*> &);
+  void ReceiveWeakNullableCastableObjectSequence(nsTArray<TestInterface*> &);
+  void ReceiveWeakCastableObjectNullableSequence(Nullable< nsTArray<TestInterface*> >&);
+  void ReceiveWeakNullableCastableObjectNullableSequence(Nullable< nsTArray<TestInterface*> >&);
+  void PassCastableObjectSequence(const Sequence< OwningNonNull<TestInterface> >&);
+  void PassNullableCastableObjectSequence(const Sequence< nsRefPtr<TestInterface> > &);
+  void PassCastableObjectNullableSequence(const Nullable< Sequence< OwningNonNull<TestInterface> > >&);
+  void PassNullableCastableObjectNullableSequence(const Nullable< Sequence< nsRefPtr<TestInterface> > >&);
+  void PassOptionalSequence(const Optional<Sequence<int32_t> >&);
+  void PassOptionalNullableSequence(const Optional<Nullable<Sequence<int32_t> > >&);
+  void PassOptionalNullableSequenceWithDefaultValue(const Nullable< Sequence<int32_t> >&);
+  void PassOptionalObjectSequence(const Optional<Sequence<OwningNonNull<TestInterface> > >&);
 
-  void ReceiveStringSequence(nsTArray<nsString>&, ErrorResult&);
-  void PassStringSequence(const Sequence<nsString>&, ErrorResult&);
+  void ReceiveStringSequence(nsTArray<nsString>&);
+  void PassStringSequence(const Sequence<nsString>&);
 
   // Typed array types
-  void PassArrayBuffer(ArrayBuffer&, ErrorResult&);
-  void PassNullableArrayBuffer(ArrayBuffer*, ErrorResult&);
-  void PassOptionalArrayBuffer(const Optional<ArrayBuffer>&, ErrorResult&);
-  void PassOptionalNullableArrayBuffer(const Optional<ArrayBuffer*>&, ErrorResult&);
-  void PassOptionalNullableArrayBufferWithDefaultValue(ArrayBuffer*, ErrorResult&);
-  void PassArrayBufferView(ArrayBufferView&, ErrorResult&);
-  void PassInt8Array(Int8Array&, ErrorResult&);
-  void PassInt16Array(Int16Array&, ErrorResult&);
-  void PassInt32Array(Int32Array&, ErrorResult&);
-  void PassUint8Array(Uint8Array&, ErrorResult&);
-  void PassUint16Array(Uint16Array&, ErrorResult&);
-  void PassUint32Array(Uint32Array&, ErrorResult&);
-  void PassUint8ClampedArray(Uint8ClampedArray&, ErrorResult&);
-  void PassFloat32Array(Float32Array&, ErrorResult&);
-  void PassFloat64Array(Float64Array&, ErrorResult&);
-  JSObject* ReceiveUint8Array(ErrorResult&);
+  void PassArrayBuffer(ArrayBuffer&);
+  void PassNullableArrayBuffer(ArrayBuffer*);
+  void PassOptionalArrayBuffer(const Optional<ArrayBuffer>&);
+  void PassOptionalNullableArrayBuffer(const Optional<ArrayBuffer*>&);
+  void PassOptionalNullableArrayBufferWithDefaultValue(ArrayBuffer*);
+  void PassArrayBufferView(ArrayBufferView&);
+  void PassInt8Array(Int8Array&);
+  void PassInt16Array(Int16Array&);
+  void PassInt32Array(Int32Array&);
+  void PassUint8Array(Uint8Array&);
+  void PassUint16Array(Uint16Array&);
+  void PassUint32Array(Uint32Array&);
+  void PassUint8ClampedArray(Uint8ClampedArray&);
+  void PassFloat32Array(Float32Array&);
+  void PassFloat64Array(Float64Array&);
+  JSObject* ReceiveUint8Array();
 
   // String types
-  void PassString(const nsAString&, ErrorResult&);
-  void PassNullableString(const nsAString&, ErrorResult&);
-  void PassOptionalString(const Optional<nsAString>&, ErrorResult&);
-  void PassOptionalStringWithDefaultValue(const nsAString&, ErrorResult&);
-  void PassOptionalNullableString(const Optional<nsAString>&, ErrorResult&);
-  void PassOptionalNullableStringWithDefaultValue(const nsAString&, ErrorResult&);
+  void PassString(const nsAString&);
+  void PassNullableString(const nsAString&);
+  void PassOptionalString(const Optional<nsAString>&);
+  void PassOptionalStringWithDefaultValue(const nsAString&);
+  void PassOptionalNullableString(const Optional<nsAString>&);
+  void PassOptionalNullableStringWithDefaultValue(const nsAString&);
 
   // Enumarated types
-  void PassEnum(TestEnum, ErrorResult&);
-  void PassOptionalEnum(const Optional<TestEnum>&, ErrorResult&);
-  void PassEnumWithDefault(TestEnum, ErrorResult&);
-  TestEnum ReceiveEnum(ErrorResult&);
-  TestEnum GetEnumAttribute(ErrorResult&);
-  TestEnum GetReadonlyEnumAttribute(ErrorResult&);
-  void SetEnumAttribute(TestEnum, ErrorResult&);
+  void PassEnum(TestEnum);
+  void PassOptionalEnum(const Optional<TestEnum>&);
+  void PassEnumWithDefault(TestEnum);
+  TestEnum ReceiveEnum();
+  TestEnum GetEnumAttribute();
+  TestEnum GetReadonlyEnumAttribute();
+  void SetEnumAttribute(TestEnum);
 
   // Callback types
-  void PassCallback(JSContext*, JSObject*, ErrorResult&);
-  void PassNullableCallback(JSContext*, JSObject*, ErrorResult&);
-  void PassOptionalCallback(JSContext*, const Optional<JSObject*>&,
-                            ErrorResult&);
-  void PassOptionalNullableCallback(JSContext*, const Optional<JSObject*>&,
-                                    ErrorResult&);
-  void PassOptionalNullableCallbackWithDefaultValue(JSContext*, JSObject*,
-                                                    ErrorResult&);
-  JSObject* ReceiveCallback(JSContext*, ErrorResult&);
-  JSObject* ReceiveNullableCallback(JSContext*, ErrorResult&);
+  void PassCallback(JSContext*, JSObject*);
+  void PassNullableCallback(JSContext*, JSObject*);
+  void PassOptionalCallback(JSContext*, const Optional<JSObject*>&);
+  void PassOptionalNullableCallback(JSContext*, const Optional<JSObject*>&);
+  void PassOptionalNullableCallbackWithDefaultValue(JSContext*, JSObject*);
+  JSObject* ReceiveCallback(JSContext*);
+  JSObject* ReceiveNullableCallback(JSContext*);
 
   // Any types
-  void PassAny(JSContext*, JS::Value, ErrorResult&);
-  void PassOptionalAny(JSContext*, const Optional<JS::Value>&, ErrorResult&);
-  void PassAnyDefaultNull(JSContext*, JS::Value, ErrorResult&);
-  JS::Value ReceiveAny(JSContext*, ErrorResult&);
+  void PassAny(JSContext*, JS::Value);
+  void PassOptionalAny(JSContext*, const Optional<JS::Value>&);
+  void PassAnyDefaultNull(JSContext*, JS::Value);
+  JS::Value ReceiveAny(JSContext*);
 
   // object types
-  void PassObject(JSContext*, JSObject&, ErrorResult&);
-  void PassNullableObject(JSContext*, JSObject*, ErrorResult&);
-  void PassOptionalObject(JSContext*, const Optional<NonNull<JSObject> >&, ErrorResult&);
-  void PassOptionalNullableObject(JSContext*, const Optional<JSObject*>&, ErrorResult&);
-  void PassOptionalNullableObjectWithDefaultValue(JSContext*, JSObject*, ErrorResult&);
-  JSObject* ReceiveObject(JSContext*, ErrorResult&);
-  JSObject* ReceiveNullableObject(JSContext*, ErrorResult&);
+  void PassObject(JSContext*, JSObject&);
+  void PassNullableObject(JSContext*, JSObject*);
+  void PassOptionalObject(JSContext*, const Optional<NonNull<JSObject> >&);
+  void PassOptionalNullableObject(JSContext*, const Optional<JSObject*>&);
+  void PassOptionalNullableObjectWithDefaultValue(JSContext*, JSObject*);
+  JSObject* ReceiveObject(JSContext*);
+  JSObject* ReceiveNullableObject(JSContext*);
 
   // Union types
-  void PassUnion(JSContext*, const ObjectOrLong& arg, ErrorResult&);
-  void PassUnionWithNullable(JSContext*, const ObjectOrNullOrLong& arg, ErrorResult&)
+  void PassUnion(JSContext*, const ObjectOrLong& arg);
+  void PassUnionWithNullable(JSContext*, const ObjectOrNullOrLong& arg)
   {
     ObjectOrLong returnValue;
     if (arg.IsNull()) {
     } else if (arg.IsObject()) {
       JSObject& obj = (JSObject&)arg.GetAsObject();
       JS_GetClass(&obj);
       //returnValue.SetAsObject(&obj);
     } else {
       int32_t i = arg.GetAsLong();
       i += 1;
     }
   }
-  void PassNullableUnion(JSContext*, const Nullable<ObjectOrLong>&, ErrorResult&);
-  void PassOptionalUnion(JSContext*, const Optional<ObjectOrLong>&, ErrorResult&);
-  void PassOptionalNullableUnion(JSContext*, const Optional<Nullable<ObjectOrLong> >&, ErrorResult&);
-  void PassOptionalNullableUnionWithDefaultValue(JSContext*, const Nullable<ObjectOrLong>&, ErrorResult&);
-  //void PassUnionWithInterfaces(const TestInterfaceOrTestExternalInterface& arg, ErrorResult&);
-  //void PassUnionWithInterfacesAndNullable(const TestInterfaceOrNullOrTestExternalInterface& arg, ErrorResult&);
-  void PassUnionWithArrayBuffer(const ArrayBufferOrLong&, ErrorResult&);
-  void PassUnionWithString(JSContext*, const StringOrObject&, ErrorResult&);
-  //void PassUnionWithEnum(JSContext*, const TestEnumOrObject&, ErrorResult&);
-  void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&, ErrorResult&);
-  void PassUnionWithObject(JSContext*, const ObjectOrLong&, ErrorResult&);
+  void PassNullableUnion(JSContext*, const Nullable<ObjectOrLong>&);
+  void PassOptionalUnion(JSContext*, const Optional<ObjectOrLong>&);
+  void PassOptionalNullableUnion(JSContext*, const Optional<Nullable<ObjectOrLong> >&);
+  void PassOptionalNullableUnionWithDefaultValue(JSContext*, const Nullable<ObjectOrLong>&);
+  //void PassUnionWithInterfaces(const TestInterfaceOrTestExternalInterface& arg);
+  //void PassUnionWithInterfacesAndNullable(const TestInterfaceOrNullOrTestExternalInterface& arg);
+  void PassUnionWithArrayBuffer(const ArrayBufferOrLong&);
+  void PassUnionWithString(JSContext*, const StringOrObject&);
+  //void PassUnionWithEnum(JSContext*, const TestEnumOrObject&);
+  void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&);
+  void PassUnionWithObject(JSContext*, const ObjectOrLong&);
 
   // binaryNames tests
-  void MethodRenamedTo(ErrorResult&);
-  void MethodRenamedTo(int8_t, ErrorResult&);
-  int8_t GetAttributeGetterRenamedTo(ErrorResult&);
-  int8_t GetAttributeRenamedTo(ErrorResult&);
-  void SetAttributeRenamedTo(int8_t, ErrorResult&);
+  void MethodRenamedTo();
+  void MethodRenamedTo(int8_t);
+  int8_t GetAttributeGetterRenamedTo();
+  int8_t GetAttributeRenamedTo();
+  void SetAttributeRenamedTo(int8_t);
 
   // Dictionary tests
-  void PassDictionary(const Dict&, ErrorResult&);
-  void PassOtherDictionary(const GrandparentDict&, ErrorResult&);
-  void PassSequenceOfDictionaries(const Sequence<Dict>&, ErrorResult&);
-  void PassDictionaryOrLong(const Dict&, ErrorResult&);
-  void PassDictionaryOrLong(int32_t, ErrorResult&);
-  void PassDictContainingDict(const DictContainingDict&, ErrorResult&);
+  void PassDictionary(const Dict&);
+  void PassOtherDictionary(const GrandparentDict&);
+  void PassSequenceOfDictionaries(const Sequence<Dict>&);
+  void PassDictionaryOrLong(const Dict&);
+  void PassDictionaryOrLong(int32_t);
+  void PassDictContainingDict(const DictContainingDict&);
 
   // Methods and properties imported via "implements"
-  bool GetImplementedProperty(ErrorResult&);
-  void SetImplementedProperty(bool, ErrorResult&);
-  void ImplementedMethod(ErrorResult&);
-  bool GetImplementedParentProperty(ErrorResult&);
-  void SetImplementedParentProperty(bool, ErrorResult&);
-  void ImplementedParentMethod(ErrorResult&);
-  bool GetIndirectlyImplementedProperty(ErrorResult&);
-  void SetIndirectlyImplementedProperty(bool, ErrorResult&);
-  void IndirectlyImplementedMethod(ErrorResult&);
-  uint32_t GetDiamondImplementedProperty(ErrorResult&);
+  bool GetImplementedProperty();
+  void SetImplementedProperty(bool);
+  void ImplementedMethod();
+  bool GetImplementedParentProperty();
+  void SetImplementedParentProperty(bool);
+  void ImplementedParentMethod();
+  bool GetIndirectlyImplementedProperty();
+  void SetIndirectlyImplementedProperty(bool);
+  void IndirectlyImplementedMethod();
+  uint32_t GetDiamondImplementedProperty();
 
 private:
   // We add signatures here that _could_ start matching if the codegen
   // got data types wrong.  That way if it ever does we'll have a call
   // to these private deleted methods and compilation will fail.
-  void SetReadonlyByte(int8_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyByte(int8_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableByte(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableByte(T) MOZ_DELETE;
   template<typename T>
-  void PassByte(T, ErrorResult&) MOZ_DELETE;
+  void PassByte(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalByte(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalByte(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalByteWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalByteWithDefault(T) MOZ_DELETE;
 
-  void SetReadonlyShort(int16_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyShort(int16_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableShort(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableShort(T) MOZ_DELETE;
   template<typename T>
-  void PassShort(T, ErrorResult&) MOZ_DELETE;
+  void PassShort(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalShort(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalShort(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalShortWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalShortWithDefault(T) MOZ_DELETE;
 
-  void SetReadonlyLong(int32_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyLong(int32_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableLong(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableLong(T) MOZ_DELETE;
   template<typename T>
-  void PassLong(T, ErrorResult&) MOZ_DELETE;
+  void PassLong(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalLong(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalLongWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalLongWithDefault(T) MOZ_DELETE;
 
-  void SetReadonlyLongLong(int64_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyLongLong(int64_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableLongLong(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableLongLong(T) MOZ_DELETE;
   template<typename T>
-  void PassLongLong(T, ErrorResult&) MOZ_DELETE;
+  void PassLongLong(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalLongLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalLongLong(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalLongLongWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalLongLongWithDefault(T) MOZ_DELETE;
 
-  void SetReadonlyOctet(uint8_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyOctet(uint8_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableOctet(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableOctet(T) MOZ_DELETE;
   template<typename T>
-  void PassOctet(T, ErrorResult&) MOZ_DELETE;
+  void PassOctet(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalOctet(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalOctet(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalOctetWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalOctetWithDefault(T) MOZ_DELETE;
 
-  void SetReadonlyUnsignedShort(uint16_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyUnsignedShort(uint16_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableUnsignedShort(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableUnsignedShort(T) MOZ_DELETE;
   template<typename T>
-  void PassUnsignedShort(T, ErrorResult&) MOZ_DELETE;
+  void PassUnsignedShort(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalUnsignedShort(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalUnsignedShort(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalUnsignedShortWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalUnsignedShortWithDefault(T) MOZ_DELETE;
 
-  void SetReadonlyUnsignedLong(uint32_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyUnsignedLong(uint32_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableUnsignedLong(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableUnsignedLong(T) MOZ_DELETE;
   template<typename T>
-  void PassUnsignedLong(T, ErrorResult&) MOZ_DELETE;
+  void PassUnsignedLong(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalUnsignedLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalUnsignedLong(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalUnsignedLongWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalUnsignedLongWithDefault(T) MOZ_DELETE;
 
-  void SetReadonlyUnsignedLongLong(uint64_t, ErrorResult&) MOZ_DELETE;
+  void SetReadonlyUnsignedLongLong(uint64_t) MOZ_DELETE;
   template<typename T>
-  void SetWritableUnsignedLongLong(T, ErrorResult&) MOZ_DELETE;
+  void SetWritableUnsignedLongLong(T) MOZ_DELETE;
   template<typename T>
-  void PassUnsignedLongLong(T, ErrorResult&) MOZ_DELETE;
+  void PassUnsignedLongLong(T) MOZ_DELETE;
   template<typename T>
-  void PassOptionalUnsignedLongLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
+  void PassOptionalUnsignedLongLong(const Optional<T>&) MOZ_DELETE;
   template<typename T>
-  void PassOptionalUnsignedLongLongWithDefault(T, ErrorResult&) MOZ_DELETE;
+  void PassOptionalUnsignedLongLongWithDefault(T) MOZ_DELETE;
 
   // Enforce that only const things are passed for sequences
-  void PassSequence(Sequence<int32_t> &, ErrorResult&) MOZ_DELETE;
-  void PassNullableSequence(Nullable< Sequence<int32_t> >&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence<int32_t> >&,
-                                                    ErrorResult&) MOZ_DELETE;
+  void PassSequence(Sequence<int32_t> &) MOZ_DELETE;
+  void PassNullableSequence(Nullable< Sequence<int32_t> >&) MOZ_DELETE;
+  void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence<int32_t> >&) MOZ_DELETE;
 
   // Enforce that only const things are passed for optional
-  void PassOptionalByte(Optional<int8_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNullableByte(Optional<Nullable<int8_t> >&,
-                                ErrorResult&) MOZ_DELETE;
-  void PassOptionalShort(Optional<int16_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalLong(Optional<int32_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalLongLong(Optional<int64_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalOctet(Optional<uint8_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalUnsignedShort(Optional<uint16_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalUnsignedLong(Optional<uint32_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalUnsignedLongLong(Optional<uint64_t>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalSelf(Optional<TestInterface*> &, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNonNullSelf(Optional<NonNull<TestInterface> >&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalOther(Optional<TestNonCastableInterface*>&, ErrorResult&);
-  void PassOptionalNonNullOther(Optional<NonNull<TestNonCastableInterface> >&, ErrorResult&);
-  void PassOptionalExternal(Optional<TestExternalInterface*>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNonNullExternal(Optional<TestExternalInterface*>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalSequence(Optional<Sequence<int32_t> >&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNullableSequence(Optional<Nullable<Sequence<int32_t> > >&,
-                                    ErrorResult&) MOZ_DELETE;
-  void PassOptionalObjectSequence(Optional<Sequence<OwningNonNull<TestInterface> > >&,
-                                  ErrorResult&) MOZ_DELETE;
-  void PassOptionalArrayBuffer(Optional<ArrayBuffer>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalEnum(Optional<TestEnum>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalCallback(JSContext*, Optional<JSObject*>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNullableCallback(JSContext*, Optional<JSObject*>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalAny(Optional<JS::Value>&, ErrorResult) MOZ_DELETE;
+  void PassOptionalByte(Optional<int8_t>&) MOZ_DELETE;
+  void PassOptionalNullableByte(Optional<Nullable<int8_t> >&) MOZ_DELETE;
+  void PassOptionalShort(Optional<int16_t>&) MOZ_DELETE;
+  void PassOptionalLong(Optional<int32_t>&) MOZ_DELETE;
+  void PassOptionalLongLong(Optional<int64_t>&) MOZ_DELETE;
+  void PassOptionalOctet(Optional<uint8_t>&) MOZ_DELETE;
+  void PassOptionalUnsignedShort(Optional<uint16_t>&) MOZ_DELETE;
+  void PassOptionalUnsignedLong(Optional<uint32_t>&) MOZ_DELETE;
+  void PassOptionalUnsignedLongLong(Optional<uint64_t>&) MOZ_DELETE;
+  void PassOptionalSelf(Optional<TestInterface*> &) MOZ_DELETE;
+  void PassOptionalNonNullSelf(Optional<NonNull<TestInterface> >&) MOZ_DELETE;
+  void PassOptionalOther(Optional<TestNonCastableInterface*>&);
+  void PassOptionalNonNullOther(Optional<NonNull<TestNonCastableInterface> >&);
+  void PassOptionalExternal(Optional<TestExternalInterface*>&) MOZ_DELETE;
+  void PassOptionalNonNullExternal(Optional<TestExternalInterface*>&) MOZ_DELETE;
+  void PassOptionalSequence(Optional<Sequence<int32_t> >&) MOZ_DELETE;
+  void PassOptionalNullableSequence(Optional<Nullable<Sequence<int32_t> > >&) MOZ_DELETE;
+  void PassOptionalObjectSequence(Optional<Sequence<OwningNonNull<TestInterface> > >&) MOZ_DELETE;
+  void PassOptionalArrayBuffer(Optional<ArrayBuffer>&) MOZ_DELETE;
+  void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&) MOZ_DELETE;
+  void PassOptionalEnum(Optional<TestEnum>&) MOZ_DELETE;
+  void PassOptionalCallback(JSContext*, Optional<JSObject*>&) MOZ_DELETE;
+  void PassOptionalNullableCallback(JSContext*, Optional<JSObject*>&) MOZ_DELETE;
+  void PassOptionalAny(Optional<JS::Value>&) MOZ_DELETE;
 
   // And test that string stuff is always const
-  void PassString(nsAString&, ErrorResult&) MOZ_DELETE;
-  void PassNullableString(nsAString&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalString(Optional<nsAString>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalStringWithDefaultValue(nsAString&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNullableString(Optional<nsAString>&, ErrorResult&) MOZ_DELETE;
-  void PassOptionalNullableStringWithDefaultValue(nsAString&, ErrorResult&) MOZ_DELETE;
+  void PassString(nsAString&) MOZ_DELETE;
+  void PassNullableString(nsAString&) MOZ_DELETE;
+  void PassOptionalString(Optional<nsAString>&) MOZ_DELETE;
+  void PassOptionalStringWithDefaultValue(nsAString&) MOZ_DELETE;
+  void PassOptionalNullableString(Optional<nsAString>&) MOZ_DELETE;
+  void PassOptionalNullableStringWithDefaultValue(nsAString&) MOZ_DELETE;
 
 };
 
 class TestIndexedGetterInterface : public nsISupports,
                                    public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
-  uint32_t IndexedGetter(uint32_t, bool&, ErrorResult&);
-  uint32_t IndexedGetter(uint32_t, ErrorResult&) MOZ_DELETE;
-  uint32_t Item(uint32_t, ErrorResult&);
-  uint32_t Item(uint32_t, bool&, ErrorResult&) MOZ_DELETE;
+  uint32_t IndexedGetter(uint32_t, bool&);
+  uint32_t IndexedGetter(uint32_t&) MOZ_DELETE;
+  uint32_t Item(uint32_t&);
+  uint32_t Item(uint32_t, bool&) MOZ_DELETE;
   uint32_t GetLength();
 };
 
 class TestNamedGetterInterface : public nsISupports,
                                  public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
-  void NamedGetter(const nsAString&, bool&, nsAString&, ErrorResult&);
+  void NamedGetter(const nsAString&, bool&, nsAString&);
 };
 
 class TestIndexedAndNamedGetterInterface : public nsISupports,
                                            public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
-  uint32_t IndexedGetter(uint32_t, bool&, ErrorResult&);
-  void NamedGetter(const nsAString&, bool&, nsAString&, ErrorResult&);
-  void NamedItem(const nsAString&, nsAString&, ErrorResult&);
+  uint32_t IndexedGetter(uint32_t, bool&);
+  void NamedGetter(const nsAString&, bool&, nsAString&);
+  void NamedItem(const nsAString&, nsAString&);
   uint32_t GetLength();
 };
 
 class TestIndexedSetterInterface : public nsISupports,
                                    public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
-  void IndexedSetter(uint32_t, const nsAString&, ErrorResult&);
-  void SetItem(uint32_t, const nsAString&, ErrorResult&);
+  void IndexedSetter(uint32_t, const nsAString&);
+  void SetItem(uint32_t, const nsAString&);
 };
 
 class TestNamedSetterInterface : public nsISupports,
                                  public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
-  void NamedSetter(const nsAString&, TestIndexedSetterInterface&, ErrorResult&);
+  void NamedSetter(const nsAString&, TestIndexedSetterInterface&);
 };
 
 class TestIndexedAndNamedSetterInterface : public nsISupports,
                                            public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
-  void IndexedSetter(uint32_t, TestIndexedSetterInterface&, ErrorResult&);
-  void NamedSetter(const nsAString&, TestIndexedSetterInterface&, ErrorResult&);
-  void SetNamedItem(const nsAString&, TestIndexedSetterInterface&, ErrorResult&);
+  void IndexedSetter(uint32_t, TestIndexedSetterInterface&);
+  void NamedSetter(const nsAString&, TestIndexedSetterInterface&);
+  void SetNamedItem(const nsAString&, TestIndexedSetterInterface&);
 };
 
 class TestIndexedAndNamedGetterAndSetterInterface : public TestIndexedSetterInterface
 {
 public:
-  uint32_t IndexedGetter(uint32_t, bool&, ErrorResult&);
-  uint32_t Item(uint32_t, ErrorResult&);
-  void NamedGetter(const nsAString&, bool&, nsAString&, ErrorResult&);
-  void NamedItem(const nsAString&, nsAString&, ErrorResult&);
-  void IndexedSetter(uint32_t, int32_t&, ErrorResult&);
-  void IndexedSetter(uint32_t, const nsAString&, ErrorResult&) MOZ_DELETE;
-  void NamedSetter(const nsAString&, const nsAString&, ErrorResult&);
+  uint32_t IndexedGetter(uint32_t, bool&);
+  uint32_t Item(uint32_t);
+  void NamedGetter(const nsAString&, bool&, nsAString&);
+  void NamedItem(const nsAString&, nsAString&);
+  void IndexedSetter(uint32_t, int32_t&);
+  void IndexedSetter(uint32_t, const nsAString&) MOZ_DELETE;
+  void NamedSetter(const nsAString&, const nsAString&);
   void Stringify(nsAString&);
   uint32_t GetLength();
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* TestBindingHeader_h */
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -31,17 +31,17 @@ interface OnlyForUseInConstructor {
  Constructor(DOMString str),
  Constructor(unsigned long num, boolean? bool),
  Constructor(TestInterface? iface),
  Constructor(TestNonCastableInterface iface)
  // , Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3)
  ]
 interface TestInterface {
   // Integer types
-  // XXXbz add tests for infallible versions of all the integer stuff
+  // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
   byte receiveByte();
   void passOptionalByte(optional byte arg);
   void passOptionalByteWithDefault(optional byte arg = 0);
   void passNullableByte(byte? arg);
   void passOptionalNullableByte(optional byte? arg);
@@ -91,17 +91,17 @@ interface TestInterface {
   readonly attribute unsigned long long readonlyUnsignedLongLong;
   attribute unsigned long long  writableUnsignedLongLong;
   void passUnsignedLongLong(unsigned long long arg);
   unsigned long long receiveUnsignedLongLong();
   void passOptionalUnsignedLongLong(optional unsigned long long arg);
   void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17);
 
   // Castable interface types
-  // XXXbz add tests for infallible versions of all the castable interface stuff
+  // XXXbz add tests for throwing versions of all the castable interface stuff
   TestInterface receiveSelf();
   TestInterface? receiveNullableSelf();
   TestInterface receiveWeakSelf();
   TestInterface? receiveWeakNullableSelf();
   // A verstion to test for casting to TestInterface&
   void passSelf(TestInterface arg);
   // A version we can use to test for the exact type passed in
   void passSelf2(TestInterface arg);
@@ -371,26 +371,28 @@ dictionary ParentDict : GrandparentDict 
 };
 
 dictionary DictContainingDict {
   Dict memberDict;
 };
 
 interface TestIndexedGetterInterface {
   getter long item(unsigned long index);
+  [Infallible]
   readonly attribute unsigned long length;
 };
 
 interface TestNamedGetterInterface {
   getter DOMString (DOMString name);
 };
 
 interface TestIndexedAndNamedGetterInterface {
   getter long (unsigned long index);
   getter DOMString namedItem(DOMString name);
+  [Infallible]
   readonly attribute unsigned long length;
 };
 
 interface TestIndexedSetterInterface {
   setter creator void setItem(unsigned long index, DOMString item);
 };
 
 interface TestNamedSetterInterface {
@@ -402,11 +404,13 @@ interface TestIndexedAndNamedSetterInter
   setter creator void setNamedItem(DOMString name, TestIndexedSetterInterface item);
 };
 
 interface TestIndexedAndNamedGetterAndSetterInterface : TestIndexedSetterInterface {
   getter long item(unsigned long index);
   getter DOMString namedItem(DOMString name);
   setter creator void (unsigned long index, long item);
   setter creator void (DOMString name, DOMString item);
+  [Infallible]
   stringifier DOMString ();
+  [Infallible]
   readonly attribute unsigned long length;
 };
--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -102,16 +102,22 @@ BrowserElementChild.prototype = {
                      /* useCapture = */ true,
                      /* wantsUntrusted = */ false);
 
     addEventListener('DOMLinkAdded',
                      this._iconChangedHandler.bind(this),
                      /* useCapture = */ true,
                      /* wantsUntrusted = */ false);
 
+    this._afterPaintHandlerClosure = this._afterPaintHandler.bind(this);
+    addEventListener('MozAfterPaint',
+                     this._afterPaintHandlerClosure,
+                     /* useCapture = */ true,
+                     /* wantsUntrusted = */ false);
+
     var self = this;
     function addMsgListener(msg, handler) {
       addMessageListener('browser-element-api:' + msg, handler.bind(self));
     }
 
     addMsgListener("get-screenshot", this._recvGetScreenshot);
     addMsgListener("set-visible", this._recvSetVisible);
     addMsgListener("send-mouse-event", this._recvSendMouseEvent);
@@ -346,16 +352,29 @@ BrowserElementChild.prototype = {
         sendAsyncMsg('iconchange', e.target.href);
       }
       else {
         debug("Not top level!");
       }
     }
   },
 
+  _afterPaintHandler: function(e) {
+    let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
+    debug("Got afterpaint event: " + uri.spec);
+    if (uri.spec != "about:blank") {
+      /* this._afterPaintHandlerClosure == arguments.callee, except we're in
+       * strict mode so we don't have arguments.callee. */
+      removeEventListener('MozAfterPaint', this._afterPaintHandlerClosure,
+                          /* useCapture */ true);
+
+      sendAsyncMsg('firstpaint');
+    }
+  },
+
   _closeHandler: function(e) {
     let win = e.target;
     if (win != content || e.defaultPrevented) {
       return;
     }
 
     debug("Closing window " + win);
     sendAsyncMsg('close');
--- a/dom/browser-element/BrowserElementParent.js
+++ b/dom/browser-element/BrowserElementParent.js
@@ -190,16 +190,17 @@ function BrowserElementParent(frameLoade
   addMessageListener("loadstart", this._fireEventFromMsg);
   addMessageListener("loadend", this._fireEventFromMsg);
   addMessageListener("titlechange", this._fireEventFromMsg);
   addMessageListener("iconchange", this._fireEventFromMsg);
   addMessageListener("close", this._fireEventFromMsg);
   addMessageListener("securitychange", this._fireEventFromMsg);
   addMessageListener("error", this._fireEventFromMsg);
   addMessageListener("scroll", this._fireEventFromMsg);
+  addMessageListener("firstpaint", this._fireEventFromMsg);
   addMessageListener("keyevent", this._fireKeyEvent);
   addMessageListener("showmodalprompt", this._handleShowModalPrompt);
   addMessageListener('got-screenshot', this._gotDOMRequestResult);
   addMessageListener('got-can-go-back', this._gotDOMRequestResult);
   addMessageListener('got-can-go-forward', this._gotDOMRequestResult);
   addMessageListener('fullscreen-origin-change', this._remoteFullscreenOriginChange);
   addMessageListener('rollback-fullscreen', this._remoteFrameFullscreenReverted);
   addMessageListener('exit-fullscreen', this._exitFullscreen);
--- a/dom/browser-element/mochitest/Makefile.in
+++ b/dom/browser-element/mochitest/Makefile.in
@@ -62,16 +62,18 @@ MOCHITEST_FILES = \
 		file_browserElement_XFrameOptionsDeny.html \
 		browserElement_XFrameOptionsSameOrigin.js \
 		test_browserElement_inproc_XFrameOptionsSameOrigin.html \
 		file_browserElement_XFrameOptionsSameOrigin.html \
 		browserElement_XFrameOptionsAllowFrom.js \
 		test_browserElement_inproc_XFrameOptionsAllowFrom.html \
 		file_browserElement_XFrameOptionsAllowFrom.html \
 		file_browserElement_XFrameOptionsAllowFrom.sjs \
+		browserElement_FirstPaint.js \
+		test_browserElement_inproc_FirstPaint.html \
 		browserElement_Alert.js \
 		test_browserElement_inproc_Alert.html \
 		browserElement_AlertInFrame.js \
 		test_browserElement_inproc_AlertInFrame.html \
 		file_browserElement_AlertInFrame.html \
 		file_browserElement_AlertInFrame_Inner.html \
 		browserElement_TargetTop.js \
 		test_browserElement_inproc_TargetTop.html \
@@ -154,16 +156,17 @@ MOCHITEST_FILES += \
 		test_browserElement_oop_SetVisible.html \
 		test_browserElement_oop_SetVisibleFrames.html \
 		test_browserElement_oop_SetVisibleFrames2.html \
 		test_browserElement_oop_KeyEvents.html \
 		test_browserElement_oop_XFrameOptions.html \
 		test_browserElement_oop_XFrameOptionsDeny.html \
 		test_browserElement_oop_XFrameOptionsSameOrigin.html \
 		test_browserElement_oop_XFrameOptionsAllowFrom.html \
+		test_browserElement_oop_FirstPaint.html \
 		test_browserElement_oop_Alert.html \
 		test_browserElement_oop_AlertInFrame.html \
 		test_browserElement_oop_TargetTop.html \
 		test_browserElement_oop_ForwardName.html \
 		test_browserElement_oop_TargetBlank.html \
 		test_browserElement_oop_PromptCheck.html \
 		test_browserElement_oop_PromptConfirm.html \
 		test_browserElement_oop_Close.html \
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/browserElement_FirstPaint.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the public domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Bug 787378 - Add mozbrowserfirstpaint event.
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+  browserElementTestHelpers.setEnabledPref(true);
+  browserElementTestHelpers.addPermission();
+
+  var iframe = document.createElement('iframe');
+  iframe.mozbrowser = true;
+
+  var gotFirstPaint = false;
+  var gotFirstLocationChange = false;
+  iframe.addEventListener('mozbrowserfirstpaint', function(e) {
+    ok(!gotFirstPaint, "Got only one first paint.");
+    gotFirstPaint = true;
+
+    if (gotFirstLocationChange) {
+      iframe.src = browserElementTestHelpers.emptyPage1 + '?2';
+    }
+  });
+
+  iframe.addEventListener('mozbrowserlocationchange', function(e) {
+    if (e.detail == browserElementTestHelpers.emptyPage1) {
+      gotFirstLocationChange = true;
+      if (gotFirstPaint) {
+        iframe.src = browserElementTestHelpers.emptyPage1 + '?2';
+      }
+    }
+    else if (e.detail.endsWith('?2')) {
+      SimpleTest.finish();
+    }
+  });
+
+  document.body.appendChild(iframe);
+
+  iframe.src = browserElementTestHelpers.emptyPage1;
+}
+
+runTest();
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_FirstPaint.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Bug 787378</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="application/javascript;version=1.7" src="browserElement_FirstPaint.js">
+</script>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/test_browserElement_oop_FirstPaint.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Bug 787378</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script type="application/javascript;version=1.7" src="browserElement_FirstPaint.js">
+</script>
+</body>
+</html>
\ No newline at end of file
deleted file mode 100644
--- a/dom/camera/CameraCapabilities.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DOM_CAMERA_NSCAMERACAPABILITIES_H
-#define DOM_CAMERA_NSCAMERACAPABILITIES_H
-
-#include "CameraControl.h"
-#include "nsAutoPtr.h"
-#include "mozilla/Attributes.h"
-
-namespace mozilla {
-
-typedef nsresult (*ParseItemAndAddFunc)(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd);
-
-class nsCameraCapabilities MOZ_FINAL : public nsICameraCapabilities
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSICAMERACAPABILITIES
-
-  nsCameraCapabilities(nsCameraControl* aCamera);
-
-  nsresult ParameterListToNewArray(
-    JSContext* cx,
-    JSObject** aArray,
-    uint32_t aKey,
-    ParseItemAndAddFunc aParseItemAndAdd
-  );
-  nsresult StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
-  nsresult DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
-
-private:
-  nsCameraCapabilities(const nsCameraCapabilities&) MOZ_DELETE;
-  nsCameraCapabilities& operator=(const nsCameraCapabilities&) MOZ_DELETE;
-
-protected:
-  /* additional members */
-  ~nsCameraCapabilities();
-  nsCOMPtr<nsCameraControl> mCamera;
-};
-
-} // namespace mozilla
-
-#endif // DOM_CAMERA_NSCAMERACAPABILITIES_H
--- a/dom/camera/CameraCommon.h
+++ b/dom/camera/CameraCommon.h
@@ -16,36 +16,90 @@
 #endif
 
 #ifndef NAN
 #define NAN std::numeric_limits<double>::quiet_NaN()
 #endif
 
 #include "nsThreadUtils.h"
 #include "nsIDOMCameraManager.h"
+#include "prlog.h"
 
-#define DOM_CAMERA_LOG( l, ... )          \
-  do {                                    \
-    if ( DOM_CAMERA_LOG_LEVEL >= (l) ) {  \
-      printf_stderr (__VA_ARGS__);        \
-    }                                     \
-  } while (0)
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gCameraLog;
+#define DOM_CAMERA_LOG( type, ... ) PR_LOG(gCameraLog, (PRLogModuleLevel)type, ( __VA_ARGS__ ))
+#else
+#define DOM_CAMERA_LOG( type, ... )
+#endif
 
-#define DOM_CAMERA_LOGA( ... )        DOM_CAMERA_LOG( 0, __VA_ARGS__ )
+#define DOM_CAMERA_LOGA( ... )      DOM_CAMERA_LOG( 0, __VA_ARGS__ )
 
+/**
+ * From the least to the most output.
+ */
 enum {
   DOM_CAMERA_LOG_NOTHING,
   DOM_CAMERA_LOG_ERROR,
   DOM_CAMERA_LOG_WARNING,
-  DOM_CAMERA_LOG_INFO
+  DOM_CAMERA_LOG_INFO,
+  DOM_CAMERA_LOG_TRACE,
+  DOM_CAMERA_LOG_REFERENCES
 };
 
-#define DOM_CAMERA_LOGI( ... )        DOM_CAMERA_LOG( DOM_CAMERA_LOG_INFO,  __VA_ARGS__ )
-#define DOM_CAMERA_LOGW( ... )        DOM_CAMERA_LOG( DOM_CAMERA_LOG_WARNING, __VA_ARGS__ )
-#define DOM_CAMERA_LOGE( ... )        DOM_CAMERA_LOG( DOM_CAMERA_LOG_ERROR, __VA_ARGS__ )
+/**
+ * DOM_CAMERA_LOGR() can be called before 'gCameraLog' is set, so
+ * we need to handle this one a little differently.
+ */
+#ifdef PR_LOGGING
+#define DOM_CAMERA_LOGR( ... )                                  \
+  do {                                                          \
+    if (gCameraLog) {                                           \
+      DOM_CAMERA_LOG( DOM_CAMERA_LOG_REFERENCES, __VA_ARGS__ ); \
+    }                                                           \
+  } while (0)
+#else
+#define DOM_CAMERA_LOGR( ... )
+#endif
+#define DOM_CAMERA_LOGT( ... )      DOM_CAMERA_LOG( DOM_CAMERA_LOG_TRACE, __VA_ARGS__ )
+#define DOM_CAMERA_LOGI( ... )      DOM_CAMERA_LOG( DOM_CAMERA_LOG_INFO, __VA_ARGS__ )
+#define DOM_CAMERA_LOGW( ... )      DOM_CAMERA_LOG( DOM_CAMERA_LOG_WARNING, __VA_ARGS__ )
+#define DOM_CAMERA_LOGE( ... )      DOM_CAMERA_LOG( DOM_CAMERA_LOG_ERROR, __VA_ARGS__ )
+
+enum {
+  CAMERA_PARAM_EFFECT,
+  CAMERA_PARAM_WHITEBALANCE,
+  CAMERA_PARAM_SCENEMODE,
+  CAMERA_PARAM_FLASHMODE,
+  CAMERA_PARAM_FOCUSMODE,
+  CAMERA_PARAM_ZOOM,
+  CAMERA_PARAM_METERINGAREAS,
+  CAMERA_PARAM_FOCUSAREAS,
+  CAMERA_PARAM_FOCALLENGTH,
+  CAMERA_PARAM_FOCUSDISTANCENEAR,
+  CAMERA_PARAM_FOCUSDISTANCEOPTIMUM,
+  CAMERA_PARAM_FOCUSDISTANCEFAR,
+  CAMERA_PARAM_EXPOSURECOMPENSATION,
+
+  CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
+  CAMERA_PARAM_SUPPORTED_VIDEOSIZES,
+  CAMERA_PARAM_SUPPORTED_PICTURESIZES,
+  CAMERA_PARAM_SUPPORTED_PICTUREFORMATS,
+  CAMERA_PARAM_SUPPORTED_WHITEBALANCES,
+  CAMERA_PARAM_SUPPORTED_SCENEMODES,
+  CAMERA_PARAM_SUPPORTED_EFFECTS,
+  CAMERA_PARAM_SUPPORTED_FLASHMODES,
+  CAMERA_PARAM_SUPPORTED_FOCUSMODES,
+  CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS,
+  CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS,
+  CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION,
+  CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION,
+  CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP,
+  CAMERA_PARAM_SUPPORTED_ZOOM,
+  CAMERA_PARAM_SUPPORTED_ZOOMRATIOS
+};
 
 class CameraErrorResult : public nsRunnable
 {
 public:
   CameraErrorResult(nsICameraErrorCallback* onError, const nsString& aErrorMsg)
     : mOnErrorCb(onError)
     , mErrorMsg(aErrorMsg)
   { }
@@ -60,9 +114,48 @@ public:
     return NS_OK;
   }
 
 protected:
   nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
   const nsString mErrorMsg;
 };
 
+#ifdef PR_LOGGING
+
+static inline void nsLogAddRefCamera(const char *file, uint32_t line, void* p, uint32_t count, const char *clazz, uint32_t size)
+{
+  if (count == 1) {
+    DOM_CAMERA_LOGR("++++++++++++++++++++++++++++++++++++++++");
+  }
+  DOM_CAMERA_LOGR("%s:%d : CAMREF-ADD(%s): this=%p, mRefCnt=%d\n", file, line, clazz, p, count);
+}
+
+static inline void nsLogReleaseCamera(const char *file, uint32_t line, void* p, uint32_t count, const char *clazz, bool abortOnDelete)
+{
+  DOM_CAMERA_LOGR("%s:%d : CAMREF-REL(%s): this=%p, mRefCnt=%d\n", file, line, clazz, p, count);
+  if (count == 0) {
+    if (!abortOnDelete) {
+      DOM_CAMERA_LOGR("----------------------------------------");
+    } else {
+      DOM_CAMERA_LOGR("---------- ABORTING ON DELETE ----------");
+      *((uint32_t *)0xdeadbeef) = 0x266230;
+    }
+  }
+}
+
+#ifdef NS_LOG_ADDREF
+#undef NS_LOG_ADDREF
+#endif
+#ifdef NS_LOG_RELEASE
+#undef NS_LOG_RELEASE
+#endif
+
+#define NS_LOG_ADDREF( p, n, c, s ) nsLogAddRefCamera(__FILE__, __LINE__, (p), (n), (c), (s))
+#ifdef DOM_CAMERA_DEBUG_REFS_ABORT_ON_DELETE
+#define NS_LOG_RELEASE( p, n, c )   nsLogReleaseCamera(__FILE__, __LINE__, (p), (n), (c), DOM_CAMERA_DEBUG_REFS_ABORT_ON_DELETE)
+#else
+#define NS_LOG_RELEASE( p, n, c )   nsLogReleaseCamera(__FILE__, __LINE__, (p), (n), (c), false)
+#endif
+
+#endif // PR_LOGGING
+
 #endif // DOM_CAMERA_CAMERACOMMON_H
deleted file mode 100644
--- a/dom/camera/CameraControl.cpp
+++ /dev/null
@@ -1,506 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsCOMPtr.h"
-#include "nsDOMClassInfo.h"
-#include "jsapi.h"
-#include "nsThread.h"
-#include "DOMCameraManager.h"
-#include "CameraControl.h"
-#include "CameraCapabilities.h"
-#include "CameraControl.h"
-#include "mozilla/Services.h"
-#include "nsIObserverService.h"
-
-#define DOM_CAMERA_LOG_LEVEL  3
-#include "CameraCommon.h"
-
-using namespace mozilla;
-using namespace dom;
-
-DOMCI_DATA(CameraControl, nsICameraControl)
-
-NS_INTERFACE_MAP_BEGIN(nsCameraControl)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_INTERFACE_MAP_ENTRY(nsICameraControl)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraControl)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_THREADSAFE_ADDREF(nsCameraControl)
-NS_IMPL_THREADSAFE_RELEASE(nsCameraControl)
-
-// Helpers for string properties.
-nsresult
-nsCameraControl::SetHelper(uint32_t aKey, const nsAString& aValue)
-{
-  SetParameter(aKey, NS_ConvertUTF16toUTF8(aValue).get());
-  return NS_OK;
-}
-
-nsresult
-nsCameraControl::GetHelper(uint32_t aKey, nsAString& aValue)
-{
-  const char* value = GetParameterConstChar(aKey);
-  if (!value) {
-    return NS_ERROR_FAILURE;
-  }
-
-  aValue.AssignASCII(value);
-  return NS_OK;
-}
-
-// Helpers for doubles.
-nsresult
-nsCameraControl::SetHelper(uint32_t aKey, double aValue)
-{
-  SetParameter(aKey, aValue);
-  return NS_OK;
-}
-
-nsresult
-nsCameraControl::GetHelper(uint32_t aKey, double* aValue)
-{
-  MOZ_ASSERT(aValue);
-  *aValue = GetParameterDouble(aKey);
-  return NS_OK;
-}
-
-// Helper for weighted regions.
-nsresult
-nsCameraControl::SetHelper(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit)
-{
-  if (aLimit == 0) {
-    DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__);
-    return NS_OK;
-  }
-
-  if (!aValue.isObject()) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  uint32_t length = 0;
-
-  JSObject* regions = &aValue.toObject();
-  if (!JS_GetArrayLength(aCx, regions, &length)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit);
-  if (length > aLimit) {
-    length = aLimit;
-  }
-    
-  nsTArray<CameraRegion> regionArray;
-  regionArray.SetCapacity(length);
-
-  for (uint32_t i = 0; i < length; ++i) {
-    JS::Value v;
-
-    if (!JS_GetElement(aCx, regions, i, &v)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    CameraRegion* r = regionArray.AppendElement();
-    /**
-     * These are the default values.  We can remove these when the xpidl
-     * dictionary parser gains the ability to grok default values.
-     */
-    r->top = -1000;
-    r->left = -1000;
-    r->bottom = 1000;
-    r->right = 1000;
-    r->weight = 1000;
-
-    nsresult rv = r->Init(aCx, &v);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%d\n",
-      i,
-      r->top,
-      r->left,
-      r->bottom,
-      r->right,
-      r->weight
-    );
-  }
-  SetParameter(aKey, regionArray);
-  return NS_OK;
-}
-
-nsresult
-nsCameraControl::GetHelper(JSContext* aCx, uint32_t aKey, JS::Value* aValue)
-{
-  nsTArray<CameraRegion> regionArray;
-
-  GetParameter(aKey, regionArray);
-
-  JSObject* array = JS_NewArrayObject(aCx, 0, nullptr);
-  if (!array) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  uint32_t length = regionArray.Length();
-  DOM_CAMERA_LOGI("%s:%d : got %d regions\n", __func__, __LINE__, length);
-
-  for (uint32_t i = 0; i < length; ++i) {
-    CameraRegion* r = &regionArray[i];
-    JS::Value v;
-
-    JSObject* o = JS_NewObject(aCx, nullptr, nullptr, nullptr);
-    if (!o) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    DOM_CAMERA_LOGI("top=%d\n", r->top);
-    v = INT_TO_JSVAL(r->top);
-    if (!JS_SetProperty(aCx, o, "top", &v)) {
-      return NS_ERROR_FAILURE;
-    }
-    DOM_CAMERA_LOGI("left=%d\n", r->left);
-    v = INT_TO_JSVAL(r->left);
-    if (!JS_SetProperty(aCx, o, "left", &v)) {
-      return NS_ERROR_FAILURE;
-    }
-    DOM_CAMERA_LOGI("bottom=%d\n", r->bottom);
-    v = INT_TO_JSVAL(r->bottom);
-    if (!JS_SetProperty(aCx, o, "bottom", &v)) {
-      return NS_ERROR_FAILURE;
-    }
-    DOM_CAMERA_LOGI("right=%d\n", r->right);
-    v = INT_TO_JSVAL(r->right);
-    if (!JS_SetProperty(aCx, o, "right", &v)) {
-      return NS_ERROR_FAILURE;
-    }
-    DOM_CAMERA_LOGI("weight=%d\n", r->weight);
-    v = INT_TO_JSVAL(r->weight);
-    if (!JS_SetProperty(aCx, o, "weight", &v)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    v = OBJECT_TO_JSVAL(o);
-    if (!JS_SetElement(aCx, array, i, &v)) {
-      return NS_ERROR_FAILURE;
-    }
-  }
-
-  *aValue = JS::ObjectValue(*array);
-  return NS_OK;
-}
-
-/* readonly attribute nsICameraCapabilities capabilities; */
-NS_IMETHODIMP
-nsCameraControl::GetCapabilities(nsICameraCapabilities** aCapabilities)
-{
-  if (!mCapabilities) {
-    mCapabilities = new nsCameraCapabilities(this);
-  }
-
-  nsCOMPtr<nsICameraCapabilities> capabilities = mCapabilities;
-  capabilities.forget(aCapabilities);
-  return NS_OK;
-}
-
-/* attribute DOMString effect; */
-NS_IMETHODIMP
-nsCameraControl::GetEffect(nsAString& aEffect)
-{
-  return GetHelper(CAMERA_PARAM_EFFECT, aEffect);
-}
-NS_IMETHODIMP
-nsCameraControl::SetEffect(const nsAString& aEffect)
-{
-  return SetHelper(CAMERA_PARAM_EFFECT, aEffect);
-}
-
-/* attribute DOMString whiteBalanceMode; */
-NS_IMETHODIMP
-nsCameraControl::GetWhiteBalanceMode(nsAString& aWhiteBalanceMode)
-{
-  return GetHelper(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
-}
-NS_IMETHODIMP
-nsCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode)
-{
-  return SetHelper(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
-}
-
-/* attribute DOMString sceneMode; */
-NS_IMETHODIMP
-nsCameraControl::GetSceneMode(nsAString& aSceneMode)
-{
-  return GetHelper(CAMERA_PARAM_SCENEMODE, aSceneMode);
-}
-NS_IMETHODIMP
-nsCameraControl::SetSceneMode(const nsAString& aSceneMode)
-{
-  return SetHelper(CAMERA_PARAM_SCENEMODE, aSceneMode);
-}
-
-/* attribute DOMString flashMode; */
-NS_IMETHODIMP
-nsCameraControl::GetFlashMode(nsAString& aFlashMode)
-{
-  return GetHelper(CAMERA_PARAM_FLASHMODE, aFlashMode);
-}
-NS_IMETHODIMP
-nsCameraControl::SetFlashMode(const nsAString& aFlashMode)
-{
-  return SetHelper(CAMERA_PARAM_FLASHMODE, aFlashMode);
-}
-
-/* attribute DOMString focusMode; */
-NS_IMETHODIMP
-nsCameraControl::GetFocusMode(nsAString& aFocusMode)
-{
-  return GetHelper(CAMERA_PARAM_FOCUSMODE, aFocusMode);
-}
-NS_IMETHODIMP
-nsCameraControl::SetFocusMode(const nsAString& aFocusMode)
-{
-  return SetHelper(CAMERA_PARAM_FOCUSMODE, aFocusMode);
-}
-
-/* attribute double zoom; */
-NS_IMETHODIMP
-nsCameraControl::GetZoom(double* aZoom)
-{
-  return GetHelper(CAMERA_PARAM_ZOOM, aZoom);
-}
-NS_IMETHODIMP
-nsCameraControl::SetZoom(double aZoom)
-{
-  return SetHelper(CAMERA_PARAM_ZOOM, aZoom);
-}
-
-/* attribute jsval meteringAreas; */
-NS_IMETHODIMP
-nsCameraControl::GetMeteringAreas(JSContext* cx, JS::Value* aMeteringAreas)
-{
-  return GetHelper(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas);
-}
-NS_IMETHODIMP
-nsCameraControl::SetMeteringAreas(JSContext* cx, const JS::Value& aMeteringAreas)
-{
-  return SetHelper(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas, mMaxMeteringAreas);
-}
-
-/* attribute jsval focusAreas; */
-NS_IMETHODIMP
-nsCameraControl::GetFocusAreas(JSContext* cx, JS::Value* aFocusAreas)
-{
-  return GetHelper(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas);
-}
-NS_IMETHODIMP
-nsCameraControl::SetFocusAreas(JSContext* cx, const JS::Value& aFocusAreas)
-{
-  return SetHelper(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas, mMaxFocusAreas);
-}
-
-/* readonly attribute double focalLength; */
-NS_IMETHODIMP
-nsCameraControl::GetFocalLength(double* aFocalLength)
-{
-  return GetHelper(CAMERA_PARAM_FOCALLENGTH, aFocalLength);
-}
-
-/* readonly attribute double focusDistanceNear; */
-NS_IMETHODIMP
-nsCameraControl::GetFocusDistanceNear(double* aFocusDistanceNear)
-{
-  return GetHelper(CAMERA_PARAM_FOCUSDISTANCENEAR, aFocusDistanceNear);
-}
-
-/* readonly attribute double focusDistanceOptimum; */
-NS_IMETHODIMP
-nsCameraControl::GetFocusDistanceOptimum(double* aFocusDistanceOptimum)
-{
-  return GetHelper(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, aFocusDistanceOptimum);
-}
-
-/* readonly attribute double focusDistanceFar; */
-NS_IMETHODIMP
-nsCameraControl::GetFocusDistanceFar(double* aFocusDistanceFar)
-{
-  return GetHelper(CAMERA_PARAM_FOCUSDISTANCEFAR, aFocusDistanceFar);
-}
-
-/* void setExposureCompensation (const JS::Value& aCompensation, JSContext* cx); */
-NS_IMETHODIMP
-nsCameraControl::SetExposureCompensation(const JS::Value& aCompensation, JSContext* cx)
-{
-  if (aCompensation.isNullOrUndefined()) {
-    // use NaN to switch the camera back into auto mode
-    return SetHelper(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN);
-  }
-
-  double compensation;
-  if (!JS_ValueToNumber(cx, aCompensation, &compensation)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  return SetHelper(CAMERA_PARAM_EXPOSURECOMPENSATION, compensation);
-}
-
-/* readonly attribute double exposureCompensation; */
-NS_IMETHODIMP
-nsCameraControl::GetExposureCompensation(double* aExposureCompensation)
-{
-  return GetHelper(CAMERA_PARAM_EXPOSURECOMPENSATION, aExposureCompensation);
-}
-
-/* attribute nsICameraShutterCallback onShutter; */
-NS_IMETHODIMP
-nsCameraControl::GetOnShutter(nsICameraShutterCallback** aOnShutter)
-{
-  *aOnShutter = mOnShutterCb;
-  return NS_OK;
-}
-NS_IMETHODIMP
-nsCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter)
-{
-  mOnShutterCb = aOnShutter;
-  return NS_OK;
-}
-
-/* void startRecording (in jsval aOptions, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
-NS_IMETHODIMP
-nsCameraControl::StartRecording(const JS::Value& aOptions, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
-{
-  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
-
-  CameraSize size;
-  nsresult rv = size.Init(cx, &aOptions);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIRunnable> startRecordingTask = new StartRecordingTask(this, size, onSuccess, onError);
-  mCameraThread->Dispatch(startRecordingTask, NS_DISPATCH_NORMAL);
-
-  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-  if (!obs) {
-    NS_WARNING("Could not get the Observer service for CameraControl::StartRecording.");
-    return NS_ERROR_FAILURE;
-  }
-
-  obs->NotifyObservers(nullptr,
-                       "recording-device-events",
-                       NS_LITERAL_STRING("starting").get());
-
-  return NS_OK;
-}
-
-/* void stopRecording (); */
-NS_IMETHODIMP
-nsCameraControl::StopRecording()
-{
-  nsCOMPtr<nsIRunnable> stopRecordingTask = new StopRecordingTask(this);
-  mCameraThread->Dispatch(stopRecordingTask, NS_DISPATCH_NORMAL);
-
-  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-  if (!obs) {
-    NS_WARNING("Could not get the Observer service for CameraControl::StopRecording.");
-    return NS_ERROR_FAILURE;
-  }
-
-  obs->NotifyObservers(nullptr,
-                       "recording-device-events",
-                       NS_LITERAL_STRING("shutdown").get());
-
-  return NS_OK;
-}
-
-/* [implicit_jscontext] void getPreviewStream (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
-NS_IMETHODIMP
-nsCameraControl::GetPreviewStream(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
-{
-  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
-
-  CameraSize size;
-  nsresult rv = size.Init(cx, &aOptions);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIRunnable> getPreviewStreamTask = new GetPreviewStreamTask(this, size, onSuccess, onError);
-  return NS_DispatchToMainThread(getPreviewStreamTask);
-}
-
-/* void autoFocus (in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
-NS_IMETHODIMP
-nsCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
-{
-  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
-
-  nsCOMPtr<nsIRunnable> autoFocusTask = new AutoFocusTask(this, onSuccess, onError);
-  mCameraThread->Dispatch(autoFocusTask, NS_DISPATCH_NORMAL);
-
-  return NS_OK;
-}
-
-/* void takePicture (in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
-NS_IMETHODIMP nsCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
-{
-  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
-
-  CameraPictureOptions  options;
-  CameraSize            size;
-  CameraPosition        pos;
-
-  nsresult rv = options.Init(cx, &aOptions);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = size.Init(cx, &options.pictureSize);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  /**
-   * Default values, until the dictionary parser can handle them.
-   * NaN indicates no value provided.
-   */
-  pos.latitude = NAN;
-  pos.longitude = NAN;
-  pos.altitude = NAN;
-  pos.timestamp = NAN;
-  rv = pos.Init(cx, &options.position);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIRunnable> takePictureTask = new TakePictureTask(this, size, options.rotation, options.fileFormat, pos, onSuccess, onError);
-  mCameraThread->Dispatch(takePictureTask, NS_DISPATCH_NORMAL);
-
-  return NS_OK;
-}
-
-void
-nsCameraControl::AutoFocusComplete(bool aSuccess)
-{
-  /**
-   * Auto focusing can change some of the camera's parameters, so
-   * we need to pull a new set before sending the result to the
-   * main thread.
-   */
-  PullParametersImpl(nullptr);
-
-  nsCOMPtr<nsIRunnable> autoFocusResult = new AutoFocusResult(aSuccess, mAutoFocusOnSuccessCb);
-
-  nsresult rv = NS_DispatchToMainThread(autoFocusResult);
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Failed to dispatch autoFocus() onSuccess callback to main thread!");
-  }
-}
-
-void
-nsCameraControl::TakePictureComplete(uint8_t* aData, uint32_t aLength)
-{
-  uint8_t* data = new uint8_t[aLength];
-
-  memcpy(data, aData, aLength);
-
-  /**
-   * TODO: pick up the actual specified picture format for the MIME type;
-   * for now, assume we'll be using JPEGs.
-   */
-  nsIDOMBlob* blob = new nsDOMMemoryFile(static_cast<void*>(data), static_cast<uint64_t>(aLength), NS_LITERAL_STRING("image/jpeg"));
-  nsCOMPtr<nsIRunnable> takePictureResult = new TakePictureResult(blob, mTakePictureOnSuccessCb);
-
-  nsresult rv = NS_DispatchToMainThread(takePictureResult);
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Failed to dispatch takePicture() onSuccess callback to main thread!");
-  }
-}
new file mode 100644
--- /dev/null
+++ b/dom/camera/CameraControlImpl.cpp
@@ -0,0 +1,244 @@
+/* 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 "base/basictypes.h"
+#include "DOMCameraPreview.h"
+#include "CameraControlImpl.h"
+#include "CameraCommon.h"
+
+using namespace mozilla;
+
+// Helpers for string properties.
+nsresult
+CameraControlImpl::Set(uint32_t aKey, const nsAString& aValue)
+{
+  SetParameter(aKey, NS_ConvertUTF16toUTF8(aValue).get());
+  return NS_OK;
+}
+
+nsresult
+CameraControlImpl::Get(uint32_t aKey, nsAString& aValue)
+{
+  const char* value = GetParameterConstChar(aKey);
+  if (!value) {
+    return NS_ERROR_FAILURE;
+  }
+
+  aValue.AssignASCII(value);
+  return NS_OK;
+}
+
+// Helpers for doubles.
+nsresult
+CameraControlImpl::Set(uint32_t aKey, double aValue)
+{
+  SetParameter(aKey, aValue);
+  return NS_OK;
+}
+
+nsresult
+CameraControlImpl::Get(uint32_t aKey, double* aValue)
+{
+  MOZ_ASSERT(aValue);
+  *aValue = GetParameterDouble(aKey);
+  return NS_OK;
+}
+
+// Helper for weighted regions.
+nsresult
+CameraControlImpl::Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit)
+{
+  if (aLimit == 0) {
+    DOM_CAMERA_LOGI("%s:%d : aLimit = 0, nothing to do\n", __func__, __LINE__);
+    return NS_OK;
+  }
+
+  if (!aValue.isObject()) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  uint32_t length = 0;
+
+  JSObject* regions = &aValue.toObject();
+  if (!JS_GetArrayLength(aCx, regions, &length)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  DOM_CAMERA_LOGI("%s:%d : got %d regions (limited to %d)\n", __func__, __LINE__, length, aLimit);
+  if (length > aLimit) {
+    length = aLimit;
+  }
+
+  nsTArray<CameraRegion> regionArray;
+  regionArray.SetCapacity(length);
+
+  for (uint32_t i = 0; i < length; ++i) {
+    JS::Value v;
+
+    if (!JS_GetElement(aCx, regions, i, &v)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    CameraRegion* r = regionArray.AppendElement();
+    /**
+     * These are the default values.  We can remove these when the xpidl
+     * dictionary parser gains the ability to grok default values.
+     */
+    r->top = -1000;
+    r->left = -1000;
+    r->bottom = 1000;
+    r->right = 1000;
+    r->weight = 1000;
+
+    nsresult rv = r->Init(aCx, &v);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    DOM_CAMERA_LOGI("region %d: top=%d, left=%d, bottom=%d, right=%d, weight=%d\n",
+      i,
+      r->top,
+      r->left,
+      r->bottom,
+      r->right,
+      r->weight
+    );
+  }
+  SetParameter(aKey, regionArray);
+  return NS_OK;
+}
+
+nsresult
+CameraControlImpl::Get(JSContext* aCx, uint32_t aKey, JS::Value* aValue)
+{
+  nsTArray<CameraRegion> regionArray;
+
+  GetParameter(aKey, regionArray);
+
+  JSObject* array = JS_NewArrayObject(aCx, 0, nullptr);
+  if (!array) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  uint32_t length = regionArray.Length();
+  DOM_CAMERA_LOGI("%s:%d : got %d regions\n", __func__, __LINE__, length);
+
+  for (uint32_t i = 0; i < length; ++i) {
+    CameraRegion* r = &regionArray[i];
+    JS::Value v;
+
+    JSObject* o = JS_NewObject(aCx, nullptr, nullptr, nullptr);
+    if (!o) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    DOM_CAMERA_LOGI("top=%d\n", r->top);
+    v = INT_TO_JSVAL(r->top);
+    if (!JS_SetProperty(aCx, o, "top", &v)) {
+      return NS_ERROR_FAILURE;
+    }
+    DOM_CAMERA_LOGI("left=%d\n", r->left);
+    v = INT_TO_JSVAL(r->left);
+    if (!JS_SetProperty(aCx, o, "left", &v)) {
+      return NS_ERROR_FAILURE;
+    }
+    DOM_CAMERA_LOGI("bottom=%d\n", r->bottom);
+    v = INT_TO_JSVAL(r->bottom);
+    if (!JS_SetProperty(aCx, o, "bottom", &v)) {
+      return NS_ERROR_FAILURE;
+    }
+    DOM_CAMERA_LOGI("right=%d\n", r->right);
+    v = INT_TO_JSVAL(r->right);
+    if (!JS_SetProperty(aCx, o, "right", &v)) {
+      return NS_ERROR_FAILURE;
+    }
+    DOM_CAMERA_LOGI("weight=%d\n", r->weight);
+    v = INT_TO_JSVAL(r->weight);
+    if (!JS_SetProperty(aCx, o, "weight", &v)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    v = OBJECT_TO_JSVAL(o);
+    if (!JS_SetElement(aCx, array, i, &v)) {
+      return NS_ERROR_FAILURE;
+    }
+  }
+
+  *aValue = JS::ObjectValue(*array);
+  return NS_OK;
+}
+
+nsresult
+CameraControlImpl::GetPreviewStream(CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
+{
+  /**
+   * The camera preview stream object is DOM-facing, and as such
+   * must be a cycle-collection participant created on the main
+   * thread.
+   */
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIRunnable> getPreviewStreamTask = new GetPreviewStreamTask(this, aSize, onSuccess, onError);
+  return NS_DispatchToCurrentThread(getPreviewStreamTask);
+}
+
+nsresult
+CameraControlImpl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
+{
+  nsCOMPtr<nsIRunnable> autoFocusTask = new AutoFocusTask(this, onSuccess, onError);
+  return mCameraThread->Dispatch(autoFocusTask, NS_DISPATCH_NORMAL);
+}
+
+nsresult
+CameraControlImpl::TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
+{
+  nsCOMPtr<nsIRunnable> takePictureTask = new TakePictureTask(this, aSize, aRotation, aFileFormat, aPosition, onSuccess, onError);
+  return mCameraThread->Dispatch(takePictureTask, NS_DISPATCH_NORMAL);
+}
+
+nsresult
+CameraControlImpl::StartRecording(CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
+{
+  nsCOMPtr<nsIRunnable> startRecordingTask = new StartRecordingTask(this, aSize, onSuccess, onError);
+  return mCameraThread->Dispatch(startRecordingTask, NS_DISPATCH_NORMAL);
+}
+
+nsresult
+CameraControlImpl::StopRecording()
+{
+  nsCOMPtr<nsIRunnable> stopRecordingTask = new StopRecordingTask(this);
+  return mCameraThread->Dispatch(stopRecordingTask, NS_DISPATCH_NORMAL);
+}
+
+nsresult
+CameraControlImpl::StartPreview(DOMCameraPreview* aDOMPreview)
+{
+  nsCOMPtr<nsIRunnable> startPreviewTask = new StartPreviewTask(this, aDOMPreview);
+  return mCameraThread->Dispatch(startPreviewTask, NS_DISPATCH_NORMAL);
+}
+
+void
+CameraControlImpl::StopPreview()
+{
+  nsCOMPtr<nsIRunnable> stopPreviewTask = new StopPreviewTask(this);
+  mCameraThread->Dispatch(stopPreviewTask, NS_DISPATCH_NORMAL);
+}
+
+void
+CameraControlImpl::ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder)
+{
+  if (mDOMPreview) {
+    mDOMPreview->ReceiveFrame(aBuffer, aFormat, aBuilder);
+  }
+}
+
+NS_IMETHODIMP
+GetPreviewStreamResult::Run()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (mOnSuccessCb) {
+    nsCOMPtr<nsIDOMMediaStream> stream = new DOMCameraPreview(mCameraControl, mWidth, mHeight, mFramesPerSecond);
+    mOnSuccessCb->HandleEvent(stream);
+  }
+  return NS_OK;
+}
rename from dom/camera/CameraControl.h
rename to dom/camera/CameraControlImpl.h
--- a/dom/camera/CameraControl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -1,223 +1,227 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef DOM_CAMERA_NSCAMERACONTROL_H
-#define DOM_CAMERA_NSCAMERACONTROL_H
+#ifndef DOM_CAMERA_CAMERACONTROLIMPL_H
+#define DOM_CAMERA_CAMERACONTROLIMPL_H
 
-#include "prtypes.h"
 #include "nsCOMPtr.h"
-#include "nsThread.h"
 #include "nsDOMFile.h"
 #include "DictionaryHelpers.h"
-#include "CameraPreview.h"
 #include "nsIDOMCameraManager.h"
-
-#define DOM_CAMERA_LOG_LEVEL 3
+#include "ICameraControl.h"
 #include "CameraCommon.h"
 
 namespace mozilla {
 
 using namespace dom;
 
 class GetPreviewStreamTask;
+class StartPreviewTask;
+class StopPreviewTask;
 class AutoFocusTask;
 class TakePictureTask;
 class StartRecordingTask;
 class StopRecordingTask;
 class SetParameterTask;
 class GetParameterTask;
-class PushParametersTask;
-class PullParametersTask;
 
-// Main camera control.
-class nsCameraControl : public nsICameraControl
+class DOMCameraPreview;
+
+class CameraControlImpl : public ICameraControl
 {
   friend class GetPreviewStreamTask;
+  friend class StartPreviewTask;
+  friend class StopPreviewTask;
   friend class AutoFocusTask;
   friend class TakePictureTask;
   friend class StartRecordingTask;
   friend class StopRecordingTask;
   friend class SetParameterTask;
   friend class GetParameterTask;
-  friend class PushParametersTask;
-  friend class PullParametersTask;
 
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSICAMERACONTROL
-
-  enum {
-    CAMERA_PARAM_EFFECT,
-    CAMERA_PARAM_WHITEBALANCE,
-    CAMERA_PARAM_SCENEMODE,
-    CAMERA_PARAM_FLASHMODE,
-    CAMERA_PARAM_FOCUSMODE,
-    CAMERA_PARAM_ZOOM,
-    CAMERA_PARAM_METERINGAREAS,
-    CAMERA_PARAM_FOCUSAREAS,
-    CAMERA_PARAM_FOCALLENGTH,
-    CAMERA_PARAM_FOCUSDISTANCENEAR,
-    CAMERA_PARAM_FOCUSDISTANCEOPTIMUM,
-    CAMERA_PARAM_FOCUSDISTANCEFAR,
-    CAMERA_PARAM_EXPOSURECOMPENSATION,
+  CameraControlImpl(uint32_t aCameraId, nsIThread* aCameraThread)
+    : mCameraId(aCameraId)
+    , mCameraThread(aCameraThread)
+    , mFileFormat()
+    , mMaxMeteringAreas(0)
+    , mMaxFocusAreas(0)
+    , mDOMPreview(nullptr)
+    , mAutoFocusOnSuccessCb(nullptr)
+    , mAutoFocusOnErrorCb(nullptr)
+    , mTakePictureOnSuccessCb(nullptr)
+    , mTakePictureOnErrorCb(nullptr)
+    , mStartRecordingOnSuccessCb(nullptr)
+    , mStartRecordingOnErrorCb(nullptr)
+    , mOnShutterCb(nullptr)
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
-    CAMERA_PARAM_SUPPORTED_PREVIEWSIZES,
-    CAMERA_PARAM_SUPPORTED_VIDEOSIZES,
-    CAMERA_PARAM_SUPPORTED_PICTURESIZES,
-    CAMERA_PARAM_SUPPORTED_PICTUREFORMATS,
-    CAMERA_PARAM_SUPPORTED_WHITEBALANCES,
-    CAMERA_PARAM_SUPPORTED_SCENEMODES,
-    CAMERA_PARAM_SUPPORTED_EFFECTS,
-    CAMERA_PARAM_SUPPORTED_FLASHMODES,
-    CAMERA_PARAM_SUPPORTED_FOCUSMODES,
-    CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS,
-    CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS,
-    CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION,
-    CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION,
-    CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP,
-    CAMERA_PARAM_SUPPORTED_ZOOM,
-    CAMERA_PARAM_SUPPORTED_ZOOMRATIOS
-  };
+  nsresult GetPreviewStream(CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError);
+  nsresult StartPreview(DOMCameraPreview* aDOMPreview);
+  void StopPreview();
+  nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError);
+  nsresult TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError);
+  nsresult StartRecording(CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError);
+  nsresult StopRecording();
+
+  nsresult Set(uint32_t aKey, const nsAString& aValue);
+  nsresult Get(uint32_t aKey, nsAString& aValue);
+  nsresult Set(uint32_t aKey, double aValue);
+  nsresult Get(uint32_t aKey, double* aValue);
+  nsresult Set(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit);
+  nsresult Get(JSContext* aCx, uint32_t aKey, JS::Value* aValue);
+
+  nsresult SetFocusAreas(JSContext* aCx, const JS::Value& aValue)
+  {
+    return Set(aCx, CAMERA_PARAM_FOCUSAREAS, aValue, mMaxFocusAreas);
+  }
+
+  nsresult SetMeteringAreas(JSContext* aCx, const JS::Value& aValue)
+  {
+    return Set(aCx, CAMERA_PARAM_METERINGAREAS, aValue, mMaxMeteringAreas);
+  }
+
   virtual const char* GetParameter(const char* aKey) = 0;
   virtual const char* GetParameterConstChar(uint32_t aKey) = 0;
   virtual double GetParameterDouble(uint32_t aKey) = 0;
   virtual void GetParameter(uint32_t aKey, nsTArray<CameraRegion>& aRegions) = 0;
   virtual void SetParameter(const char* aKey, const char* aValue) = 0;
   virtual void SetParameter(uint32_t aKey, const char* aValue) = 0;
   virtual void SetParameter(uint32_t aKey, double aValue) = 0;
   virtual void SetParameter(uint32_t aKey, const nsTArray<CameraRegion>& aRegions) = 0;
-  virtual void PushParameters() = 0;
+  virtual nsresult PushParameters() = 0;
 
-  nsCameraControl(uint32_t aCameraId, nsIThread* aCameraThread)
-    : mCameraId(aCameraId)
-    , mCameraThread(aCameraThread)
-    , mCapabilities(nullptr)
-    , mPreview(nullptr)
-    , mFileFormat()
-    , mMaxMeteringAreas(0)
-    , mMaxFocusAreas(0)
-    , mAutoFocusOnSuccessCb(nullptr)
-    , mAutoFocusOnErrorCb(nullptr)
-    , mTakePictureOnSuccessCb(nullptr)
-    , mTakePictureOnErrorCb(nullptr)
-    , mStartRecordingOnSuccessCb(nullptr)
-    , mStartRecordingOnErrorCb(nullptr)
-    , mOnShutterCb(nullptr)
-  { }
-
-  void TakePictureComplete(uint8_t *aData, uint32_t aLength);
-  void AutoFocusComplete(bool aSuccess);
+  void ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
 
 protected:
-  virtual ~nsCameraControl() { }
-
-  nsresult SetHelper(uint32_t aKey, const nsAString& aValue);
-  nsresult GetHelper(uint32_t aKey, nsAString& aValue);
-  nsresult SetHelper(uint32_t aKey, double aValue);
-  nsresult GetHelper(uint32_t aKey, double* aValue);
-  nsresult SetHelper(JSContext* aCx, uint32_t aKey, const JS::Value& aValue, uint32_t aLimit);
-  nsresult GetHelper(JSContext* aCx, uint32_t aKey, JS::Value* aValue);
+  virtual ~CameraControlImpl()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   virtual nsresult GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream) = 0;
+  virtual nsresult StartPreviewImpl(StartPreviewTask* aStartPreview) = 0;
+  virtual nsresult StopPreviewImpl(StopPreviewTask* aStopPreview) = 0;
   virtual nsresult AutoFocusImpl(AutoFocusTask* aAutoFocus) = 0;
   virtual nsresult TakePictureImpl(TakePictureTask* aTakePicture) = 0;
   virtual nsresult StartRecordingImpl(StartRecordingTask* aStartRecording) = 0;
   virtual nsresult StopRecordingImpl(StopRecordingTask* aStopRecording) = 0;
-  virtual nsresult PushParametersImpl(PushParametersTask* aPushParameters) = 0;
-  virtual nsresult PullParametersImpl(PullParametersTask* aPullParameters) = 0;
+  virtual nsresult PushParametersImpl() = 0;
+  virtual nsresult PullParametersImpl() = 0;
 
-private:
-  nsCameraControl(const nsCameraControl&) MOZ_DELETE;
-  nsCameraControl& operator=(const nsCameraControl&) MOZ_DELETE;
+  uint32_t            mCameraId;
+  nsCOMPtr<nsIThread> mCameraThread;
+  nsString            mFileFormat;
+  uint32_t            mMaxMeteringAreas;
+  uint32_t            mMaxFocusAreas;
 
-protected:
-  /* additional members */
-  uint32_t                        mCameraId;
-  nsCOMPtr<nsIThread>             mCameraThread;
-  nsCOMPtr<nsICameraCapabilities> mCapabilities;
-  uint32_t                        mPreviewWidth;
-  uint32_t                        mPreviewHeight;
-  nsCOMPtr<CameraPreview>         mPreview;
-  nsString                        mFileFormat;
-  uint32_t                        mMaxMeteringAreas;
-  uint32_t                        mMaxFocusAreas;
+  /**
+   * 'mDOMPreview' is a raw pointer to the object that will receive incoming
+   * preview frames.  This is guaranteed to be valid, or null.
+   *
+   * It is set by a call to StartPreview(), and set to null on StopPreview().
+   * It is up to the caller to ensure that the object will not disappear
+   * out from under this pointer--usually by calling NS_ADDREF().
+   */
+  DOMCameraPreview*   mDOMPreview;
 
   nsCOMPtr<nsICameraAutoFocusCallback>      mAutoFocusOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback>          mAutoFocusOnErrorCb;
   nsCOMPtr<nsICameraTakePictureCallback>    mTakePictureOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback>          mTakePictureOnErrorCb;
   nsCOMPtr<nsICameraStartRecordingCallback> mStartRecordingOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback>          mStartRecordingOnErrorCb;
   nsCOMPtr<nsICameraShutterCallback>        mOnShutterCb;
+
+private:
+  CameraControlImpl(const CameraControlImpl&) MOZ_DELETE;
+  CameraControlImpl& operator=(const CameraControlImpl&) MOZ_DELETE;
 };
 
 // Return the resulting preview stream to JS.  Runs on the main thread.
 class GetPreviewStreamResult : public nsRunnable
 {
 public:
-  GetPreviewStreamResult(nsIDOMMediaStream* aStream, nsICameraPreviewStreamCallback* onSuccess)
-    : mStream(aStream)
+  GetPreviewStreamResult(CameraControlImpl* aCameraControl, uint32_t aWidth, uint32_t aHeight, uint32_t aFramesPerSecond, nsICameraPreviewStreamCallback* onSuccess)
+    : mCameraControl(aCameraControl)
+    , mWidth(aWidth)
+    , mHeight(aHeight)
+    , mFramesPerSecond(aFramesPerSecond)
     , mOnSuccessCb(onSuccess)
-  { }
-
-  NS_IMETHOD Run()
   {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    if (mOnSuccessCb) {
-      mOnSuccessCb->HandleEvent(mStream);
-    }
-    return NS_OK;
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
+  virtual ~GetPreviewStreamResult()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  // Run() method is implementation specific.
+  NS_IMETHOD Run();
+
 protected:
-  nsCOMPtr<nsIDOMMediaStream> mStream;
+  nsRefPtr<CameraControlImpl> mCameraControl;
+  uint32_t mWidth;
+  uint32_t mHeight;
+  uint32_t mFramesPerSecond;
   nsCOMPtr<nsICameraPreviewStreamCallback> mOnSuccessCb;
 };
 
 // Get the desired preview stream.
 class GetPreviewStreamTask : public nsRunnable
 {
 public:
-  GetPreviewStreamTask(nsCameraControl* aCameraControl, CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
+  GetPreviewStreamTask(CameraControlImpl* aCameraControl, CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError)
     : mSize(aSize)
     , mCameraControl(aCameraControl)
     , mOnSuccessCb(onSuccess)
     , mOnErrorCb(onError)
-  { }
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~GetPreviewStreamTask()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
     nsresult rv = mCameraControl->GetPreviewStreamImpl(this);
 
     if (NS_FAILED(rv) && mOnErrorCb) {
       rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE")));
       NS_ENSURE_SUCCESS(rv, rv);
     }
     return rv;
   }
 
   CameraSize mSize;
-  nsCOMPtr<nsCameraControl> mCameraControl;
+  nsRefPtr<CameraControlImpl> mCameraControl;
   nsCOMPtr<nsICameraPreviewStreamCallback> mOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
 };
 
 // Return the autofocus status to JS.  Runs on the main thread.
 class AutoFocusResult : public nsRunnable
 {
 public:
   AutoFocusResult(bool aSuccess, nsICameraAutoFocusCallback* onSuccess)
     : mSuccess(aSuccess)
     , mOnSuccessCb(onSuccess)
   { }
 
+  virtual ~AutoFocusResult() { }
+
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mOnSuccessCb) {
       mOnSuccessCb->HandleEvent(mSuccess);
     }
     return NS_OK;
@@ -227,92 +231,115 @@ protected:
   bool mSuccess;
   nsCOMPtr<nsICameraAutoFocusCallback> mOnSuccessCb;
 };
 
 // Autofocus the camera.
 class AutoFocusTask : public nsRunnable
 {
 public:
-  AutoFocusTask(nsCameraControl* aCameraControl, nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
+  AutoFocusTask(CameraControlImpl* aCameraControl, nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
     : mCameraControl(aCameraControl)
     , mOnSuccessCb(onSuccess)
     , mOnErrorCb(onError)
-  { }
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~AutoFocusTask()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->AutoFocusImpl(this);
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     if (NS_FAILED(rv) && mOnErrorCb) {
       rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE")));
       NS_ENSURE_SUCCESS(rv, rv);
     }
     return rv;
   }
 
-  nsCOMPtr<nsCameraControl> mCameraControl;
+  nsRefPtr<CameraControlImpl> mCameraControl;
   nsCOMPtr<nsICameraAutoFocusCallback> mOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
 };
 
 // Return the captured picture to JS.  Runs on the main thread.
 class TakePictureResult : public nsRunnable
 {
 public:
   TakePictureResult(nsIDOMBlob* aImage, nsICameraTakePictureCallback* onSuccess)
     : mImage(aImage)
     , mOnSuccessCb(onSuccess)
-  { }
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~TakePictureResult()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
     if (mOnSuccessCb) {
       mOnSuccessCb->HandleEvent(mImage);
     }
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
     return NS_OK;
   }
 
 protected:
   nsCOMPtr<nsIDOMBlob> mImage;
   nsCOMPtr<nsICameraTakePictureCallback> mOnSuccessCb;
 };
 
 // Capture a still image with the camera.
 class TakePictureTask : public nsRunnable
 {
 public:
-  TakePictureTask(nsCameraControl* aCameraControl, CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
+  TakePictureTask(CameraControlImpl* aCameraControl, CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
     : mCameraControl(aCameraControl)
     , mSize(aSize)
     , mRotation(aRotation)
     , mFileFormat(aFileFormat)
     , mPosition(aPosition)
     , mOnSuccessCb(onSuccess)
     , mOnErrorCb(onError)
-  { }
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~TakePictureTask()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->TakePictureImpl(this);
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     if (NS_FAILED(rv) && mOnErrorCb) {
       rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE")));
       NS_ENSURE_SUCCESS(rv, rv);
     }
     return rv;
   }
 
-  nsCOMPtr<nsCameraControl> mCameraControl;
+  nsRefPtr<CameraControlImpl> mCameraControl;
   CameraSize mSize;
   int32_t mRotation;
   nsString mFileFormat;
   CameraPosition mPosition;
   nsCOMPtr<nsICameraTakePictureCallback> mOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
 };
 
@@ -320,16 +347,18 @@ public:
 class StartRecordingResult : public nsRunnable
 {
 public:
   StartRecordingResult(nsIDOMMediaStream* aStream, nsICameraStartRecordingCallback* onSuccess)
     : mStream(aStream)
     , mOnSuccessCb(onSuccess)
   { }
 
+  virtual ~StartRecordingResult() { }
+
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mOnSuccessCb) {
       mOnSuccessCb->HandleEvent(mStream);
     }
     return NS_OK;
@@ -339,100 +368,129 @@ protected:
   nsCOMPtr<nsIDOMMediaStream> mStream;
   nsCOMPtr<nsICameraStartRecordingCallback> mOnSuccessCb;
 };
 
 // Start video recording.
 class StartRecordingTask : public nsRunnable
 {
 public:
-  StartRecordingTask(nsCameraControl* aCameraControl, CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
+  StartRecordingTask(CameraControlImpl* aCameraControl, CameraSize aSize, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
     : mSize(aSize)
     , mCameraControl(aCameraControl)
     , mOnSuccessCb(onSuccess)
     , mOnErrorCb(onError)
-  { }
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~StartRecordingTask()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->StartRecordingImpl(this);
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     if (NS_FAILED(rv) && mOnErrorCb) {
       rv = NS_DispatchToMainThread(new CameraErrorResult(mOnErrorCb, NS_LITERAL_STRING("FAILURE")));
       NS_ENSURE_SUCCESS(rv, rv);
     }
     return rv;
   }
 
   CameraSize mSize;
-  nsCOMPtr<nsCameraControl> mCameraControl;
+  nsRefPtr<CameraControlImpl> mCameraControl;
   nsCOMPtr<nsICameraStartRecordingCallback> mOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
 };
 
 // Stop video recording.
 class StopRecordingTask : public nsRunnable
 {
 public:
-  StopRecordingTask(nsCameraControl* aCameraControl)
+  StopRecordingTask(CameraControlImpl* aCameraControl)
     : mCameraControl(aCameraControl)
-  { }
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~StopRecordingTask()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
     nsresult rv = mCameraControl->StopRecordingImpl(this);
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
 
-  nsCOMPtr<nsCameraControl> mCameraControl;
+  nsRefPtr<CameraControlImpl> mCameraControl;
 };
 
-// Pushes all camera parameters to the camera.
-class PushParametersTask : public nsRunnable
+// Start the preview.
+class StartPreviewTask : public nsRunnable
 {
 public:
-  PushParametersTask(nsCameraControl* aCameraControl)
+  StartPreviewTask(CameraControlImpl* aCameraControl, DOMCameraPreview* aDOMPreview)
     : mCameraControl(aCameraControl)
-  { }
+    , mDOMPreview(aDOMPreview)
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~StartPreviewTask()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
-    nsresult rv = mCameraControl->PushParametersImpl(this);
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
+    nsresult rv = mCameraControl->StartPreviewImpl(this);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
 
-  nsCOMPtr<nsCameraControl> mCameraControl;
+  nsRefPtr<CameraControlImpl> mCameraControl;
+  DOMCameraPreview* mDOMPreview; // DOMCameraPreview NS_ADDREFs itself for us
 };
 
-// Get all camera parameters from the camera.
-class PullParametersTask : public nsRunnable
+// Stop the preview.
+class StopPreviewTask : public nsRunnable
 {
 public:
-  PullParametersTask(nsCameraControl* aCameraControl)
+  StopPreviewTask(CameraControlImpl* aCameraControl)
     : mCameraControl(aCameraControl)
-  { }
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  virtual ~StopPreviewTask()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
 
   NS_IMETHOD Run()
   {
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
-    nsresult rv = mCameraControl->PullParametersImpl(this);
-    DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
+    mCameraControl->StopPreviewImpl(this);
+    DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
-    NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
 
-  nsCOMPtr<nsCameraControl> mCameraControl;
+  nsRefPtr<CameraControlImpl> mCameraControl;
 };
 
 } // namespace mozilla
 
-#endif // DOM_CAMERA_NSCAMERACONTROL_H
+#endif // DOM_CAMERA_CAMERACONTROLIMPL_H
deleted file mode 100644
--- a/dom/camera/CameraPreview.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "CameraPreview.h"
-#include "Layers.h"
-#include "ImageContainer.h"
-#define DOM_CAMERA_LOG_LEVEL  3
-#include "CameraCommon.h"
-
-using namespace mozilla;
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(CameraPreview, CameraPreview)
-
-class CameraPreviewListener : public MediaStreamListener
-{
-public:
-  CameraPreviewListener(CameraPreview* aPreview) :
-    mPreview(aPreview)
-  {
-    DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
-  }
-
-  ~CameraPreviewListener()
-  {
-    DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
-  }
-
-  void NotifyConsumptionChanged(MediaStreamGraph* aGraph, Consumption aConsuming)
-  {
-    const char* state;
-
-    DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
-
-    switch (aConsuming) {
-      case NOT_CONSUMED:
-        state = "not consuming";
-        break;
-
-      case CONSUMED:
-        state = "consuming";
-        break;
-
-      default:
-        state = "unknown";
-        break;
-    }
-
-    DOM_CAMERA_LOGA("camera viewfinder is %s\n", state);
-
-    switch (aConsuming) {
-      case NOT_CONSUMED:
-        mPreview->Stop();
-        break;
-
-      case CONSUMED:
-        mPreview->Start();
-        break;
-    }
-  }
-
-protected:
-  nsCOMPtr<CameraPreview> mPreview;
-};
-
-CameraPreview::CameraPreview(nsIThread* aCameraThread, uint32_t aWidth, uint32_t aHeight)
-  : nsDOMMediaStream()
-  , mWidth(aWidth)
-  , mHeight(aHeight)
-  , mFramesPerSecond(0)
-  , mFrameCount(0)
-  , mCameraThread(aCameraThread)
-{
-  DOM_CAMERA_LOGI("%s:%d : mWidth=%d, mHeight=%d : this=%p\n", __func__, __LINE__, mWidth, mHeight, this);
-
-  mImageContainer = LayerManager::CreateImageContainer();
-  MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
-  mStream = gm->CreateInputStream(this);
-  mInput = GetStream()->AsSourceStream();
-  mInput->AddListener(new CameraPreviewListener(this));
-}
-
-void
-CameraPreview::SetFrameRate(uint32_t aFramesPerSecond)
-{
-  mFramesPerSecond = aFramesPerSecond;
-  mInput->AddTrack(TRACK_VIDEO, mFramesPerSecond, 0, new VideoSegment());
-  mInput->AdvanceKnownTracksTime(MEDIA_TIME_MAX);
-}
-
-void
-CameraPreview::Start()
-{
-  nsCOMPtr<nsIRunnable> cameraPreviewControl = NS_NewRunnableMethod(this, &CameraPreview::StartImpl);
-  nsresult rv = mCameraThread->Dispatch(cameraPreviewControl, NS_DISPATCH_NORMAL);
-  if (NS_FAILED(rv)) {
-    DOM_CAMERA_LOGE("failed to start camera preview (%d)\n", rv);
-  }
-}
-
-void
-CameraPreview::Stop()
-{
-  nsCOMPtr<nsIRunnable> cameraPreviewControl = NS_NewRunnableMethod(this, &CameraPreview::StopImpl);
-  nsresult rv = mCameraThread->Dispatch(cameraPreviewControl, NS_DISPATCH_NORMAL);
-  if (NS_FAILED(rv)) {
-    DOM_CAMERA_LOGE("failed to stop camera preview (%d)\n", rv);
-  }
-}
-
-CameraPreview::~CameraPreview()
-{
-  DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
-}
deleted file mode 100644
--- a/dom/camera/CameraPreview.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DOM_CAMERA_CAMERAPREVIEW_H
-#define DOM_CAMERA_CAMERAPREVIEW_H
-
-#include "MediaStreamGraph.h"
-#include "StreamBuffer.h"
-#include "nsDOMMediaStream.h"
-
-#define DOM_CAMERA_LOG_LEVEL  3
-#include "CameraCommon.h"
-
-using namespace mozilla;
-using namespace mozilla::layers;
-
-namespace mozilla {
-
-class CameraPreview : public nsDOMMediaStream
-                    , public MediaStreamListener
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  CameraPreview(nsIThread* aCameraThread, uint32_t aWidth, uint32_t aHeight);
-
-  void SetFrameRate(uint32_t aFramesPerSecond);
-
-  NS_IMETHODIMP
-  GetCurrentTime(double* aCurrentTime) {
-    return nsDOMMediaStream::GetCurrentTime(aCurrentTime);
-  }
-
-  void Start();
-  void Stop();
-
-  virtual nsresult StartImpl() = 0;
-  virtual nsresult StopImpl() = 0;
-
-protected:
-  virtual ~CameraPreview();
-
-  uint32_t mWidth;
-  uint32_t mHeight;
-  uint32_t mFramesPerSecond;
-  SourceMediaStream* mInput;
-  nsRefPtr<mozilla::layers::ImageContainer> mImageContainer;
-  VideoSegment mVideoSegment;
-  uint32_t mFrameCount;
-  nsCOMPtr<nsIThread> mCameraThread;
-
-  enum { TRACK_VIDEO = 1 };
-
-private:
-  CameraPreview(const CameraPreview&) MOZ_DELETE;
-  CameraPreview& operator=(const CameraPreview&) MOZ_DELETE;
-};
-
-} // namespace mozilla
-
-#endif // DOM_CAMERA_CAMERAPREVIEW_H
rename from dom/camera/GonkCameraCapabilities.cpp
rename to dom/camera/DOMCameraCapabilities.cpp
--- a/dom/camera/GonkCameraCapabilities.cpp
+++ b/dom/camera/DOMCameraCapabilities.cpp
@@ -1,61 +1,52 @@
 /* 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 <string.h>
-#include <stdlib.h>
+#include <cstring>
+#include <cstdlib>
+#include "base/basictypes.h"
 #include "nsDOMClassInfo.h"
 #include "jsapi.h"
-#include "camera/CameraParameters.h"
-#include "CameraControl.h"
-#include "CameraCapabilities.h"
-
-#define DOM_CAMERA_LOG_LEVEL  3
+#include "DOMCameraControl.h"
+#include "DOMCameraCapabilities.h"
 #include "CameraCommon.h"
 
-using namespace android;
 using namespace mozilla;
 
 DOMCI_DATA(CameraCapabilities, nsICameraCapabilities)
 
-NS_INTERFACE_MAP_BEGIN(nsCameraCapabilities)
+NS_IMPL_CYCLE_COLLECTION_0(DOMCameraCapabilities)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMCameraCapabilities)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsICameraCapabilities)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraCapabilities)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(nsCameraCapabilities)
-NS_IMPL_RELEASE(nsCameraCapabilities)
-
-
-nsCameraCapabilities::nsCameraCapabilities(nsCameraControl* aCamera)
-  : mCamera(aCamera)
-{
-  // member initializers and constructor code
-  DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
-}
-
-nsCameraCapabilities::~nsCameraCapabilities()
-{
-  // destructor code
-  DOM_CAMERA_LOGI("%s:%d : this=%p, mCamera=%p\n", __func__, __LINE__, this, mCamera.get());
-}
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMCameraCapabilities)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMCameraCapabilities)
 
 static nsresult
 ParseZoomRatioItemAndAdd(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd)
 {
   if (!*aEnd) {
     // make 'aEnd' follow the same semantics as strchr().
     aEnd = nullptr;
   }
 
+  /**
+   * The by-100 divisor is Gonk-specific.  For now, assume other platforms
+   * return actual fractoinal multipliers.
+   */
   double d = strtod(aStart, aEnd);
+#if MOZ_WIDGET_GONK
   d /= 100;
+#endif
 
   jsval v = JS_NumberValue(d);
 
   if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
@@ -112,17 +103,17 @@ ParseDimensionItemAndAdd(JSContext* aCx,
   if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
-nsCameraCapabilities::ParameterListToNewArray(JSContext* aCx, JSObject** aArray, uint32_t aKey, ParseItemAndAddFunc aParseItemAndAdd)
+DOMCameraCapabilities::ParameterListToNewArray(JSContext* aCx, JSObject** aArray, uint32_t aKey, ParseItemAndAddFunc aParseItemAndAdd)
 {
   NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
 
   const char* value = mCamera->GetParameterConstChar(aKey);
   if (!value) {
     // in case we get nonsense data back
     *aArray = nullptr;
     return NS_OK;
@@ -134,217 +125,226 @@ nsCameraCapabilities::ParameterListToNew
   }
 
   const char* p = value;
   uint32_t index = 0;
   nsresult rv;
   char* q;
 
   while (p) {
-    q = strchr(p, ',');
+    /**
+     * In C's string.h, strchr() is declared as returning 'char*'; in C++'s
+     * cstring, it is declared as returning 'const char*', _except_ in MSVC,
+     * where the C version is declared to return const like the C++ version.
+     *
+     * Unfortunately, for both cases, strtod() and strtol() take a 'char**' as
+     * the end-of-conversion pointer, so we need to cast away strchr()'s
+     * const-ness here to make the MSVC build everything happy.
+     */
+    q = const_cast<char*>(strchr(p, ','));
     if (q != p) { // skip consecutive delimiters, just in case
       rv = aParseItemAndAdd(aCx, *aArray, index, p, &q);
       NS_ENSURE_SUCCESS(rv, rv);
       ++index;
     }
     p = q;
     if (p) {
       ++p;
     }
   }
 
   return JS_FreezeObject(aCx, *aArray) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
-nsCameraCapabilities::StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
+DOMCameraCapabilities::StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
 {
   JSObject* array;
 
   nsresult rv = ParameterListToNewArray(aCx, &array, aKey, ParseStringItemAndAdd);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aArray = OBJECT_TO_JSVAL(array);
   return NS_OK;
 }
 
 nsresult
-nsCameraCapabilities::DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
+DOMCameraCapabilities::DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey)
 {
   JSObject* array;
   nsresult rv;
 
   rv = ParameterListToNewArray(aCx, &array, aKey, ParseDimensionItemAndAdd);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aArray = OBJECT_TO_JSVAL(array);
   return NS_OK;
 }
 
 /* readonly attribute jsval previewSizes; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetPreviewSizes(JSContext* cx, JS::Value* aPreviewSizes)
+DOMCameraCapabilities::GetPreviewSizes(JSContext* cx, JS::Value* aPreviewSizes)
 {
-  return DimensionListToNewObject(cx, aPreviewSizes, nsCameraControl::CAMERA_PARAM_SUPPORTED_PREVIEWSIZES);
+  return DimensionListToNewObject(cx, aPreviewSizes, CAMERA_PARAM_SUPPORTED_PREVIEWSIZES);
 }
 
 /* readonly attribute jsval pictureSizes; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
+DOMCameraCapabilities::GetPictureSizes(JSContext* cx, JS::Value* aPictureSizes)
 {
-  return DimensionListToNewObject(cx, aPictureSizes, nsCameraControl::CAMERA_PARAM_SUPPORTED_PICTURESIZES);
+  return DimensionListToNewObject(cx, aPictureSizes, CAMERA_PARAM_SUPPORTED_PICTURESIZES);
 }
 
 /* readonly attribute jsval fileFormats; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
+DOMCameraCapabilities::GetFileFormats(JSContext* cx, JS::Value* aFileFormats)
 {
-  return StringListToNewObject(cx, aFileFormats, nsCameraControl::CAMERA_PARAM_SUPPORTED_PICTUREFORMATS);
+  return StringListToNewObject(cx, aFileFormats, CAMERA_PARAM_SUPPORTED_PICTUREFORMATS);
 }
 
 /* readonly attribute jsval whiteBalanceModes; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetWhiteBalanceModes(JSContext* cx, JS::Value* aWhiteBalanceModes)
+DOMCameraCapabilities::GetWhiteBalanceModes(JSContext* cx, JS::Value* aWhiteBalanceModes)
 {
-  return StringListToNewObject(cx, aWhiteBalanceModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_WHITEBALANCES);
+  return StringListToNewObject(cx, aWhiteBalanceModes, CAMERA_PARAM_SUPPORTED_WHITEBALANCES);
 }
 
 /* readonly attribute jsval sceneModes; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetSceneModes(JSContext* cx, JS::Value* aSceneModes)
+DOMCameraCapabilities::GetSceneModes(JSContext* cx, JS::Value* aSceneModes)
 {
-  return StringListToNewObject(cx, aSceneModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_SCENEMODES);
+  return StringListToNewObject(cx, aSceneModes, CAMERA_PARAM_SUPPORTED_SCENEMODES);
 }
 
 /* readonly attribute jsval effects; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetEffects(JSContext* cx, JS::Value* aEffects)
+DOMCameraCapabilities::GetEffects(JSContext* cx, JS::Value* aEffects)
 {
-  return StringListToNewObject(cx, aEffects, nsCameraControl::CAMERA_PARAM_SUPPORTED_EFFECTS);
+  return StringListToNewObject(cx, aEffects, CAMERA_PARAM_SUPPORTED_EFFECTS);
 }
 
 /* readonly attribute jsval flashModes; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetFlashModes(JSContext* cx, JS::Value* aFlashModes)
+DOMCameraCapabilities::GetFlashModes(JSContext* cx, JS::Value* aFlashModes)
 {
-  return StringListToNewObject(cx, aFlashModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_FLASHMODES);
+  return StringListToNewObject(cx, aFlashModes, CAMERA_PARAM_SUPPORTED_FLASHMODES);
 }
 
 /* readonly attribute jsval focusModes; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetFocusModes(JSContext* cx, JS::Value* aFocusModes)
+DOMCameraCapabilities::GetFocusModes(JSContext* cx, JS::Value* aFocusModes)
 {
-  return StringListToNewObject(cx, aFocusModes, nsCameraControl::CAMERA_PARAM_SUPPORTED_FOCUSMODES);
+  return StringListToNewObject(cx, aFocusModes, CAMERA_PARAM_SUPPORTED_FOCUSMODES);
 }
 
 /* readonly attribute long maxFocusAreas; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
+DOMCameraCapabilities::GetMaxFocusAreas(JSContext* cx, int32_t* aMaxFocusAreas)
 {
   NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
 
-  const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS);
+  const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS);
   if (!value) {
     // in case we get nonsense data back
     *aMaxFocusAreas = 0;
     return NS_OK;
   }
 
   *aMaxFocusAreas = atoi(value);
   return NS_OK;
 }
 
 /* readonly attribute double minExposureCompensation; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExposureCompensation)
+DOMCameraCapabilities::GetMinExposureCompensation(JSContext* cx, double* aMinExposureCompensation)
 {
   NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
 
-  const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION);
+  const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION);
   if (!value) {
     // in case we get nonsense data back
     *aMinExposureCompensation = 0;
     return NS_OK;
   }
 
   *aMinExposureCompensation = atof(value);
   return NS_OK;
 }
 
 /* readonly attribute double maxExposureCompensation; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExposureCompensation)
+DOMCameraCapabilities::GetMaxExposureCompensation(JSContext* cx, double* aMaxExposureCompensation)
 {
   NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
 
-  const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION);
+  const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION);
   if (!value) {
     // in case we get nonsense data back
     *aMaxExposureCompensation = 0;
     return NS_OK;
   }
 
   *aMaxExposureCompensation = atof(value);
   return NS_OK;
 }
 
 /* readonly attribute double stepExposureCompensation; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepExposureCompensation)
+DOMCameraCapabilities::GetStepExposureCompensation(JSContext* cx, double* aStepExposureCompensation)
 {
   NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
 
-  const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP);
+  const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP);
   if (!value) {
     // in case we get nonsense data back
     *aStepExposureCompensation = 0;
     return NS_OK;
   }
 
   *aStepExposureCompensation = atof(value);
   return NS_OK;
 }
 
 /* readonly attribute long maxMeteringAreas; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAreas)
+DOMCameraCapabilities::GetMaxMeteringAreas(JSContext* cx, int32_t* aMaxMeteringAreas)
 {
   NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
 
-  const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS);
+  const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS);
   if (!value) {
     // in case we get nonsense data back
     *aMaxMeteringAreas = 0;
     return NS_OK;
   }
 
   *aMaxMeteringAreas = atoi(value);
   return NS_OK;
 }
 
 /* readonly attribute jsval zoomRatios; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
+DOMCameraCapabilities::GetZoomRatios(JSContext* cx, JS::Value* aZoomRatios)
 {
   NS_ENSURE_TRUE(mCamera, NS_ERROR_NOT_AVAILABLE);
 
-  const char* value = mCamera->GetParameterConstChar(nsCameraControl::CAMERA_PARAM_SUPPORTED_ZOOM);
-  if (!value || strcmp(value, CameraParameters::TRUE) != 0) {
+  const char* value = mCamera->GetParameterConstChar(CAMERA_PARAM_SUPPORTED_ZOOM);
+  if (!value || strcmp(value, "true") != 0) {
     // if zoom is not supported, return a null object
     *aZoomRatios = JSVAL_NULL;
     return NS_OK;
   }
 
   JSObject* array;
 
-  nsresult rv = ParameterListToNewArray(cx, &array, nsCameraControl::CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, ParseZoomRatioItemAndAdd);
+  nsresult rv = ParameterListToNewArray(cx, &array, CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, ParseZoomRatioItemAndAdd);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aZoomRatios = OBJECT_TO_JSVAL(array);
   return NS_OK;
 }
 
 /* readonly attribute jsval videoSizes; */
 NS_IMETHODIMP
-nsCameraCapabilities::GetVideoSizes(JSContext* cx, JS::Value* aVideoSizes)
+DOMCameraCapabilities::GetVideoSizes(JSContext* cx, JS::Value* aVideoSizes)
 {
-  return DimensionListToNewObject(cx, aVideoSizes, nsCameraControl::CAMERA_PARAM_SUPPORTED_VIDEOSIZES);
+  return DimensionListToNewObject(cx, aVideoSizes, CAMERA_PARAM_SUPPORTED_VIDEOSIZES);
 }
new file mode 100644
--- /dev/null
+++ b/dom/camera/DOMCameraCapabilities.h
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DOM_CAMERA_DOMCAMERACAPABILITIES_H
+#define DOM_CAMERA_DOMCAMERACAPABILITIES_H
+
+#include "nsCycleCollectionParticipant.h"
+#include "ICameraControl.h"
+#include "nsAutoPtr.h"
+#include "CameraCommon.h"
+
+namespace mozilla {
+
+typedef nsresult (*ParseItemAndAddFunc)(JSContext* aCx, JSObject* aArray, uint32_t aIndex, const char* aStart, char** aEnd);
+
+class DOMCameraCapabilities MOZ_FINAL : public nsICameraCapabilities
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(DOMCameraCapabilities)
+  NS_DECL_NSICAMERACAPABILITIES
+
+  DOMCameraCapabilities(ICameraControl* aCamera)
+    : mCamera(aCamera)
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  nsresult ParameterListToNewArray(
+    JSContext* cx,
+    JSObject** aArray,
+    uint32_t aKey,
+    ParseItemAndAddFunc aParseItemAndAdd
+  );
+  nsresult StringListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
+  nsresult DimensionListToNewObject(JSContext* aCx, JS::Value* aArray, uint32_t aKey);
+
+private:
+  DOMCameraCapabilities(const DOMCameraCapabilities&) MOZ_DELETE;
+  DOMCameraCapabilities& operator=(const DOMCameraCapabilities&) MOZ_DELETE;
+
+protected:
+  /* additional members */
+  ~DOMCameraCapabilities()
+  {
+    // destructor code
+    DOM_CAMERA_LOGT("%s:%d : this=%p, mCamera=%p\n", __func__, __LINE__, this, mCamera.get());
+  }
+
+  nsRefPtr<ICameraControl> mCamera;
+};
+
+} // namespace mozilla
+
+#endif // DOM_CAMERA_DOMCAMERACAPABILITIES_H
new file mode 100644
--- /dev/null
+++ b/dom/camera/DOMCameraControl.cpp
@@ -0,0 +1,370 @@
+/* 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 "base/basictypes.h"
+#include "nsCOMPtr.h"
+#include "nsDOMClassInfo.h"
+#include "jsapi.h"
+#include "nsThread.h"
+#include "mozilla/Services.h"
+#include "nsIObserverService.h"
+#include "DOMCameraManager.h"
+#include "DOMCameraCapabilities.h"
+#include "DOMCameraControl.h"
+#include "CameraCommon.h"
+
+using namespace mozilla;
+using namespace dom;
+
+DOMCI_DATA(CameraControl, nsICameraControl)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMCameraControl)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMCameraControl)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMCapabilities)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMCameraControl)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMCapabilities)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraControl)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY(nsICameraControl)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraControl)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCameraControl)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCameraControl)
+
+nsDOMCameraControl::~nsDOMCameraControl()
+{
+  DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+}
+
+/* readonly attribute nsICameraCapabilities capabilities; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetCapabilities(nsICameraCapabilities** aCapabilities)
+{
+  if (!mDOMCapabilities) {
+    mDOMCapabilities = new DOMCameraCapabilities(mCameraControl);
+  }
+
+  nsCOMPtr<nsICameraCapabilities> capabilities = mDOMCapabilities;
+  capabilities.forget(aCapabilities);
+  return NS_OK;
+}
+
+/* attribute DOMString effect; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetEffect(nsAString& aEffect)
+{
+  return mCameraControl->Get(CAMERA_PARAM_EFFECT, aEffect);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetEffect(const nsAString& aEffect)
+{
+  return mCameraControl->Set(CAMERA_PARAM_EFFECT, aEffect);
+}
+
+/* attribute DOMString whiteBalanceMode; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetWhiteBalanceMode(nsAString& aWhiteBalanceMode)
+{
+  return mCameraControl->Get(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetWhiteBalanceMode(const nsAString& aWhiteBalanceMode)
+{
+  return mCameraControl->Set(CAMERA_PARAM_WHITEBALANCE, aWhiteBalanceMode);
+}
+
+/* attribute DOMString sceneMode; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetSceneMode(nsAString& aSceneMode)
+{
+  return mCameraControl->Get(CAMERA_PARAM_SCENEMODE, aSceneMode);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetSceneMode(const nsAString& aSceneMode)
+{
+  return mCameraControl->Set(CAMERA_PARAM_SCENEMODE, aSceneMode);
+}
+
+/* attribute DOMString flashMode; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetFlashMode(nsAString& aFlashMode)
+{
+  return mCameraControl->Get(CAMERA_PARAM_FLASHMODE, aFlashMode);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetFlashMode(const nsAString& aFlashMode)
+{
+  return mCameraControl->Set(CAMERA_PARAM_FLASHMODE, aFlashMode);
+}
+
+/* attribute DOMString focusMode; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetFocusMode(nsAString& aFocusMode)
+{
+  return mCameraControl->Get(CAMERA_PARAM_FOCUSMODE, aFocusMode);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetFocusMode(const nsAString& aFocusMode)
+{
+  return mCameraControl->Set(CAMERA_PARAM_FOCUSMODE, aFocusMode);
+}
+
+/* attribute double zoom; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetZoom(double* aZoom)
+{
+  return mCameraControl->Get(CAMERA_PARAM_ZOOM, aZoom);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetZoom(double aZoom)
+{
+  return mCameraControl->Set(CAMERA_PARAM_ZOOM, aZoom);
+}
+
+/* attribute jsval meteringAreas; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetMeteringAreas(JSContext* cx, JS::Value* aMeteringAreas)
+{
+  return mCameraControl->Get(cx, CAMERA_PARAM_METERINGAREAS, aMeteringAreas);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetMeteringAreas(JSContext* cx, const JS::Value& aMeteringAreas)
+{
+  return mCameraControl->SetMeteringAreas(cx, aMeteringAreas);
+}
+
+/* attribute jsval focusAreas; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetFocusAreas(JSContext* cx, JS::Value* aFocusAreas)
+{
+  return mCameraControl->Get(cx, CAMERA_PARAM_FOCUSAREAS, aFocusAreas);
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetFocusAreas(JSContext* cx, const JS::Value& aFocusAreas)
+{
+  return mCameraControl->SetFocusAreas(cx, aFocusAreas);
+}
+
+/* readonly attribute double focalLength; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetFocalLength(double* aFocalLength)
+{
+  return mCameraControl->Get(CAMERA_PARAM_FOCALLENGTH, aFocalLength);
+}
+
+/* readonly attribute double focusDistanceNear; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetFocusDistanceNear(double* aFocusDistanceNear)
+{
+  return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCENEAR, aFocusDistanceNear);
+}
+
+/* readonly attribute double focusDistanceOptimum; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetFocusDistanceOptimum(double* aFocusDistanceOptimum)
+{
+  return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEOPTIMUM, aFocusDistanceOptimum);
+}
+
+/* readonly attribute double focusDistanceFar; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetFocusDistanceFar(double* aFocusDistanceFar)
+{
+  return mCameraControl->Get(CAMERA_PARAM_FOCUSDISTANCEFAR, aFocusDistanceFar);
+}
+
+/* void setExposureCompensation (const JS::Value& aCompensation, JSContext* cx); */
+NS_IMETHODIMP
+nsDOMCameraControl::SetExposureCompensation(const JS::Value& aCompensation, JSContext* cx)
+{
+  if (aCompensation.isNullOrUndefined()) {
+    // use NaN to switch the camera back into auto mode
+    return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, NAN);
+  }
+
+  double compensation;
+  if (!JS_ValueToNumber(cx, aCompensation, &compensation)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  return mCameraControl->Set(CAMERA_PARAM_EXPOSURECOMPENSATION, compensation);
+}
+
+/* readonly attribute double exposureCompensation; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetExposureCompensation(double* aExposureCompensation)
+{
+  return mCameraControl->Get(CAMERA_PARAM_EXPOSURECOMPENSATION, aExposureCompensation);
+}
+
+/* attribute nsICameraShutterCallback onShutter; */
+NS_IMETHODIMP
+nsDOMCameraControl::GetOnShutter(nsICameraShutterCallback** aOnShutter)
+{
+  // TODO: see bug 779138.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP
+nsDOMCameraControl::SetOnShutter(nsICameraShutterCallback* aOnShutter)
+{
+  // TODO: see bug 779138.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void startRecording (in jsval aOptions, in nsICameraStartRecordingCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
+NS_IMETHODIMP
+nsDOMCameraControl::StartRecording(const JS::Value& aOptions, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
+{
+  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
+
+  CameraSize size;
+  nsresult rv = size.Init(cx, &aOptions);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (!obs) {
+    NS_WARNING("Could not get the Observer service for CameraControl::StartRecording.");
+    return NS_ERROR_FAILURE;
+  }
+
+  obs->NotifyObservers(nullptr,
+                       "recording-device-events",
+                       NS_LITERAL_STRING("starting").get());
+
+  return mCameraControl->StartRecording(size, onSuccess, onError);
+}
+
+/* void stopRecording (); */
+NS_IMETHODIMP
+nsDOMCameraControl::StopRecording()
+{
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (!obs) {
+    NS_WARNING("Could not get the Observer service for CameraControl::StopRecording.");
+    return NS_ERROR_FAILURE;
+  }
+
+  obs->NotifyObservers(nullptr,
+                       "recording-device-events",
+                       NS_LITERAL_STRING("shutdown").get());
+
+  return mCameraControl->StopRecording();
+}
+
+/* [implicit_jscontext] void getPreviewStream (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
+NS_IMETHODIMP
+nsDOMCameraControl::GetPreviewStream(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
+{
+  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
+
+  CameraSize size;
+  nsresult rv = size.Init(cx, &aOptions);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return mCameraControl->GetPreviewStream(size, onSuccess, onError);
+}
+
+/* void resumePreview(); */
+NS_IMETHODIMP
+nsDOMCameraControl::ResumePreview()
+{
+  return mCameraControl->StartPreview(nullptr);
+}
+
+/* void autoFocus (in nsICameraAutoFocusCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
+NS_IMETHODIMP
+nsDOMCameraControl::AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError)
+{
+  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
+  return mCameraControl->AutoFocus(onSuccess, onError);
+}
+
+/* void takePicture (in jsval aOptions, in nsICameraTakePictureCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
+NS_IMETHODIMP
+nsDOMCameraControl::TakePicture(const JS::Value& aOptions, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
+{
+  NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
+
+  CameraPictureOptions  options;
+  CameraSize            size;
+  CameraPosition        pos;
+
+  nsresult rv = options.Init(cx, &aOptions);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = size.Init(cx, &options.pictureSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  /**
+   * Default values, until the dictionary parser can handle them.
+   * NaN indicates no value provided.
+   */
+  pos.latitude = NAN;
+  pos.longitude = NAN;
+  pos.altitude = NAN;
+  pos.timestamp = NAN;
+  rv = pos.Init(cx, &options.position);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return mCameraControl->TakePicture(size, options.rotation, options.fileFormat, pos, onSuccess, onError);
+}
+
+class GetCameraResult : public nsRunnable
+{
+public:
+  GetCameraResult(nsDOMCameraControl* aDOMCameraControl, nsresult aResult, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
+    : mDOMCameraControl(aDOMCameraControl)
+    , mResult(aResult)
+    , mOnSuccessCb(onSuccess)
+    , mOnErrorCb(onError)
+  { }
+
+  NS_IMETHOD Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    DOM_CAMERA_LOGT("%s : this=%p -- BEFORE CALLBACK\n", __func__, this);
+    if (NS_FAILED(mResult)) {
+      if (mOnErrorCb) {
+        mOnErrorCb->HandleEvent(NS_LITERAL_STRING("FAILURE"));
+      }
+    } else {
+      if (mOnSuccessCb) {
+        mOnSuccessCb->HandleEvent(mDOMCameraControl);
+      }
+    }
+    DOM_CAMERA_LOGT("%s : this=%p -- AFTER CALLBACK\n", __func__, this);
+
+    /**
+     * Finally, release the extra reference to the DOM-facing camera control.
+     * See the nsDOMCameraControl constructor for the corresponding call to
+     * NS_ADDREF_THIS().
+     */
+    NS_RELEASE(mDOMCameraControl);
+    return NS_OK;
+  }
+
+protected:
+  /**
+   * 'mDOMCameraControl' is a raw pointer to a previously ADDREF()ed object,
+   * which is released in Run().
+   */
+  nsDOMCameraControl* mDOMCameraControl;
+  nsresult mResult;
+  nsCOMPtr<nsICameraGetCameraCallback> mOnSuccessCb;
+  nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
+};
+
+nsresult
+nsDOMCameraControl::Result(nsresult aResult, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError)
+{
+  nsCOMPtr<GetCameraResult> getCameraResult = new GetCameraResult(this, aResult, onSuccess, onError);
+  return NS_DispatchToMainThread(getCameraResult);
+}
new file mode 100644
--- /dev/null
+++ b/dom/camera/DOMCameraControl.h
@@ -0,0 +1,50 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DOM_CAMERA_DOMCAMERACONTROL_H
+#define DOM_CAMERA_DOMCAMERACONTROL_H
+
+#include "base/basictypes.h"
+#include "prtypes.h"
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+#include "nsCycleCollectionParticipant.h"
+#include "DictionaryHelpers.h"
+#include "ICameraControl.h"
+#include "DOMCameraPreview.h"
+#include "nsIDOMCameraManager.h"
+#include "CameraCommon.h"
+
+namespace mozilla {
+
+using namespace mozilla;
+using namespace dom;
+
+// Main camera control.
+class nsDOMCameraControl : public nsICameraControl
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMCameraControl)
+  NS_DECL_NSICAMERACONTROL
+
+  nsDOMCameraControl(uint32_t aCameraId, nsIThread* aCameraThread, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError);
+  nsresult Result(nsresult aResult, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError);
+
+protected:
+  virtual ~nsDOMCameraControl();
+
+private:
+  nsDOMCameraControl(const nsDOMCameraControl&) MOZ_DELETE;
+  nsDOMCameraControl& operator=(const nsDOMCameraControl&) MOZ_DELETE;
+
+protected:
+  /* additional members */
+  nsRefPtr<ICameraControl>        mCameraControl; // non-DOM camera control
+  nsCOMPtr<nsICameraCapabilities> mDOMCapabilities;
+};
+
+} // namespace mozilla
+
+#endif // DOM_CAMERA_DOMCAMERACONTROL_H
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -1,65 +1,77 @@
 /* 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 "CameraControl.h"
+#include "DOMCameraControl.h"
 #include "DOMCameraManager.h"
 #include "nsDOMClassInfo.h"
 #include "DictionaryHelpers.h"
-
-#undef DOM_CAMERA_LOG_LEVEL
-#define DOM_CAMERA_LOG_LEVEL  DOM_CAMERA_LOG_NOTHING
 #include "CameraCommon.h"
 
 using namespace mozilla;
 
 DOMCI_DATA(CameraManager, nsIDOMCameraManager)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMCameraManager)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCameraManager)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CameraManager)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsDOMCameraManager)
 NS_IMPL_RELEASE(nsDOMCameraManager)
 
 /**
+ * Global camera logging object
+ *
+ * Set the NSPR_LOG_MODULES environment variable to enable logging
+ * in a debug build, e.g. NSPR_LOG_MODULES=Camera:5
+ */
+#ifdef PR_LOGGING
+PRLogModuleInfo* gCameraLog;
+#endif
+
+/**
  * nsDOMCameraManager::GetListOfCameras
  * is implementation-specific, and can be found in (e.g.)
  * GonkCameraManager.cpp and FallbackCameraManager.cpp.
  */
 
 nsDOMCameraManager::nsDOMCameraManager(uint64_t aWindowId)
   : mWindowId(aWindowId)
 {
   /* member initializers and constructor code */
-  DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+  DOM_CAMERA_LOGT("%s:%d : this=%p, windowId=%llx\n", __func__, __LINE__, this, mWindowId);
 }
 
 nsDOMCameraManager::~nsDOMCameraManager()
 {
   /* destructor code */
-  DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+  DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
 }
 
 void
 nsDOMCameraManager::OnNavigation(uint64_t aWindowId)
 {
-  // TODO: implement -- see getUserMedia() implementation
+  // TODO: see bug 779145.
 }
 
 // static creator
 already_AddRefed<nsDOMCameraManager>
 nsDOMCameraManager::Create(uint64_t aWindowId)
 {
-  // TODO: check for permissions here to access cameras
+  // TODO: see bug 776934.
 
+#ifdef PR_LOGGING
+  if (!gCameraLog) {
+    gCameraLog = PR_LOG_DEFINE("Camera");
+  }
+#endif
   nsRefPtr<nsDOMCameraManager> cameraManager = new nsDOMCameraManager(aWindowId);
   return cameraManager.forget();
 }
 
 /* [implicit_jscontext] void getCamera ([optional] in jsval aOptions, in nsICameraGetCameraCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
 NS_IMETHODIMP
 nsDOMCameraManager::GetCamera(const JS::Value& aOptions, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
 {
@@ -76,15 +88,15 @@ nsDOMCameraManager::GetCamera(const JS::
   }
 
   // reuse the same camera thread to conserve resources
   if (!mCameraThread) {
     rv = NS_NewThread(getter_AddRefs(mCameraThread));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  DOM_CAMERA_LOGI("%s:%d\n", __func__, __LINE__);
+  DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
-  nsCOMPtr<nsIRunnable> getCameraTask = new GetCameraTask(cameraId, onSuccess, onError, mCameraThread);
-  mCameraThread->Dispatch(getCameraTask, NS_DISPATCH_NORMAL);
+  // Creating this object will trigger the onSuccess handler
+  nsCOMPtr<nsICameraControl> cameraControl = new nsDOMCameraControl(cameraId, mCameraThread, onSuccess, onError);
 
   return NS_OK;
 }
--- a/dom/camera/DOMCameraManager.h
+++ b/dom/camera/DOMCameraManager.h
@@ -31,17 +31,16 @@ private:
   nsDOMCameraManager& operator=(const nsDOMCameraManager&) MOZ_DELETE;
   ~nsDOMCameraManager();
 
 protected:
   uint64_t mWindowId;
   nsCOMPtr<nsIThread> mCameraThread;
 };
 
-
 class GetCameraTask : public nsRunnable
 {
 public:
   GetCameraTask(uint32_t aCameraId, nsICameraGetCameraCallback* onSuccess, nsICameraErrorCallback* onError, nsIThread* aCameraThread)
     : mCameraId(aCameraId)
     , mOnSuccessCb(onSuccess)
     , mOnErrorCb(onError)
     , mCameraThread(aCameraThread)
@@ -51,33 +50,9 @@ public:
 
 protected:
   uint32_t mCameraId;
   nsCOMPtr<nsICameraGetCameraCallback> mOnSuccessCb;
   nsCOMPtr<nsICameraErrorCallback> mOnErrorCb;
   nsCOMPtr<nsIThread> mCameraThread;
 };
 
-class GetCameraResult : public nsRunnable
-{
-public:
-  GetCameraResult(nsICameraControl* aCameraControl, nsICameraGetCameraCallback* onSuccess)
-    : mCameraControl(aCameraControl)
-    , mOnSuccessCb(onSuccess)
-  { }
-
-  NS_IMETHOD Run()
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    // TODO: window management stuff
-    if (mOnSuccessCb) {
-      mOnSuccessCb->HandleEvent(mCameraControl);
-    }
-    return NS_OK;
-  }
-
-protected:
-  nsCOMPtr<nsICameraControl> mCameraControl;
-  nsCOMPtr<nsICameraGetCameraCallback> mOnSuccessCb;
-};
-
 #endif // DOM_CAMERA_DOMCAMERAMANAGER_H
new file mode 100644
--- /dev/null
+++ b/dom/camera/DOMCameraPreview.cpp
@@ -0,0 +1,289 @@
+/* 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 "base/basictypes.h"
+#include "Layers.h"
+#include "VideoUtils.h"
+#include "DOMCameraPreview.h"
+#include "CameraCommon.h"
+
+using namespace mozilla;
+
+/**
+ * 'PreviewControl' is a helper class that dispatches preview control
+ * events from the main thread.
+ *
+ * NS_NewRunnableMethod() can't be used because it AddRef()s the method's
+ * object, which can't be done off the main thread for cycle collection
+ * participants.
+ *
+ * Before using this class, 'aDOMPreview' must be appropriately AddRef()ed.
+ */
+class PreviewControl : public nsRunnable
+{
+public:
+  enum {
+    START,
+    STOP,
+    STARTED,
+    STOPPED
+  };
+  PreviewControl(DOMCameraPreview* aDOMPreview, uint32_t aControl)
+    : mDOMPreview(aDOMPreview)
+    , mControl(aControl)
+  { }
+
+  NS_IMETHOD Run()
+  {
+    NS_ASSERTION(NS_IsMainThread(), "PreviewControl not run on main thread");
+
+    switch (mControl) {
+      case START:
+        mDOMPreview->Start();
+        break;
+
+      case STOP:
+        mDOMPreview->Stop();
+        break;
+
+      case STARTED:
+        mDOMPreview->SetStateStarted();
+        break;
+
+      case STOPPED:
+        mDOMPreview->SetStateStopped();
+        break;
+
+      default:
+        DOM_CAMERA_LOGE("PreviewControl: invalid control %d\n", mControl);
+        break;
+    }
+
+    return NS_OK;
+  }
+
+protected:
+  /**
+   * This must be a raw pointer because this class is not created on the
+   * main thread, and DOMCameraPreview is not threadsafe.  Prior to
+   * issuing a preview control event, the caller must ensure that
+   * mDOMPreview will not disappear.
+   */
+  DOMCameraPreview* mDOMPreview;
+  uint32_t mControl;
+};
+
+class DOMCameraPreviewListener : public MediaStreamListener
+{
+public:
+  DOMCameraPreviewListener(DOMCameraPreview* aDOMPreview) :
+    mDOMPreview(aDOMPreview)
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  ~DOMCameraPreviewListener()
+  {
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+  }
+
+  void NotifyConsumptionChanged(MediaStreamGraph* aGraph, Consumption aConsuming)
+  {
+    const char* state;
+
+    DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+
+    switch (aConsuming) {
+      case NOT_CONSUMED:
+        state = "not consuming";
+        break;
+
+      case CONSUMED:
+        state = "consuming";
+        break;
+
+      default:
+        state = "unknown";
+        break;
+    }
+
+    DOM_CAMERA_LOGA("camera viewfinder is %s\n", state);
+    nsCOMPtr<nsIRunnable> previewControl;
+
+    switch (aConsuming) {
+      case NOT_CONSUMED:
+        previewControl = new PreviewControl(mDOMPreview, PreviewControl::STOP);
+        break;
+
+      case CONSUMED:
+        previewControl = new PreviewControl(mDOMPreview, PreviewControl::START);
+        break;
+
+      default:
+        return;
+    }
+
+    nsresult rv = NS_DispatchToMainThread(previewControl);
+    if (NS_FAILED(rv)) {
+      DOM_CAMERA_LOGE("Failed to dispatch preview control (%d)!\n", rv);
+    }
+  }