Merge IonMonkey to mozilla-central. a=arewefastyet
authorDavid Anderson <danderson@mozilla.com>
Tue, 11 Sep 2012 10:25:14 -0700
changeset 113658 ca3fa3fbe62ad72fa7db075d9d93843c959d6725
parent 113657 01f6ddbb6542cccbe61029ff16a2918aaa81462f (current diff)
parent 111650 d042ad078f436e284610366dc39cebdcb6fa8658 (diff)
child 113659 fdfaef738a00c5808782864cd991494d53eaf680
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarewefastyet
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge IonMonkey to mozilla-central. a=arewefastyet
b2g/app/nsBrowserApp.cpp
browser/base/content/tabbrowser.xml
browser/components/nsBrowserGlue.js
browser/themes/winstripe/browser.css
caps/src/nsSecurityManagerFactory.cpp
configure.in
content/base/public/nsContentUtils.h
content/base/public/nsIWebSocket.idl
content/base/src/Makefile.in
content/base/src/WebSocket.cpp
content/base/src/WebSocket.h
content/base/src/nsContentUtils.cpp
content/base/src/nsINode.cpp
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsWebSocket.cpp
content/base/src/nsWebSocket.h
content/base/test/Makefile.in
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/ipc/ContentChild.cpp
dom/ipc/CrashReporterParent.cpp
dom/ipc/CrashReporterParent.h
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/ipc/PluginModuleParent.cpp
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicLayers.h
gfx/thebes/gfxWindowsPlatform.cpp
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/gc/Root.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsgc.cpp
js/src/jsinfer.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/shell/js.cpp
js/xpconnect/src/XPCWrapper.cpp
js/xpconnect/src/dom_quickstubs.qsconf
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/AccessCheck.cpp
js/xpconnect/wrappers/AccessCheck.h
js/xpconnect/wrappers/FilteringWrapper.cpp
js/xpconnect/wrappers/WrapperFactory.cpp
js/xpconnect/wrappers/WrapperFactory.h
js/xpconnect/wrappers/XrayWrapper.cpp
layout/base/crashtests/crashtests.list
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/build/nsLayoutModule.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
mobile/android/chrome/content/browser.js
netwerk/cache/nsDiskCacheMap.cpp
testing/mochitest/specialpowers/content/specialpowers.js
toolkit/components/aboutmemory/content/aboutMemory.js
toolkit/crashreporter/CrashSubmit.jsm
toolkit/crashreporter/Makefile.in
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
toolkit/crashreporter/test/unit/head_crashreporter.js
toolkit/mozapps/extensions/nsBlocklistService.js
toolkit/mozapps/installer/packager.mk
toolkit/xre/nsAppRunner.cpp
xpcom/base/nsMemoryReporterManager.cpp
xpcom/base/nsStackWalk.cpp
xpcom/base/nsTraceRefcntImpl.cpp
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -159,17 +159,17 @@ int main(int argc, char* argv[])
 
   nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't calculate the application directory.\n");
     return 255;
   }
 
   char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
-  if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
+  if (!lastSlash || ((lastSlash - exePath) + sizeof(XPCOM_DLL) + 1 > MAXPATHLEN))
     return 255;
 
   strcpy(++lastSlash, XPCOM_DLL);
 
   int gotCounters;
 #if defined(XP_UNIX)
   struct rusage initialRUsage;
   gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3642,28 +3642,28 @@
               this._dragTime = Date.now();
             if (Date.now() >= this._dragTime + this._dragOverDelay)
               this.selectedItem = tab;
             ind.collapsed = true;
             return;
           }
         }
 
-        var scrollRect = tabStrip.scrollClientRect;
         var rect = tabStrip.getBoundingClientRect();
-        var minMargin = scrollRect.left - rect.left;
-        var maxMargin = Math.min(minMargin + scrollRect.width,
-                                 scrollRect.right);
-        if (!ltr)
-          [minMargin, maxMargin] = [this.clientWidth - maxMargin,
-                                    this.clientWidth - minMargin];
         var newMargin;
         if (pixelsToScroll) {
           // if we are scrolling, put the drop indicator at the edge
           // so that it doesn't jump while scrolling
+          let scrollRect = tabStrip.scrollClientRect;
+          let minMargin = scrollRect.left - rect.left;
+          let maxMargin = Math.min(minMargin + scrollRect.width,
+                                   scrollRect.right);
+          if (!ltr)
+            [minMargin, maxMargin] = [this.clientWidth - maxMargin,
+                                      this.clientWidth - minMargin];
           newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
         }
         else {
           let newIndex = this._getDropIndex(event);
           if (newIndex == this.childNodes.length) {
             let tabRect = this.childNodes[newIndex-1].getBoundingClientRect();
             if (ltr)
               newMargin = tabRect.right - rect.left;
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1633,21 +1633,25 @@ ContentPermissionPrompt.prototype = {
         .rootTreeItem
         .QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIDOMWindow)
         .QueryInterface(Ci.nsIDOMChromeWindow);
       return chromeWin;
     }
 
     var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
+    let secHistogram = Components.classes["@mozilla.org/base/telemetry;1"].
+                                  getService(Ci.nsITelemetry).
+                                  getHistogramById("SECURITY_UI");
 
     var mainAction = {
       label: browserBundle.GetStringFromName("geolocation.shareLocation"),
       accessKey: browserBundle.GetStringFromName("geolocation.shareLocation.accesskey"),
       callback: function() {
+        secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_SHARE_LOCATION);
         request.allow();
       },
     };
 
     var message;
     var secondaryActions = [];
     var requestingWindow = request.window.top;
     var chromeWin = getChromeWindow(requestingWindow).wrappedJSObject;
@@ -1662,31 +1666,34 @@ ContentPermissionPrompt.prototype = {
 
       // Don't offer to "always/never share" in PB mode
       if (("gPrivateBrowsingUI" in chromeWin) && !chromeWin.gPrivateBrowsingUI.privateWindow) {
         secondaryActions.push({
           label: browserBundle.GetStringFromName("geolocation.alwaysShareLocation"),
           accessKey: browserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
           callback: function () {
             Services.perms.addFromPrincipal(requestingPrincipal, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
+            secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_ALWAYS_SHARE);
             request.allow();
           }
         });
         secondaryActions.push({
           label: browserBundle.GetStringFromName("geolocation.neverShareLocation"),
           accessKey: browserBundle.GetStringFromName("geolocation.neverShareLocation.accesskey"),
           callback: function () {
             Services.perms.addFromPrincipal(requestingPrincipal, "geo", Ci.nsIPermissionManager.DENY_ACTION);
+            secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_NEVER_SHARE);
             request.cancel();
           }
         });
       }
     }
 
     var browser = chromeWin.gBrowser.getBrowserForDocument(requestingWindow.document);
 
+    secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST);
     chromeWin.PopupNotifications.show(browser, "geolocation", message, "geo-notification-icon",
                                       mainAction, secondaryActions);
   }
 };
 
 var components = [BrowserGlue, ContentPermissionPrompt];
 var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1582,17 +1582,17 @@ richlistitem[type~="action"][actiontype=
 .tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) {
   background-image: -moz-radial-gradient(center 3px, circle cover, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
 }
 .tabbrowser-tab[pinned][titlechanged]:not([selected="true"]):hover {
   background-image: -moz-linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.6) 2px, hsla(0,0%,75%,.2) 80%),
                     -moz-radial-gradient(center 3px, circle cover, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
 }
 
-#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
+#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab > .tab-stack > .tab-content[pinned] {
   min-height: 18px; /* corresponds to the max. height of non-textual tab contents, i.e. the tab close button */
 }
 
 .tabbrowser-tab:focus > .tab-stack {
   outline: 1px dotted;
 }
 
 .tab-throbber,
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -1918,20 +1918,16 @@ richlistitem[type~="action"][actiontype=
 .tab-throbber {
   list-style-image: url("chrome://browser/skin/tabbrowser/connecting.png");
 }
 
 .tab-throbber[progress] {
   list-style-image: url("chrome://browser/skin/tabbrowser/loading.png");
 }
 
-#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
-  min-height: 16px; /* corresponds to the max. height of non-textual tab contents, i.e. the favicon */
-}
-
 .tab-throbber[pinned],
 .tab-icon-image[pinned] {
   -moz-margin-start: 5px;
   -moz-margin-end: 5px;
 }
 
 /* tabbrowser-tab focus ring */
 .tabbrowser-tab:focus > .tab-stack {
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -40,18 +40,17 @@ nsSecurityNameSet::~nsSecurityNameSet()
 {
 }
 
 NS_IMPL_ISUPPORTS1(nsSecurityNameSet, nsIScriptExternalNameSet)
 
 static JSBool
 netscape_security_enablePrivilege(JSContext *cx, unsigned argc, jsval *vp)
 {
-    xpc::EnableUniversalXPConnect(cx);
-    return JS_TRUE;
+    return xpc::EnableUniversalXPConnect(cx);
 }
 
 static JSFunctionSpec PrivilegeManager_static_methods[] = {
     JS_FS("enablePrivilege", netscape_security_enablePrivilege, 1, 0),
     JS_FS_END
 };
 
 /*
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -22,18 +22,16 @@ STDCXX_COMPAT =
 ifneq (WINNT,$(HOST_OS_ARCH))
 HOST_PROGRAM	= nsinstall_real$(HOST_BIN_SUFFIX)
 HOST_CSRCS	= nsinstall.c pathsub.c
 endif
 
 ifndef CROSS_COMPILE
 ifdef USE_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
 override NSBUILDROOT :=
 endif
@@ -136,18 +134,18 @@ endif
 install::
 	$(SYSINSTALL) $(IFLAGS1) $(DEPTH)/mozilla-config.h $(DESTDIR)$(includedir)
 
 GARBAGE += \
   $(FINAL_LINK_COMPS) $(FINAL_LINK_LIBS) $(FINAL_LINK_COMP_NAMES) buildid $(srcdir)/*.pyc *.pyc
 
 ifndef CROSS_COMPILE
 ifdef USE_ELF_DYNSTR_GC
-elf-dynstr-gc: elf-dynstr-gc.c $(GLOBAL_DEPS)
-	$(CC) $(COMPILE_CFLAGS) $(GLIB_CFLAGS) -o $@ $< $(LDFLAGS) $(GLIB_LIBS) 
+elf-dynstr-gc: elf-dynstr-gc.c $(GLOBAL_DEPS) $(call mkdir_deps,$(MDDEPDIR))
+	$(CC) $(COMPILE_CFLAGS) $(GLIB_CFLAGS) -o $@ $< $(LDFLAGS) $(GLIB_LIBS)
 endif
 endif
 
 FORCE:
 
 PYUNITS := \
   unit-Expression.py \
   unit-Preprocessor.py \
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -375,23 +375,17 @@ endif
 ifndef PROGOBJS
 PROGOBJS		= $(OBJS)
 endif
 
 ifndef HOST_PROGOBJS
 HOST_PROGOBJS		= $(HOST_OBJS)
 endif
 
-# MAKE_DIRS: List of directories to build while looping over directories.
-# A Makefile that needs $(MDDEPDIR) created but doesn't set any of these
-# variables we know to check can just set NEED_MDDEPDIR explicitly.
-ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)$(NEED_MDDEPDIR))
-MAKE_DIRS       += $(CURDIR)/$(MDDEPDIR)
-GARBAGE_DIRS    += $(CURDIR)/$(MDDEPDIR)
-endif
+GARBAGE_DIRS    += $(wildcard $(CURDIR)/$(MDDEPDIR))
 
 #
 # Tags: emacs (etags), vi (ctags)
 # TAG_PROGRAM := ctags -L -
 #
 TAG_PROGRAM		= xargs etags -a
 
 #
@@ -947,17 +941,17 @@ endif # Sun Studio on Solaris
 $(HOST_CMOBJS): host_%.$(OBJ_SUFFIX): %.m
 	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 $(HOST_CMMOBJS): host_%.$(OBJ_SUFFIX): %.mm
 	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
-$(COBJS): %.$(OBJ_SUFFIX): %.c
+$(COBJS): %.$(OBJ_SUFFIX): %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h
@@ -977,55 +971,55 @@ ifdef ASFILES
 endif
 
 $(SOBJS): %.$(OBJ_SUFFIX): %.S
 	$(AS) -o $@ $(ASFLAGS) -c $<
 
 #
 # Please keep the next two rules in sync.
 #
-$(CCOBJS): %.$(OBJ_SUFFIX): %.cc
+$(CCOBJS): %.$(OBJ_SUFFIX): %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-$(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp
+$(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-$(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm
+$(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
 
-$(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m
+$(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
 
-%.s: %.cpp
+%.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-%.s: %.cc
+%.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-%.s: %.c
+%.s: %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
-%.i: %.cpp
+%.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
 
-%.i: %.cc
+%.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
 
-%.i: %.c
+%.i: %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i
 
-%.i: %.mm
+%.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i
 
 %.res: %.rc
 	@echo Creating Resource file: $@
 ifeq ($(OS_ARCH),OS2)
 	$(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@
 else
 ifdef GNU_CC
@@ -1351,28 +1345,30 @@ endif
 
 ################################################################################
 # Copy testing-only JS modules to appropriate destination.
 #
 # For each file defined in TESTING_JS_MODULES, copy it to
 # objdir/_tests/modules/. If TESTING_JS_MODULE_DIR is defined, that path
 # wlll be appended to the output directory.
 
+ifdef ENABLE_TESTS
 ifdef TESTING_JS_MODULES
 testmodulesdir = $(DEPTH)/_tests/modules/$(TESTING_JS_MODULE_DIR)
 
 GENERATED_DIRS += $(testmodulesdir)
 
 ifndef NO_DIST_INSTALL
 TESTING_JS_MODULES_FILES := $(TESTING_JS_MODULES)
 TESTING_JS_MODULES_DEST := $(testmodulesdir)
 INSTALL_TARGETS += TESTING_JS_MODULES
 endif
 
 endif
+endif
 
 ################################################################################
 # SDK
 
 ifneq (,$(SDK_LIBRARY))
 ifndef NO_DIST_INSTALL
 SDK_LIBRARY_FILES := $(SDK_LIBRARY)
 SDK_LIBRARY_DEST := $(SDK_LIB_DIR)
@@ -1477,19 +1473,16 @@ endif
 #   processes could simultaneously try to create the same directory.
 #
 #   We use $(CURDIR) in the rule's target to ensure that we don't find
 #   a dependency directory in the source tree via VPATH (perhaps from
 #   a previous build in the source tree) and thus neglect to create a
 #   dependency directory in the object directory, where we really need
 #   it.
 
-$(CURDIR)/$(MDDEPDIR):
-	$(MKDIR) -p $@
-
 ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
 MDDEPEND_FILES		:= $(strip $(wildcard $(foreach file,$(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS) $(TARGETS) $(XPIDLSRCS:.idl=.h) $(XPIDLSRCS:.idl=.xpt),$(MDDEPDIR)/$(notdir $(file)).pp) $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES))))
 
 ifneq (,$(MDDEPEND_FILES))
 # The script mddepend.pl checks the dependencies and writes to stdout
 # one rule to force out-of-date objects. For example,
 #   foo.o boo.o: FORCE
 # The script has an advantage over including the *.pp files directly
--- a/configure.in
+++ b/configure.in
@@ -1612,16 +1612,60 @@ MOZ_ARG_ENABLE_BOOL(profiling,
     MOZ_PROFILING= )
 
 # For profiling builds keep the symbol information
 if test "$MOZ_PROFILING" -a -z "$STRIP_FLAGS"; then
     STRIP_FLAGS="--strip-debug"
 fi
 
 dnl ========================================================
+dnl = Use incremental GC
+dnl ========================================================
+JSGC_INCREMENTAL=1
+MOZ_ARG_DISABLE_BOOL(gcincremental,
+[  --disable-gcincremental Disable incremental GC],
+    JSGC_INCREMENTAL= )
+if test -n "$JSGC_INCREMENTAL"; then
+    AC_DEFINE(JSGC_INCREMENTAL)
+fi
+
+dnl ========================================================
+dnl = Use generational GC
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(gcgenerational,
+[  --enable-gcgenerational Enable generational GC],
+    JSGC_GENERATIONAL=1,
+    JSGC_GENERATIONAL= )
+if test -n "$JSGC_GENERATIONAL"; then
+    AC_DEFINE(JSGC_GENERATIONAL)
+fi
+
+dnl ========================================================
+dnl = Perform moving GC stack rooting analysis
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(root-analysis,
+[  --enable-root-analysis  Enable moving GC stack root analysis],
+    JSGC_ROOT_ANALYSIS=1,
+    JSGC_ROOT_ANALYSIS= )
+if test -n "$JSGC_ROOT_ANALYSIS"; then
+    AC_DEFINE(JSGC_ROOT_ANALYSIS)
+fi
+
+dnl ========================================================
+dnl = Use exact stack rooting for GC
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(exact-rooting,
+[  --enable-exact-rooting  Enable use of exact stack roots for GC],
+    JSGC_USE_EXACT_ROOTING=1,
+    JSGC_USE_EXACT_ROOTING= )
+if test -n "$JSGC_USE_EXACT_ROOTING"; then
+    AC_DEFINE(JSGC_USE_EXACT_ROOTING)
+fi
+
+dnl ========================================================
 dnl = Use Valgrind
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(valgrind,
 [  --enable-valgrind       Enable Valgrind integration hooks (default=no)],
     MOZ_VALGRIND=1,
     MOZ_VALGRIND= )
 if test -n "$MOZ_VALGRIND"; then
     MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -78,14 +78,13 @@ XPIDLSRCS	= \
 		nsIScriptLoaderObserver.idl  \
 		nsIDroppedLinkHandler.idl \
 		nsIImageLoadingContent.idl \
 		nsIObjectLoadingContent.idl \
 		nsIFrameLoader.idl \
 		nsIXMLHttpRequest.idl \
 		nsIContentSecurityPolicy.idl \
 		nsIMessageManager.idl \
-		nsIWebSocket.idl \
 		nsIEventSource.idl \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/content/base/public/nsIDOMFile.idl
+++ b/content/base/public/nsIDOMFile.idl
@@ -78,14 +78,8 @@ interface nsIDOMFile : nsIDOMBlob
 [scriptable, builtinclass, uuid(57195950-edd9-496b-9b45-e4893a9ffca9)]
 interface nsIDOMMozBlobBuilder : nsISupports
 {
   nsIDOMBlob getBlob([optional] in DOMString contentType);
   nsIDOMFile getFile(in DOMString name, [optional] in DOMString contentType);
   [implicit_jscontext] void append(in jsval data,
                                    [optional] in DOMString endings);
 };
-
-dictionary BlobPropertyBag
-{
-  DOMString type;
-  DOMString endings = "transparent";
-};
deleted file mode 100644
--- a/content/base/public/nsIWebSocket.idl
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et tw=80 : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMEventListener;
-interface nsIPrincipal;
-interface nsIScriptContext;
-interface nsPIDOMWindow;
-interface nsIDOMDOMStringList;
-interface nsIVariant;
-
-%{C++
-#include "nsTArray.h"
-class nsString;
-%}
-[ref] native nsStringTArrayRef(nsTArray<nsString>);
-
-/**
- * The nsIWebSocket interface enables Web applications to maintain
- * bidirectional communications with server-side processes as described in:
- *
- * http://dev.w3.org/html5/websockets/
- *
- */
-[scriptable, uuid(5224dbe7-58ac-43e6-93ba-f288a1421dff)]
-interface nsIWebSocket : nsISupports
-{
-  readonly attribute DOMString url;
-  readonly attribute DOMString extensions;
-  readonly attribute DOMString protocol;
-
-  //ready state
-  const unsigned short CONNECTING = 0;
-  const unsigned short OPEN = 1;
-  const unsigned short CLOSING = 2;
-  const unsigned short CLOSED = 3;
-  readonly attribute unsigned short readyState;
-
-  readonly attribute unsigned long bufferedAmount;
-
-  // "blob" by default: can set to "blob" or "arraybuffer": setting to other
-  // values will throw SYNTAX_ERR exception.
-  attribute DOMString binaryType;
-
-  // event handler attributes
-  [implicit_jscontext] attribute jsval onopen;
-  [implicit_jscontext] attribute jsval onmessage;
-  [implicit_jscontext] attribute jsval onerror;
-  [implicit_jscontext] attribute jsval onclose;
-
-  /**
-   * Transmits data to other end of the connection.
-   * @param data The data to be transmitted.  Arraybuffers and Blobs are sent as
-   * binary data.  Strings are sent as UTF-8 text data.  Other types are
-   * converted to a String and sent as a String.
-   * @return if the connection is still established and the data was queued or
-   *         sent successfully.
-   */
-  [implicit_jscontext] void send(in nsIVariant data);
-
-  /**
-   * Closes the Web Socket connection or connection attempt, if any.
-   * If the connection is already closed, it does nothing.
-   */
-  [optional_argc] void close([optional] in unsigned short code,
-                             [optional] in DOMString reason);
-
-  /**
-   * Initialize the object for use from C++ code with the principal, script
-   * context, and owner window that should be used.
-   *
-   * @param principal The principal to use for the request. This must not be
-   *                  null.
-   * @param scriptContext The script context to use for the request. May be
-   *                      null.
-   * @param ownerWindow The associated window for the request. May be null.
-   * @param url The url for opening the socket. This must not be empty, and
-   *            must have an absolute url, using either the ws or wss schemes.
-   * @param protocol  Specifies array of sub-protocols acceptable to the client.
-   *                  If the length of the array is at least one, the server
-   *                  must select one of the listed sub-protocols for the
-   *                  connection to be successful. If empty, no sub-protocol is
-   *                  specified. The server selected sub-protocol can be read
-   *                  from the protocol attribute after connection.
-   */
-  [noscript] void init(in nsIPrincipal principal,
-                       in nsIScriptContext scriptContext,
-                       in nsPIDOMWindow ownerWindow,
-                       in DOMString url,
-                       in nsStringTArrayRef protocol);
-};
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -117,17 +117,17 @@ CPPSRCS		= \
 		nsStyledElement.cpp \
 		nsStyleLinkElement.cpp \
 		nsSyncLoadService.cpp \
 		nsTextFragment.cpp \
 		nsTextNode.cpp \
 		nsTraversal.cpp \
 		nsTreeSanitizer.cpp \
 		nsTreeWalker.cpp \
-		nsWebSocket.cpp \
+		WebSocket.cpp \
 		nsXHTMLContentSerializer.cpp \
 		nsXMLContentSerializer.cpp \
 		nsXMLHttpRequest.cpp \
 		nsXMLNameSpaceMap.cpp \
 		FragmentOrElement.cpp \
 		Link.cpp \
 		nsBlobProtocolHandler.cpp \
 		nsBlobURI.cpp \
rename from content/base/src/nsWebSocket.cpp
rename to content/base/src/WebSocket.cpp
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/Util.h"
-
-#include "nsWebSocket.h"
+#include "WebSocket.h"
+#include "mozilla/dom/WebSocketBinding.h"
 
 #include "nsIScriptGlobalObject.h"
 #include "nsIDOMWindow.h"
 #include "nsIDocument.h"
 #include "nsXPCOM.h"
 #include "nsIXPConnect.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
@@ -45,69 +44,51 @@
 #include "jsfriendapi.h"
 #include "prmem.h"
 #include "nsDOMFile.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIObserverService.h"
 #include "GeneratedEvents.h"
 
-using namespace mozilla;
+namespace mozilla {
+namespace dom {
 
 #define UTF_8_REPLACEMENT_CHAR    static_cast<PRUnichar>(0xFFFD)
 
-#define TRUE_OR_FAIL_WEBSOCKET(x, ret)                                    \
-  PR_BEGIN_MACRO                                                          \
-    if (NS_UNLIKELY(!(x))) {                                              \
-      NS_WARNING("TRUE_OR_FAIL_WEBSOCKET(" #x ") failed");                \
-      FailConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR);          \
-      return ret;                                                         \
-    }                                                                     \
-  PR_END_MACRO
-
-#define SUCCESS_OR_FAIL_WEBSOCKET(res, ret)                               \
-  PR_BEGIN_MACRO                                                          \
-    nsresult __rv = res;                                                  \
-    if (NS_FAILED(__rv)) {                                                \
-      NS_ENSURE_SUCCESS_BODY(res, ret)                                    \
-      FailConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR);          \
-      return ret;                                                         \
-    }                                                                     \
-  PR_END_MACRO
-
 class CallDispatchConnectionCloseEvents: public nsRunnable
 {
 public:
-CallDispatchConnectionCloseEvents(nsWebSocket *aWebSocket)
+CallDispatchConnectionCloseEvents(WebSocket* aWebSocket)
   : mWebSocket(aWebSocket)
   {}
 
   NS_IMETHOD Run()
   {
     mWebSocket->DispatchConnectionCloseEvents();
     return NS_OK;
   }
 
 private:
-  nsRefPtr<nsWebSocket> mWebSocket;
+  nsRefPtr<WebSocket> mWebSocket;
 };
 
 //-----------------------------------------------------------------------------
-// nsWebSocket
+// WebSocket
 //-----------------------------------------------------------------------------
 
 nsresult
-nsWebSocket::PrintErrorOnConsole(const char *aBundleURI,
-                                 const PRUnichar *aError,
-                                 const PRUnichar **aFormatStrings,
-                                 uint32_t aFormatStringsLen)
+WebSocket::PrintErrorOnConsole(const char *aBundleURI,
+                               const PRUnichar *aError,
+                               const PRUnichar **aFormatStrings,
+                               uint32_t aFormatStringsLen)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+
   nsresult rv;
-
   nsCOMPtr<nsIStringBundleService> bundleService =
     do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIStringBundle> strBundle;
   rv = bundleService->CreateBundle(aBundleURI, getter_AddRefs(strBundle));
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -140,98 +121,97 @@ nsWebSocket::PrintErrorOnConsole(const c
   // print the error message directly to the JS console
   rv = console->LogMessage(errorObject);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
-nsWebSocket::CloseConnection(uint16_t aReasonCode,
+WebSocket::CloseConnection(uint16_t aReasonCode,
                              const nsACString& aReasonString)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  if (mReadyState == nsIWebSocket::CLOSING ||
-      mReadyState == nsIWebSocket::CLOSED) {
+  if (mReadyState == WebSocket::CLOSING ||
+      mReadyState == WebSocket::CLOSED) {
     return NS_OK;
   }
 
   // The common case...
   if (mChannel) {
-    mReadyState = nsIWebSocket::CLOSING;
+    mReadyState = WebSocket::CLOSING;
     return mChannel->Close(aReasonCode, aReasonString);
   }
 
   // No channel, but not disconnected: canceled or failed early
   //
-  MOZ_ASSERT(mReadyState == nsIWebSocket::CONNECTING,
+  MOZ_ASSERT(mReadyState == WebSocket::CONNECTING,
              "Should only get here for early websocket cancel/error");
 
   // Server won't be sending us a close code, so use what's passed in here.
   mCloseEventCode = aReasonCode;
   CopyUTF8toUTF16(aReasonString, mCloseEventReason);
 
-  mReadyState = nsIWebSocket::CLOSING;
+  mReadyState = WebSocket::CLOSING;
 
   // Can be called from Cancel() or Init() codepaths, so need to dispatch
   // onerror/onclose asynchronously
   ScheduleConnectionCloseEvents(
                     nullptr,
                     (aReasonCode == nsIWebSocketChannel::CLOSE_NORMAL ||
                      aReasonCode == nsIWebSocketChannel::CLOSE_GOING_AWAY) ?
                      NS_OK : NS_ERROR_FAILURE,
                     false);
 
   return NS_OK;
 }
 
 nsresult
-nsWebSocket::ConsoleError()
+WebSocket::ConsoleError()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  nsresult rv;
 
   nsAutoCString targetSpec;
-  rv = mURI->GetSpec(targetSpec);
+  nsresult rv = mURI->GetSpec(targetSpec);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to get targetSpec");
   } else {
     NS_ConvertUTF8toUTF16 specUTF16(targetSpec);
-    const PRUnichar *formatStrings[] = { specUTF16.get() };
+    const PRUnichar* formatStrings[] = { specUTF16.get() };
 
-    if (mReadyState < nsIWebSocket::OPEN) {
+    if (mReadyState < WebSocket::OPEN) {
       PrintErrorOnConsole("chrome://global/locale/appstrings.properties",
                           NS_LITERAL_STRING("connectionFailure").get(),
                           formatStrings, ArrayLength(formatStrings));
     } else {
       PrintErrorOnConsole("chrome://global/locale/appstrings.properties",
                           NS_LITERAL_STRING("netInterrupt").get(),
                           formatStrings, ArrayLength(formatStrings));
     }
   }
   /// todo some specific errors - like for message too large
   return rv;
 }
 
 
 nsresult
-nsWebSocket::FailConnection(uint16_t aReasonCode,
-                            const nsACString& aReasonString)
+WebSocket::FailConnection(uint16_t aReasonCode,
+                          const nsACString& aReasonString)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   ConsoleError();
   mFailed = true;
   CloseConnection(aReasonCode, aReasonString);
 
   return NS_OK;
 }
 
 nsresult
-nsWebSocket::Disconnect()
+WebSocket::Disconnect()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   if (mDisconnected)
     return NS_OK;
 
   nsCOMPtr<nsILoadGroup> loadGroup;
   GetLoadGroup(getter_AddRefs(loadGroup));
@@ -241,79 +221,79 @@ nsWebSocket::Disconnect()
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
     os->RemoveObserver(this, DOM_WINDOW_FROZEN_TOPIC);
   }
 
   // DontKeepAliveAnyMore() can release the object. So hold a reference to this
   // until the end of the method.
-  nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
+  nsRefPtr<WebSocket> kungfuDeathGrip = this;
 
   DontKeepAliveAnyMore();
   mChannel = nullptr;
   mDisconnected = true;
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
-// nsWebSocket::nsIWebSocketListener methods:
+// WebSocket::nsIWebSocketListener methods:
 //-----------------------------------------------------------------------------
 
 nsresult
-nsWebSocket::DoOnMessageAvailable(const nsACString & aMsg, bool isBinary)
+WebSocket::DoOnMessageAvailable(const nsACString& aMsg, bool isBinary)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  if (mReadyState == nsIWebSocket::CLOSED) {
+  if (mReadyState == WebSocket::CLOSED) {
     NS_ERROR("Received message after CLOSED");
     return NS_ERROR_UNEXPECTED;
   }
 
-  if (mReadyState == nsIWebSocket::OPEN) {
+  if (mReadyState == WebSocket::OPEN) {
     // Dispatch New Message
     nsresult rv = CreateAndDispatchMessageEvent(aMsg, isBinary);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch the message event");
     }
   } else {
     // CLOSING should be the only other state where it's possible to get msgs
     // from channel: Spec says to drop them.
-    MOZ_ASSERT(mReadyState == nsIWebSocket::CLOSING,
+    MOZ_ASSERT(mReadyState == WebSocket::CLOSING,
                "Received message while CONNECTING or CLOSED");
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::OnMessageAvailable(nsISupports *aContext, const nsACString & aMsg)
+WebSocket::OnMessageAvailable(nsISupports* aContext, const nsACString& aMsg)
 {
   return DoOnMessageAvailable(aMsg, false);
 }
 
 NS_IMETHODIMP
-nsWebSocket::OnBinaryMessageAvailable(nsISupports *aContext,
-                                      const nsACString & aMsg)
+WebSocket::OnBinaryMessageAvailable(nsISupports* aContext,
+                                    const nsACString& aMsg)
 {
   return DoOnMessageAvailable(aMsg, true);
 }
 
 NS_IMETHODIMP
-nsWebSocket::OnStart(nsISupports *aContext)
+WebSocket::OnStart(nsISupports* aContext)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   // This is the only function that sets OPEN, and should be called only once
-  MOZ_ASSERT(mReadyState != nsIWebSocket::OPEN,
+  MOZ_ASSERT(mReadyState != WebSocket::OPEN,
              "readyState already OPEN! OnStart called twice?");
 
   // Nothing to do if we've already closed/closing
-  if (mReadyState != nsIWebSocket::CONNECTING) {
+  if (mReadyState != WebSocket::CONNECTING) {
     return NS_OK;
   }
 
   // Attempt to kill "ghost" websocket: but usually too early for check to fail
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
     return rv;
@@ -321,46 +301,46 @@ nsWebSocket::OnStart(nsISupports *aConte
 
   if (!mRequestedProtocolList.IsEmpty()) {
     mChannel->GetProtocol(mEstablishedProtocol);
   }
 
   mChannel->GetExtensions(mEstablishedExtensions);
   UpdateURI();
 
-  mReadyState = nsIWebSocket::OPEN;
+  mReadyState = WebSocket::OPEN;
 
   // Call 'onopen'
   rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("open"));
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to dispatch the open event");
   }
 
   UpdateMustKeepAlive();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::OnStop(nsISupports *aContext, nsresult aStatusCode)
+WebSocket::OnStop(nsISupports* aContext, nsresult aStatusCode)
 {
   // We can be CONNECTING here if connection failed.
   // We can be OPEN if we have encountered a fatal protocol error
   // We can be CLOSING if close() was called and/or server initiated close.
-  MOZ_ASSERT(mReadyState != nsIWebSocket::CLOSED,
+  MOZ_ASSERT(mReadyState != WebSocket::CLOSED,
              "Shouldn't already be CLOSED when OnStop called");
 
   // called by network stack, not JS, so can dispatch JS events synchronously
   return ScheduleConnectionCloseEvents(aContext, aStatusCode, true);
 }
 
 nsresult
-nsWebSocket::ScheduleConnectionCloseEvents(nsISupports *aContext,
-                                           nsresult aStatusCode,
-                                           bool sync)
+WebSocket::ScheduleConnectionCloseEvents(nsISupports* aContext,
+                                         nsresult aStatusCode,
+                                         bool sync)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   // no-op if some other code has already initiated close event
   if (!mOnCloseScheduled) {
     mCloseEventWasClean = NS_SUCCEEDED(aStatusCode);
 
     if (aStatusCode == NS_BASE_STREAM_CLOSED) {
@@ -382,76 +362,75 @@ nsWebSocket::ScheduleConnectionCloseEven
                               NS_DISPATCH_NORMAL);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::OnAcknowledge(nsISupports *aContext, uint32_t aSize)
+WebSocket::OnAcknowledge(nsISupports *aContext, uint32_t aSize)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   if (aSize > mOutgoingBufferedAmount)
     return NS_ERROR_UNEXPECTED;
 
   mOutgoingBufferedAmount -= aSize;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::OnServerClose(nsISupports *aContext, uint16_t aCode,
+WebSocket::OnServerClose(nsISupports *aContext, uint16_t aCode,
                            const nsACString &aReason)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  MOZ_ASSERT(mReadyState != nsIWebSocket::CONNECTING,
+  MOZ_ASSERT(mReadyState != WebSocket::CONNECTING,
              "Received server close before connected?");
-  MOZ_ASSERT(mReadyState != nsIWebSocket::CLOSED,
+  MOZ_ASSERT(mReadyState != WebSocket::CLOSED,
              "Received server close after already closed!");
 
   // store code/string for onclose DOM event
   mCloseEventCode = aCode;
   CopyUTF8toUTF16(aReason, mCloseEventReason);
 
-  if (mReadyState == nsIWebSocket::OPEN) {
+  if (mReadyState == WebSocket::OPEN) {
     // Server initiating close.
     // RFC 6455, 5.5.1: "When sending a Close frame in response, the endpoint
     // typically echos the status code it received".
     // But never send certain codes, per section 7.4.1
     if (aCode == 1005 || aCode == 1006 || aCode == 1015) {
       CloseConnection(0, EmptyCString());
     } else {
       CloseConnection(aCode, aReason);
     }
   } else {
     // We initiated close, and server has replied: OnStop does rest of the work.
-    MOZ_ASSERT(mReadyState == nsIWebSocket::CLOSING, "unknown state");
+    MOZ_ASSERT(mReadyState == WebSocket::CLOSING, "unknown state");
   }
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
-// nsWebSocket::nsIInterfaceRequestor
+// WebSocket::nsIInterfaceRequestor
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsWebSocket::GetInterface(const nsIID &aIID, void **aResult)
+WebSocket::GetInterface(const nsIID& aIID, void** aResult)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  if (mReadyState == nsIWebSocket::CLOSED)
+  if (mReadyState == WebSocket::CLOSED)
     return NS_ERROR_FAILURE;
 
   if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
       aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
     nsresult rv;
-
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     nsCOMPtr<nsIDocument> doc =
       nsContentUtils::GetDocumentFromScriptContext(sc);
     if (!doc)
       return NS_ERROR_NOT_AVAILABLE;
 
     nsCOMPtr<nsIPromptFactory> wwatch =
       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
@@ -460,265 +439,356 @@ nsWebSocket::GetInterface(const nsIID &a
     nsCOMPtr<nsPIDOMWindow> outerWindow = doc->GetWindow();
     return wwatch->GetPrompt(outerWindow, aIID, aResult);
   }
 
   return QueryInterface(aIID, aResult);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsWebSocket
+// WebSocket
 ////////////////////////////////////////////////////////////////////////////////
 
-nsWebSocket::nsWebSocket() : mKeepingAlive(false),
-                             mCheckMustKeepAlive(true),
-                             mOnCloseScheduled(false),
-                             mFailed(false),
-                             mDisconnected(false),
-                             mCloseEventWasClean(false),
-                             mCloseEventCode(nsIWebSocketChannel::CLOSE_ABNORMAL),
-                             mReadyState(nsIWebSocket::CONNECTING),
-                             mOutgoingBufferedAmount(0),
-                             mBinaryType(WS_BINARY_TYPE_BLOB),
-                             mScriptLine(0),
-                             mInnerWindowID(0)
+WebSocket::WebSocket()
+: mKeepingAlive(false),
+  mCheckMustKeepAlive(true),
+  mOnCloseScheduled(false),
+  mFailed(false),
+  mDisconnected(false),
+  mCloseEventWasClean(false),
+  mCloseEventCode(nsIWebSocketChannel::CLOSE_ABNORMAL),
+  mReadyState(WebSocket::CONNECTING),
+  mOutgoingBufferedAmount(0),
+  mBinaryType(BinaryTypeValues::Blob),
+  mScriptLine(0),
+  mInnerWindowID(0)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsLayoutStatics::AddRef();
+
+  SetIsDOMBinding();
 }
 
-nsWebSocket::~nsWebSocket()
+WebSocket::~WebSocket()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   // If we threw during Init we never called disconnect
   if (!mDisconnected) {
     Disconnect();
   }
   nsLayoutStatics::Release();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsWebSocket)
+JSObject*
+WebSocket::WrapObject(JSContext* cx, JSObject* scope, bool* triedToWrap)
+{
+  return WebSocketBinding::Wrap(cx, scope, this, triedToWrap);
+}
+
+//---------------------------------------------------------------------------
+// WebIDL
+//---------------------------------------------------------------------------
+
+// Constructor:
+already_AddRefed<WebSocket>
+WebSocket::Constructor(JSContext* aCx,
+                       nsISupports* aGlobal,
+                       const nsAString& aUrl,
+                       ErrorResult& aRv)
+{
+  Sequence<nsString> protocols;
+  return WebSocket::Constructor(aCx, aGlobal, aUrl, protocols, aRv);
+}
+
+already_AddRefed<WebSocket>
+WebSocket::Constructor(JSContext* aCx,
+                       nsISupports* aGlobal,
+                       const nsAString& aUrl,
+                       const nsAString& aProtocol,
+                       ErrorResult& aRv)
+{
+  Sequence<nsString> protocols;
+  protocols.AppendElement(aProtocol);
+  return WebSocket::Constructor(aCx, aGlobal, aUrl, protocols, aRv);
+}
+
+already_AddRefed<WebSocket>
+WebSocket::Constructor(JSContext* aCx,
+                       nsISupports* aGlobal,
+                       const nsAString& aUrl,
+                       const Sequence<nsString>& aProtocols,
+                       ErrorResult& aRv)
+{
+  if (!PrefEnabled()) {
+    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aGlobal);
+  if (!scriptPrincipal) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsWebSocket)
+  nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal();
+  if (!principal) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal);
+  if (!sgo) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(aGlobal);
+  if (!ownerWindow) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsTArray<nsString> protocolArray;
+
+  for (uint32_t index = 0, len = aProtocols.Length(); index < len; ++index) {
+
+    const nsString& protocolElement = aProtocols[index];
+
+    if (protocolElement.IsEmpty()) {
+      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+      return nullptr;
+    }
+    if (protocolArray.Contains(protocolElement)) {
+      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+      return nullptr;
+    }
+    if (protocolElement.FindChar(',') != -1)  /* interferes w/list */ {
+      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+      return nullptr;
+    }
+
+    protocolArray.AppendElement(protocolElement);
+  }
+
+  nsRefPtr<WebSocket> webSocket = new WebSocket();
+  nsresult rv = webSocket->Init(aCx, principal, ownerWindow, aUrl, protocolArray);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return nullptr;
+  }
+
+  return webSocket.forget();
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(WebSocket)
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(WebSocket)
   bool isBlack = tmp->IsBlack();
   if (isBlack|| tmp->mKeepingAlive) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->UnmarkGrayJSListeners();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
     }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsWebSocket)
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(WebSocket)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsWebSocket)
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(WebSocket)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsWebSocket,
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WebSocket,
                                                nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsWebSocket,
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WebSocket,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mURI)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsWebSocket,
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WebSocket,
                                                 nsDOMEventTargetHelper)
   tmp->Disconnect();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrincipal)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mURI)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-DOMCI_DATA(WebSocket, nsWebSocket)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsWebSocket)
-  NS_INTERFACE_MAP_ENTRY(nsIWebSocket)
-  NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WebSocket)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsIWebSocketListener)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIRequest)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebSocket)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
-NS_IMPL_ADDREF_INHERITED(nsWebSocket, nsDOMEventTargetHelper)
-NS_IMPL_RELEASE_INHERITED(nsWebSocket, nsDOMEventTargetHelper)
+NS_IMPL_ADDREF_INHERITED(WebSocket, nsDOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(WebSocket, nsDOMEventTargetHelper)
 
-NS_IMPL_EVENT_HANDLER(nsWebSocket, open)
-NS_IMPL_EVENT_HANDLER(nsWebSocket, error)
-NS_IMPL_EVENT_HANDLER(nsWebSocket, message)
-NS_IMPL_EVENT_HANDLER(nsWebSocket, close)
+NS_IMPL_EVENT_HANDLER(WebSocket, open)
+NS_IMPL_EVENT_HANDLER(WebSocket, error)
+NS_IMPL_EVENT_HANDLER(WebSocket, message)
+NS_IMPL_EVENT_HANDLER(WebSocket, close)
 
 void
-nsWebSocket::DisconnectFromOwner()
+WebSocket::DisconnectFromOwner()
 {
   nsDOMEventTargetHelper::DisconnectFromOwner();
   CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
   DontKeepAliveAnyMore();
 }
 
 //-----------------------------------------------------------------------------
-// nsWebSocket::nsIJSNativeInitializer methods:
+// WebSocket:: initialization
 //-----------------------------------------------------------------------------
 
-/**
- * This Initialize method is called from XPConnect via nsIJSNativeInitializer.
- * It is used for constructing our nsWebSocket from JavaScript. It expects a URL
- * string parameter and an optional protocol parameter which may be a string or
- * an array of strings. It also initializes the principal, the script context and
- * the window owner.
- */
-NS_IMETHODIMP
-nsWebSocket::Initialize(nsISupports* aOwner,
-                        JSContext* aContext,
-                        JSObject* aObject,
-                        uint32_t aArgc,
-                        JS::Value* aArgv)
+nsresult
+WebSocket::Init(JSContext* aCx,
+                nsIPrincipal* aPrincipal,
+                nsPIDOMWindow* aOwnerWindow,
+                const nsAString& aURL,
+                nsTArray<nsString>& aProtocolArray)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  nsAutoString urlParam;
+  MOZ_ASSERT(aPrincipal);
+  MOZ_ASSERT(aOwnerWindow);
+  MOZ_ASSERT(aOwnerWindow->IsInnerWindow());
 
   if (!PrefEnabled()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  if (aArgc != 1 && aArgc != 2) {
-    return NS_ERROR_DOM_SYNTAX_ERR;
-  }
+  mPrincipal = aPrincipal;
+  BindToOwner(aOwnerWindow);
 
-  JSAutoRequest ar(aContext);
+  // Attempt to kill "ghost" websocket: but usually too early for check to fail
+  nsresult rv = CheckInnerWindowCorrectness();
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  JSString* jsstr = JS_ValueToString(aContext, aArgv[0]);
-  if (!jsstr) {
-    return NS_ERROR_DOM_SYNTAX_ERR;
-  }
+  // Shut down websocket if window is frozen or destroyed (only needed for
+  // "ghost" websockets--see bug 696085)
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  NS_ENSURE_STATE(os);
+  rv = os->AddObserver(this, DOM_WINDOW_DESTROYED_TOPIC, true);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = os->AddObserver(this, DOM_WINDOW_FROZEN_TOPIC, true);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  JS::Anchor<JSString *> deleteProtector(jsstr);
-  size_t length;
-  const jschar *chars = JS_GetStringCharsAndLength(aContext, jsstr, &length);
-  if (!chars) {
-    return NS_ERROR_OUT_OF_MEMORY;
+  unsigned lineno;
+  JSScript* script;
+  if (JS_DescribeScriptedCaller(aCx, &script, &lineno)) {
+    mScriptFile = JS_GetScriptFilename(aCx, script);
+    mScriptLine = lineno;
   }
 
-  urlParam.Assign(chars, length);
-  deleteProtector.clear();
-
-  nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(aOwner);
-  NS_ENSURE_STATE(ownerWindow);
-
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
-  NS_ENSURE_STATE(sgo);
-  nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
-  NS_ENSURE_STATE(scriptContext);
-
-  nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal(do_QueryInterface(aOwner));
-  NS_ENSURE_STATE(scriptPrincipal);
-  nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal();
-  NS_ENSURE_STATE(principal);
+  // Get WindowID
+  mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(aCx);
 
-  nsTArray<nsString> protocolArray;
-
-  if (aArgc == 2) {
-    if (aArgv[1].isObject() &&
-        JS_IsArrayObject(aContext, &aArgv[1].toObject())) {
-      JSObject* jsobj = &aArgv[1].toObject();
+  // parses the url
+  rv = ParseURL(PromiseFlatString(aURL));
+  NS_ENSURE_SUCCESS(rv, rv);
 
-      uint32_t len;
-      JS_GetArrayLength(aContext, jsobj, &len);
-      
-      for (uint32_t index = 0; index < len; ++index) {
-        jsval value;
-
-        if (!JS_GetElement(aContext, jsobj, index, &value))
-          return NS_ERROR_DOM_SYNTAX_ERR;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-        jsstr = JS_ValueToString(aContext, value);
-        if (!jsstr)
-          return NS_ERROR_DOM_SYNTAX_ERR;
-
-        deleteProtector.set(jsstr);
-        chars = JS_GetStringCharsAndLength(aContext, jsstr, &length);
-        if (!chars)
-          return NS_ERROR_OUT_OF_MEMORY;
+  nsCOMPtr<nsIDocument> originDoc = nsContentUtils::GetDocumentFromScriptContext(sc);
 
-        nsDependentString protocolElement(chars, length);
-        if (protocolElement.IsEmpty())
-          return NS_ERROR_DOM_SYNTAX_ERR;
-        if (protocolArray.Contains(protocolElement))
-          return NS_ERROR_DOM_SYNTAX_ERR;
-        if (protocolElement.FindChar(',') != -1)  /* interferes w/list */
-          return NS_ERROR_DOM_SYNTAX_ERR;
-        protocolArray.AppendElement(protocolElement);
-        deleteProtector.clear();
-      }
-    } else {
-      jsstr = JS_ValueToString(aContext, aArgv[1]);
-      if (!jsstr)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-      
-      deleteProtector.set(jsstr);
-      chars = JS_GetStringCharsAndLength(aContext, jsstr, &length);
-      if (!chars)
-        return NS_ERROR_OUT_OF_MEMORY;
-      
-      nsDependentString protocolElement(chars, length);
-      if (protocolElement.IsEmpty())
-        return NS_ERROR_DOM_SYNTAX_ERR;
-      if (protocolElement.FindChar(',') != -1)  /* interferes w/list */
-        return NS_ERROR_DOM_SYNTAX_ERR;
-      protocolArray.AppendElement(protocolElement);
+  // Don't allow https:// to open ws://
+  if (!mSecure &&
+      !Preferences::GetBool("network.websocket.allowInsecureFromHTTPS",
+                            false)) {
+    // Confirmed we are opening plain ws:// and want to prevent this from a
+    // secure context (e.g. https). Check the security context of the document
+    // associated with this script, which is the same as associated with mOwner.
+    if (originDoc && originDoc->GetSecurityInfo()) {
+      return NS_ERROR_DOM_SECURITY_ERR;
     }
   }
 
-  return Init(principal, scriptContext, ownerWindow, urlParam, protocolArray);
+  // Assign the sub protocol list and scan it for illegal values
+  for (uint32_t index = 0; index < aProtocolArray.Length(); ++index) {
+    for (uint32_t i = 0; i < aProtocolArray[index].Length(); ++i) {
+      if (aProtocolArray[index][i] < static_cast<PRUnichar>(0x0021) ||
+          aProtocolArray[index][i] > static_cast<PRUnichar>(0x007E))
+        return NS_ERROR_DOM_SYNTAX_ERR;
+    }
+
+    if (!mRequestedProtocolList.IsEmpty()) {
+      mRequestedProtocolList.Append(NS_LITERAL_CSTRING(", "));
+    }
+
+    AppendUTF16toUTF8(aProtocolArray[index], mRequestedProtocolList);
+  }
+
+  // Check content policy.
+  int16_t shouldLoad = nsIContentPolicy::ACCEPT;
+  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET,
+                                 mURI,
+                                 mPrincipal,
+                                 originDoc,
+                                 EmptyCString(),
+                                 nullptr,
+                                 &shouldLoad,
+                                 nsContentUtils::GetContentPolicy(),
+                                 nsContentUtils::GetSecurityManager());
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_CP_REJECTED(shouldLoad)) {
+    // Disallowed by content policy.
+    return NS_ERROR_CONTENT_BLOCKED;
+  }
+
+  // the constructor should throw a SYNTAX_ERROR only if it fails to parse the
+  // url parameter, so don't throw if EstablishConnection fails, and call
+  // onerror/onclose asynchronously
+  if (NS_FAILED(EstablishConnection())) {
+    FailConnection(nsIWebSocketChannel::CLOSE_ABNORMAL);
+  }
+
+  return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
-// nsWebSocket methods:
+// WebSocket methods:
 //-----------------------------------------------------------------------------
 
 class nsAutoCloseWS
 {
 public:
-  nsAutoCloseWS(nsWebSocket *aWebSocket)
+  nsAutoCloseWS(WebSocket* aWebSocket)
     : mWebSocket(aWebSocket)
   {}
 
   ~nsAutoCloseWS()
   {
     if (!mWebSocket->mChannel) {
       mWebSocket->CloseConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR);
     }
   }
 private:
-  nsRefPtr<nsWebSocket> mWebSocket;
+  nsRefPtr<WebSocket> mWebSocket;
 };
 
 nsresult
-nsWebSocket::EstablishConnection()
+WebSocket::EstablishConnection()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   NS_ABORT_IF_FALSE(!mChannel, "mChannel should be null");
 
-  nsresult rv;
-
   nsCOMPtr<nsIWebSocketChannel> wsChannel;
   nsAutoCloseWS autoClose(this);
+  nsresult rv;
 
   if (mSecure) {
     wsChannel =
       do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv);
   } else {
     wsChannel =
       do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv);
   }
@@ -753,47 +823,44 @@ nsWebSocket::EstablishConnection()
   NS_ENSURE_SUCCESS(rv, rv);
 
   mChannel = wsChannel;
 
   return NS_OK;
 }
 
 void
-nsWebSocket::DispatchConnectionCloseEvents()
+WebSocket::DispatchConnectionCloseEvents()
 {
-  nsresult rv;
-
-  mReadyState = nsIWebSocket::CLOSED;
+  mReadyState = WebSocket::CLOSED;
 
   // Call 'onerror' if needed
   if (mFailed) {
     nsresult rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch the error event");
     }
   }
 
-  rv = CreateAndDispatchCloseEvent(mCloseEventWasClean, mCloseEventCode,
-                                   mCloseEventReason);
+  nsresult rv = CreateAndDispatchCloseEvent(mCloseEventWasClean, mCloseEventCode,
+                                            mCloseEventReason);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to dispatch the close event");
   }
 
   UpdateMustKeepAlive();
   Disconnect();
 }
 
 nsresult
-nsWebSocket::CreateAndDispatchSimpleEvent(const nsString& aName)
+WebSocket::CreateAndDispatchSimpleEvent(const nsString& aName)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  nsresult rv;
 
-  rv = CheckInnerWindowCorrectness();
+  nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMEvent> event;
   rv = NS_NewDOMEvent(getter_AddRefs(event), nullptr, nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -803,23 +870,22 @@ nsWebSocket::CreateAndDispatchSimpleEven
 
   rv = event->SetTrusted(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 }
 
 nsresult
-nsWebSocket::CreateAndDispatchMessageEvent(const nsACString& aData,
-                                           bool isBinary)
+WebSocket::CreateAndDispatchMessageEvent(const nsACString& aData,
+                                         bool isBinary)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  nsresult rv;
 
-  rv = CheckInnerWindowCorrectness();
+  nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv))
     return NS_OK;
 
   // Get the JSContext
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(GetOwner());
   NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
 
   nsIScriptContext* scriptContext = sgo->GetContext();
@@ -828,21 +894,21 @@ nsWebSocket::CreateAndDispatchMessageEve
   JSContext* cx = scriptContext->GetNativeContext();
   NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
 
   // Create appropriate JS object for message
   jsval jsData;
   {
     JSAutoRequest ar(cx);
     if (isBinary) {
-      if (mBinaryType == WS_BINARY_TYPE_BLOB) {
+      if (mBinaryType == BinaryTypeValues::Blob) {
         rv = CreateResponseBlob(aData, cx, jsData);
         NS_ENSURE_SUCCESS(rv, rv);
-      } else if (mBinaryType == WS_BINARY_TYPE_ARRAYBUFFER) {
-        JSObject *arrayBuf;
+      } else if (mBinaryType == BinaryTypeValues::Arraybuffer) {
+        JSObject* arrayBuf;
         rv = nsContentUtils::CreateArrayBuffer(cx, aData, &arrayBuf);
         NS_ENSURE_SUCCESS(rv, rv);
         jsData = OBJECT_TO_JSVAL(arrayBuf);
       } else {
         NS_RUNTIMEABORT("Unknown binary type!");
         return NS_ERROR_UNEXPECTED;
       }
     } else {
@@ -875,41 +941,41 @@ nsWebSocket::CreateAndDispatchMessageEve
   NS_ENSURE_SUCCESS(rv, rv);
 
   return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 }
 
 // Initial implementation: only stores to RAM, not file
 // TODO: bug 704447: large file support
 nsresult
-nsWebSocket::CreateResponseBlob(const nsACString& aData, JSContext *aCx,
-                                jsval &jsData)
+WebSocket::CreateResponseBlob(const nsACString& aData,
+                              JSContext *aCx,
+                              jsval &jsData)
 {
   uint32_t blobLen = aData.Length();
-  void *blobData = PR_Malloc(blobLen);
+  void* blobData = PR_Malloc(blobLen);
   nsCOMPtr<nsIDOMBlob> blob;
   if (blobData) {
     memcpy(blobData, aData.BeginReading(), blobLen);
     blob = new nsDOMMemoryFile(blobData, blobLen, EmptyString());
   } else {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   JSObject* scope = JS_GetGlobalForScopeChain(aCx);
   return nsContentUtils::WrapNative(aCx, scope, blob, &jsData, nullptr, true);
 }
 
 nsresult
-nsWebSocket::CreateAndDispatchCloseEvent(bool aWasClean,
-                                         uint16_t aCode,
-                                         const nsString &aReason)
+WebSocket::CreateAndDispatchCloseEvent(bool aWasClean,
+                                       uint16_t aCode,
+                                       const nsString &aReason)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  nsresult rv;
 
-  rv = CheckInnerWindowCorrectness();
+  nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return NS_OK;
   }
 
   // create an event that uses the CloseEvent interface,
   // which does not bubble, is not cancelable, and has no default action
 
   nsCOMPtr<nsIDOMEvent> event;
@@ -924,33 +990,31 @@ nsWebSocket::CreateAndDispatchCloseEvent
 
   rv = event->SetTrusted(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 }
 
 bool
-nsWebSocket::PrefEnabled()
+WebSocket::PrefEnabled()
 {
   return Preferences::GetBool("network.websocket.enabled", true);
 }
 
 nsresult
-nsWebSocket::ParseURL(const nsString& aURL)
+WebSocket::ParseURL(const nsString& aURL)
 {
-  nsresult rv;
-
   NS_ENSURE_TRUE(!aURL.IsEmpty(), NS_ERROR_DOM_SYNTAX_ERR);
 
   nsCOMPtr<nsIURI> uri;
-  rv = NS_NewURI(getter_AddRefs(uri), aURL);
+  nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SYNTAX_ERR);
 
-  nsCOMPtr<nsIURL> parsedURL(do_QueryInterface(uri, &rv));
+  nsCOMPtr<nsIURL> parsedURL = do_QueryInterface(uri, &rv);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SYNTAX_ERR);
 
   nsAutoCString fragment;
   rv = parsedURL->GetRef(fragment);
   NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && fragment.IsEmpty(),
                  NS_ERROR_DOM_SYNTAX_ERR);
 
   nsAutoCString scheme;
@@ -1018,80 +1082,80 @@ nsWebSocket::ParseURL(const nsString& aU
 //-----------------------------------------------------------------------------
 // Methods that keep alive the WebSocket object when:
 //   1. the object has registered event listeners that can be triggered
 //      ("strong event listeners");
 //   2. there are outgoing not sent messages.
 //-----------------------------------------------------------------------------
 
 void
-nsWebSocket::UpdateMustKeepAlive()
+WebSocket::UpdateMustKeepAlive()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   if (!mCheckMustKeepAlive) {
     return;
   }
 
   bool shouldKeepAlive = false;
 
   if (mListenerManager) {
     switch (mReadyState)
     {
-      case nsIWebSocket::CONNECTING:
+      case WebSocket::CONNECTING:
       {
         if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("open")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("error")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("close"))) {
           shouldKeepAlive = true;
         }
       }
       break;
 
-      case nsIWebSocket::OPEN:
-      case nsIWebSocket::CLOSING:
+      case WebSocket::OPEN:
+      case WebSocket::CLOSING:
       {
         if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("error")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")) ||
             mOutgoingBufferedAmount != 0) {
           shouldKeepAlive = true;
         }
       }
       break;
 
-      case nsIWebSocket::CLOSED:
+      case WebSocket::CLOSED:
       {
         shouldKeepAlive = false;
       }
     }
   }
 
   if (mKeepingAlive && !shouldKeepAlive) {
     mKeepingAlive = false;
     static_cast<nsIDOMEventTarget*>(this)->Release();
   } else if (!mKeepingAlive && shouldKeepAlive) {
     mKeepingAlive = true;
     static_cast<nsIDOMEventTarget*>(this)->AddRef();
   }
 }
 
 void
-nsWebSocket::DontKeepAliveAnyMore()
+WebSocket::DontKeepAliveAnyMore()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   if (mKeepingAlive) {
     mKeepingAlive = false;
     static_cast<nsIDOMEventTarget*>(this)->Release();
   }
   mCheckMustKeepAlive = false;
 }
 
 nsresult
-nsWebSocket::UpdateURI()
+WebSocket::UpdateURI()
 {
   // Check for Redirections
   nsCOMPtr<nsIURI> uri;
   nsresult rv = mChannel->GetURI(getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString spec;
   rv = uri->GetSpec(spec);
@@ -1102,402 +1166,241 @@ nsWebSocket::UpdateURI()
   rv = uri->SchemeIs("wss", &isWSS);
   NS_ENSURE_SUCCESS(rv, rv);
   mSecure = isWSS ? true : false;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::RemoveEventListener(const nsAString& aType,
-                                 nsIDOMEventListener* aListener,
-                                 bool aUseCapture)
+WebSocket::RemoveEventListener(const nsAString& aType,
+                               nsIDOMEventListener* aListener,
+                               bool aUseCapture)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv = nsDOMEventTargetHelper::RemoveEventListener(aType,
                                                             aListener,
                                                             aUseCapture);
   if (NS_SUCCEEDED(rv)) {
     UpdateMustKeepAlive();
   }
   return rv;
 }
 
 NS_IMETHODIMP
-nsWebSocket::AddEventListener(const nsAString& aType,
-                              nsIDOMEventListener *aListener,
-                              bool aUseCapture,
-                              bool aWantsUntrusted,
-                              uint8_t optional_argc)
+WebSocket::AddEventListener(const nsAString& aType,
+                            nsIDOMEventListener *aListener,
+                            bool aUseCapture,
+                            bool aWantsUntrusted,
+                            uint8_t optional_argc)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv = nsDOMEventTargetHelper::AddEventListener(aType,
                                                          aListener,
                                                          aUseCapture,
                                                          aWantsUntrusted,
                                                          optional_argc);
   if (NS_SUCCEEDED(rv)) {
     UpdateMustKeepAlive();
   }
   return rv;
 }
 
 //-----------------------------------------------------------------------------
-// nsWebSocket::nsIWebSocket methods:
+// WebSocket - methods
 //-----------------------------------------------------------------------------
 
-NS_IMETHODIMP
-nsWebSocket::GetUrl(nsAString& aURL)
+// webIDL: readonly attribute DOMString url
+void
+WebSocket::GetUrl(nsAString& aURL)
 {
   if (mEffectiveURL.IsEmpty()) {
     aURL = mOriginalURL;
   } else {
     aURL = mEffectiveURL;
   }
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsWebSocket::GetExtensions(nsAString& aExtensions)
+// webIDL: readonly attribute DOMString extensions;
+void
+WebSocket::GetExtensions(nsAString& aExtensions)
 {
   CopyUTF8toUTF16(mEstablishedExtensions, aExtensions);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsWebSocket::GetProtocol(nsAString& aProtocol)
+// webIDL: readonly attribute DOMString protocol;
+void
+WebSocket::GetProtocol(nsAString& aProtocol)
 {
   CopyUTF8toUTF16(mEstablishedProtocol, aProtocol);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-nsWebSocket::GetReadyState(uint16_t *aReadyState)
+// webIDL: void send(DOMString data);
+void
+WebSocket::Send(const nsAString& aData,
+                ErrorResult& aRv)
 {
-  *aReadyState = mReadyState;
-  return NS_OK;
-}
+  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-NS_IMETHODIMP
-nsWebSocket::GetBufferedAmount(uint32_t *aBufferedAmount)
-{
-  *aBufferedAmount = mOutgoingBufferedAmount;
-  return NS_OK;
+  NS_ConvertUTF16toUTF8 msgString(aData);
+  Send(nullptr, msgString, msgString.Length(), false, aRv);
 }
 
-NS_IMETHODIMP
-nsWebSocket::GetBinaryType(nsAString& aBinaryType)
+void
+WebSocket::Send(nsIDOMBlob* aData,
+                ErrorResult& aRv)
 {
-  switch (mBinaryType) {
-  case WS_BINARY_TYPE_ARRAYBUFFER:
-    aBinaryType.AssignLiteral("arraybuffer");
-    break;
-  case WS_BINARY_TYPE_BLOB:
-    aBinaryType.AssignLiteral("blob");
-    break;
-  default:
-    NS_ERROR("Should not happen");
+  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+
+  nsCOMPtr<nsIInputStream> msgStream;
+  nsresult rv = aData->GetInternalStream(getter_AddRefs(msgStream));
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
   }
-  return NS_OK;
+
+  uint64_t msgLength;
+  rv = aData->GetSize(&msgLength);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
+
+  if (msgLength > PR_UINT32_MAX) {
+    aRv.Throw(NS_ERROR_FILE_TOO_BIG);
+    return;
+  }
+
+  Send(msgStream, EmptyCString(), msgLength, true, aRv);
 }
 
-NS_IMETHODIMP
-nsWebSocket::SetBinaryType(const nsAString& aBinaryType)
-{
-  if (aBinaryType.EqualsLiteral("arraybuffer")) {
-    mBinaryType = WS_BINARY_TYPE_ARRAYBUFFER;
-  } else if (aBinaryType.EqualsLiteral("blob")) {
-    mBinaryType = WS_BINARY_TYPE_BLOB;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsWebSocket::Send(nsIVariant *aData, JSContext *aCx)
+void
+WebSocket::Send(ArrayBuffer& aData,
+                ErrorResult& aRv)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  if (mReadyState == nsIWebSocket::CONNECTING) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
-  }
+  MOZ_ASSERT(sizeof(*aData.Data()) == 1);
+  uint32_t len = aData.Length();
+  char* data = reinterpret_cast<char*>(aData.Data());
 
-  nsCString msgString;
-  nsCOMPtr<nsIInputStream> msgStream;
-  bool isBinary;
-  uint32_t msgLen;
-  nsresult rv = GetSendParams(aData, msgString, msgStream, isBinary, msgLen, aCx);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Always increment outgoing buffer len, even if closed
-  mOutgoingBufferedAmount += msgLen;
+  nsDependentCSubstring msgString(data, len);
+  Send(nullptr, msgString, len, true, aRv);
+}
 
-  if (mReadyState == nsIWebSocket::CLOSING ||
-      mReadyState == nsIWebSocket::CLOSED) {
-    return NS_OK;
-  }
-
-  MOZ_ASSERT(mReadyState == nsIWebSocket::OPEN,
-             "Unknown state in nsWebSocket::Send");
+void
+WebSocket::Send(ArrayBufferView& aData,
+                ErrorResult& aRv)
+{
+  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
-  if (msgStream) {
-    rv = mChannel->SendBinaryStream(msgStream, msgLen);
-  } else {
-    if (isBinary) {
-      rv = mChannel->SendBinaryMsg(msgString);
-    } else {
-      rv = mChannel->SendMsg(msgString);
-    }
-  }
-  NS_ENSURE_SUCCESS(rv, rv);
+  MOZ_ASSERT(sizeof(*aData.Data()) == 1);
+  uint32_t len = aData.Length();
+  char* data = reinterpret_cast<char*>(aData.Data());
 
-  UpdateMustKeepAlive();
-
-  return NS_OK;
+  nsDependentCSubstring msgString(data, len);
+  Send(nullptr, msgString, len, true, aRv);
 }
 
-nsresult
-nsWebSocket::GetSendParams(nsIVariant *aData, nsCString &aStringOut,
-                           nsCOMPtr<nsIInputStream> &aStreamOut,
-                           bool &aIsBinary, uint32_t &aOutgoingLength,
-                           JSContext *aCx)
+void
+WebSocket::Send(nsIInputStream* aMsgStream,
+                const nsACString& aMsgString,
+                uint32_t aMsgLength,
+                bool aIsBinary,
+                ErrorResult& aRv)
 {
-  // Get type of data (arraybuffer, blob, or string)
-  uint16_t dataType;
-  nsresult rv = aData->GetDataType(&dataType);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (mReadyState == WebSocket::CONNECTING) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
 
-  if (dataType == nsIDataType::VTYPE_INTERFACE ||
-      dataType == nsIDataType::VTYPE_INTERFACE_IS) {
-    nsCOMPtr<nsISupports> supports;
-    nsID *iid;
-    rv = aData->GetAsInterface(&iid, getter_AddRefs(supports));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsMemory::Free(iid);
+  // Always increment outgoing buffer len, even if closed
+  mOutgoingBufferedAmount += aMsgLength;
 
-    // ArrayBuffer?
-    jsval realVal;
-    JSObject* obj;
-    nsresult rv = aData->GetAsJSVal(&realVal);
-    if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
-        (obj = JSVAL_TO_OBJECT(realVal)) &&
-        (JS_IsArrayBufferObject(obj, aCx))) {
-      int32_t len = JS_GetArrayBufferByteLength(obj, aCx);
-      char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj, aCx));
+  if (mReadyState == WebSocket::CLOSING ||
+      mReadyState == WebSocket::CLOSED) {
+    return;
+  }
 
-      aStringOut.Assign(data, len);
-      aIsBinary = true;
-      aOutgoingLength = len;
-      return NS_OK;
-    }
+  MOZ_ASSERT(mReadyState == WebSocket::OPEN,
+             "Unknown state in WebSocket::Send");
 
-    // Blob?
-    nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
-    if (blob) {
-      rv = blob->GetInternalStream(getter_AddRefs(aStreamOut));
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      // GetSize() should not perform blocking I/O (unlike Available())
-      uint64_t blobLen;
-      rv = blob->GetSize(&blobLen);
-      NS_ENSURE_SUCCESS(rv, rv);
-      if (blobLen > PR_UINT32_MAX) {
-        return NS_ERROR_FILE_TOO_BIG;
-      }
-      aOutgoingLength = static_cast<uint32_t>(blobLen);
-
-      aIsBinary = true;
-      return NS_OK;
+  nsresult rv;
+  if (aMsgStream) {
+    rv = mChannel->SendBinaryStream(aMsgStream, aMsgLength);
+  } else {
+    if (aIsBinary) {
+      rv = mChannel->SendBinaryMsg(aMsgString);
+    } else {
+      rv = mChannel->SendMsg(aMsgString);
     }
   }
 
-  // Text message: if not already a string, turn it into one.
-  // TODO: bug 704444: Correctly coerce any JS type to string
-  //
-  PRUnichar* data = nullptr;
-  uint32_t len = 0;
-  rv = aData->GetAsWStringWithSize(&len, &data);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
 
-  nsString text;
-  text.Adopt(data, len);
-
-  CopyUTF16toUTF8(text, aStringOut);
-
-  aIsBinary = false;
-  aOutgoingLength = aStringOut.Length();
-  return NS_OK;
+  UpdateMustKeepAlive();
 }
 
-NS_IMETHODIMP
-nsWebSocket::Close(uint16_t code, const nsAString & reason, uint8_t argc)
+// webIDL: void close(optional unsigned short code, optional DOMString reason):
+void
+WebSocket::Close(const Optional<uint16_t>& aCode,
+                 const Optional<nsAString>& aReason,
+                 ErrorResult& aRv)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   // the reason code is optional, but if provided it must be in a specific range
   uint16_t closeCode = 0;
-  if (argc >= 1) {
-    if (code != 1000 && (code < 3000 || code > 4999)) {
-      return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+  if (aCode.WasPassed()) {
+    if (aCode.Value() != 1000 && (aCode.Value() < 3000 || aCode.Value() > 4999)) {
+      aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+      return;
     }
-    closeCode = code;
+    closeCode = aCode.Value();
   }
 
-  nsAutoCString closeReason;
-  if (argc >= 2) {
-    CopyUTF16toUTF8(reason, closeReason);
+  nsCString closeReason;
+  if (aReason.WasPassed()) {
+    CopyUTF16toUTF8(aReason.Value(), closeReason);
 
     // The API requires the UTF-8 string to be 123 or less bytes
     if (closeReason.Length() > 123) {
-      return NS_ERROR_DOM_SYNTAX_ERR;
+      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+      return;
     }
   }
 
-  if (mReadyState == nsIWebSocket::CLOSING ||
-      mReadyState == nsIWebSocket::CLOSED) {
-    return NS_OK;
-  }
-
-  if (mReadyState == nsIWebSocket::CONNECTING) {
-    FailConnection(closeCode, closeReason);
-    return NS_OK;
-  }
-
-  // mReadyState == nsIWebSocket::OPEN
-  CloseConnection(closeCode, closeReason);
-
-  return NS_OK;
-}
-
-/**
- * This Init method should only be called by C++ consumers.
- */
-NS_IMETHODIMP
-nsWebSocket::Init(nsIPrincipal* aPrincipal,
-                  nsIScriptContext* aScriptContext,
-                  nsPIDOMWindow* aOwnerWindow,
-                  const nsAString& aURL,
-                  nsTArray<nsString> & protocolArray)
-{
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  nsresult rv;
-
-  NS_ENSURE_ARG(aPrincipal);
-
-  if (!PrefEnabled()) {
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  mPrincipal = aPrincipal;
-  if (aOwnerWindow) {
-    BindToOwner(aOwnerWindow->IsOuterWindow() ?
-                aOwnerWindow->GetCurrentInnerWindow() : aOwnerWindow);
-  } else {
-    BindToOwner(aOwnerWindow);
+  if (mReadyState == WebSocket::CLOSING ||
+      mReadyState == WebSocket::CLOSED) {
+    return;
   }
 
-  // Attempt to kill "ghost" websocket: but usually too early for check to fail
-  rv = CheckInnerWindowCorrectness();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Shut down websocket if window is frozen or destroyed (only needed for
-  // "ghost" websockets--see bug 696085)
-  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
-  NS_ENSURE_STATE(os);
-  rv = os->AddObserver(this, DOM_WINDOW_DESTROYED_TOPIC, true);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = os->AddObserver(this, DOM_WINDOW_FROZEN_TOPIC, true);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIJSContextStack> stack =
-    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
-  JSContext* cx = nullptr;
-  if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) {
-    unsigned lineno;
-    JSScript *script;
-
-    if (JS_DescribeScriptedCaller(cx, &script, &lineno)) {
-        mScriptFile = JS_GetScriptFilename(cx, script);
-        mScriptLine = lineno;
-    }
-
-    mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
+  if (mReadyState == WebSocket::CONNECTING) {
+    FailConnection(closeCode, closeReason);
+    return;
   }
 
-  // parses the url
-  rv = ParseURL(PromiseFlatString(aURL));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-  nsCOMPtr<nsIDocument> originDoc =
-    nsContentUtils::GetDocumentFromScriptContext(sc);
-
-  // Don't allow https:// to open ws://
-  if (!mSecure &&
-      !Preferences::GetBool("network.websocket.allowInsecureFromHTTPS",
-                            false)) {
-    // Confirmed we are opening plain ws:// and want to prevent this from a
-    // secure context (e.g. https). Check the security context of the document
-    // associated with this script, which is the same as associated with mOwner.
-    if (originDoc && originDoc->GetSecurityInfo())
-      return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  // Assign the sub protocol list and scan it for illegal values
-  for (uint32_t index = 0; index < protocolArray.Length(); ++index) {
-    for (uint32_t i = 0; i < protocolArray[index].Length(); ++i) {
-      if (protocolArray[index][i] < static_cast<PRUnichar>(0x0021) ||
-          protocolArray[index][i] > static_cast<PRUnichar>(0x007E))
-        return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    if (!mRequestedProtocolList.IsEmpty())
-      mRequestedProtocolList.Append(NS_LITERAL_CSTRING(", "));
-    AppendUTF16toUTF8(protocolArray[index], mRequestedProtocolList);
-  }
-
-  // Check content policy.
-  int16_t shouldLoad = nsIContentPolicy::ACCEPT;
-  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET,
-                                 mURI,
-                                 mPrincipal,
-                                 originDoc,
-                                 EmptyCString(),
-                                 nullptr,
-                                 &shouldLoad,
-                                 nsContentUtils::GetContentPolicy(),
-                                 nsContentUtils::GetSecurityManager());
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (NS_CP_REJECTED(shouldLoad)) {
-    // Disallowed by content policy.
-    return NS_ERROR_CONTENT_BLOCKED;
-  }
-
-  // the constructor should throw a SYNTAX_ERROR only if it fails to parse the
-  // url parameter, so don't throw if EstablishConnection fails, and call
-  // onerror/onclose asynchronously
-  if (NS_FAILED(EstablishConnection())) {
-    FailConnection(nsIWebSocketChannel::CLOSE_ABNORMAL);
-  }
-
-  return NS_OK;
+  MOZ_ASSERT(mReadyState == WebSocket::OPEN);
+  CloseConnection(closeCode, closeReason);
 }
 
 //-----------------------------------------------------------------------------
-// nsWebSocket::nsIObserver
+// WebSocket::nsIObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsWebSocket::Observe(nsISupports* aSubject,
-                     const char* aTopic,
-                     const PRUnichar* aData)
+WebSocket::Observe(nsISupports* aSubject,
+                   const char* aTopic,
+                   const PRUnichar* aData)
 {
-  if ((mReadyState == nsIWebSocket::CLOSING) ||
-      (mReadyState == nsIWebSocket::CLOSED)) {
+  if ((mReadyState == WebSocket::CLOSING) ||
+      (mReadyState == WebSocket::CLOSED)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aSubject);
   if (!GetOwner() || window != GetOwner()) {
     return NS_OK;
   }
 
@@ -1505,97 +1408,99 @@ nsWebSocket::Observe(nsISupports* aSubje
       (strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC) == 0))
   {
     CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
   }
 
   return NS_OK;
 }
 
-
 //-----------------------------------------------------------------------------
-// nsWebSocket::nsIRequest
+// WebSocket::nsIRequest
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsWebSocket::GetName(nsACString &aName)
+WebSocket::GetName(nsACString& aName)
 {
   CopyUTF16toUTF8(mOriginalURL, aName);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::IsPending(bool *aValue)
+WebSocket::IsPending(bool* aValue)
 {
-  *aValue = (mReadyState != nsIWebSocket::CLOSED);
+  *aValue = (mReadyState != WebSocket::CLOSED);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::GetStatus(nsresult *aStatus)
+WebSocket::GetStatus(nsresult* aStatus)
 {
   *aStatus = NS_OK;
   return NS_OK;
 }
 
 // Window closed, stop/reload button pressed, user navigated away from page, etc.
 NS_IMETHODIMP
-nsWebSocket::Cancel(nsresult aStatus)
+WebSocket::Cancel(nsresult aStatus)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   if (mReadyState == CLOSING || mReadyState == CLOSED) {
     return NS_OK;
   }
 
   ConsoleError();
 
   return CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
 }
 
 NS_IMETHODIMP
-nsWebSocket::Suspend()
+WebSocket::Suspend()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsWebSocket::Resume()
+WebSocket::Resume()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsWebSocket::GetLoadGroup(nsILoadGroup **aLoadGroup)
+WebSocket::GetLoadGroup(nsILoadGroup** aLoadGroup)
 {
   *aLoadGroup = nullptr;
 
   nsresult rv;
   nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   nsCOMPtr<nsIDocument> doc =
     nsContentUtils::GetDocumentFromScriptContext(sc);
 
   if (doc) {
     *aLoadGroup = doc->GetDocumentLoadGroup().get();  // already_AddRefed
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::SetLoadGroup(nsILoadGroup *aLoadGroup)
+WebSocket::SetLoadGroup(nsILoadGroup* aLoadGroup)
 {
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
-nsWebSocket::GetLoadFlags(nsLoadFlags *aLoadFlags)
+WebSocket::GetLoadFlags(nsLoadFlags* aLoadFlags)
 {
   *aLoadFlags = nsIRequest::LOAD_BACKGROUND;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebSocket::SetLoadFlags(nsLoadFlags aLoadFlags)
+WebSocket::SetLoadFlags(nsLoadFlags aLoadFlags)
 {
   // we won't change the load flags at all.
   return NS_OK;
 }
+
+} // dom namespace
+} // mozilla namespace
rename from content/base/src/nsWebSocket.h
rename to content/base/src/WebSocket.h
--- a/content/base/src/nsWebSocket.h
+++ b/content/base/src/WebSocket.h
@@ -1,151 +1,261 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsWebSocket_h__
-#define nsWebSocket_h__
+#ifndef WebSocket_h__
+#define WebSocket_h__
+
+#include "mozilla/Util.h"
+
+#include "nsWrapperCache.h"
+#include "nsIWebSocketListener.h"
+#include "nsISupports.h"
 
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/TypedArray.h"
+#include "mozilla/dom/BindingUtils.h"
+
+// Need this for BinaryType.
+#include "mozilla/dom/WebSocketBinding.h"
+
+#include "jsfriendapi.h"
 #include "nsISupportsUtils.h"
-#include "nsIWebSocket.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
-#include "nsIJSNativeInitializer.h"
 #include "nsIPrincipal.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMEventListener.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsAutoPtr.h"
 #include "nsIDOMDOMStringList.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIWebSocketChannel.h"
 #include "nsIWebSocketListener.h"
 #include "nsIObserver.h"
 #include "nsIRequest.h"
 #include "nsWeakReference.h"
 
 #define DEFAULT_WS_SCHEME_PORT  80
 #define DEFAULT_WSS_SCHEME_PORT 443
 
-#define NS_WEBSOCKET_CID                            \
- { /* 7ca25214-98dc-40a6-bc1f-41ddbe41f46c */       \
-  0x7ca25214, 0x98dc, 0x40a6,                       \
- {0xbc, 0x1f, 0x41, 0xdd, 0xbe, 0x41, 0xf4, 0x6c} }
-
-#define NS_WEBSOCKET_CONTRACTID "@mozilla.org/websocket;1"
+namespace mozilla {
+namespace dom {
 
-class CallDispatchConnectionCloseEvents;
-class nsAutoCloseWS;
+#define IMPL_EVENT_HANDLER(_lowercase)                                  \
+  inline JSObject* GetOn##_lowercase(JSContext* aCx)                    \
+  {                                                                     \
+    JS::Value val;                                                      \
+    nsresult rv = GetOn##_lowercase(aCx, &val);                         \
+    return NS_SUCCEEDED(rv) ? JSVAL_TO_OBJECT(val) : nullptr;           \
+  }                                                                     \
+  void SetOn##_lowercase(JSContext* aCx, JSObject* aCallback,           \
+                         ErrorResult& aRv)                              \
+  {                                                                     \
+    aRv = SetOn##_lowercase(aCx, OBJECT_TO_JSVAL(aCallback));           \
+  }                                                                     \
+  NS_IMETHOD GetOn##_lowercase(JSContext* cx, JS::Value* aVal);         \
+  NS_IMETHOD SetOn##_lowercase(JSContext* cx, const JS::Value& aVal);
 
-class nsWebSocket: public nsDOMEventTargetHelper,
-                   public nsIWebSocket,
-                   public nsIJSNativeInitializer,
-                   public nsIInterfaceRequestor,
-                   public nsIWebSocketListener,
-                   public nsIObserver,
-                   public nsSupportsWeakReference,
-                   public nsIRequest
+class WebSocket : public nsDOMEventTargetHelper,
+                  public nsIInterfaceRequestor,
+                  public nsIWebSocketListener,
+                  public nsIObserver,
+                  public nsSupportsWeakReference,
+                  public nsIRequest
 {
 friend class CallDispatchConnectionCloseEvents;
 friend class nsAutoCloseWS;
 
 public:
-  nsWebSocket();
-  virtual ~nsWebSocket();
+  enum {
+    CONNECTING = 0,
+    OPEN       = 1,
+    CLOSING    = 2,
+    CLOSED     = 3
+  };
+
+public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(nsWebSocket,
+  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(WebSocket,
                                                                    nsDOMEventTargetHelper)
-  NS_DECL_NSIWEBSOCKET
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSIWEBSOCKETLISTENER
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIREQUEST
 
-  // nsIJSNativeInitializer
-  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
-                        JSObject* aObject, uint32_t aArgc, jsval* aArgv);
-
   // nsIDOMEventTarget
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener *aListener,
                               bool aUseCapture,
                               bool aWantsUntrusted,
                               uint8_t optional_argc);
   NS_IMETHOD RemoveEventListener(const nsAString& aType,
                                  nsIDOMEventListener* aListener,
                                  bool aUseCapture);
 
+  virtual void DisconnectFromOwner();
+
+  // nsWrapperCache
+  nsPIDOMWindow* GetParentObject() { return GetOwner(); }
+
+  JSObject* WrapObject(JSContext *cx,
+                       JSObject *scope,
+                       bool *triedToWrap);
+
+public: // static helpers:
+
   // Determine if preferences allow WebSocket
   static bool PrefEnabled();
 
-  virtual void DisconnectFromOwner();
+public: // WebIDL interface:
+
+  // Constructor:
+  static already_AddRefed<WebSocket> Constructor(JSContext *aCx,
+                                                 nsISupports* aGlobal,
+                                                 const nsAString& aUrl,
+                                                 ErrorResult& rv);
+
+  static already_AddRefed<WebSocket> Constructor(JSContext *aCx,
+                                                 nsISupports* aGlobal,
+                                                 const nsAString& aUrl,
+                                                 const nsAString& aProtocol,
+                                                 ErrorResult& rv);
+
+  static already_AddRefed<WebSocket> Constructor(JSContext *aCx,
+                                                 nsISupports* aGlobal,
+                                                 const nsAString& aUrl,
+                                                 const Sequence<nsString>& aProtocols,
+                                                 ErrorResult& rv);
+
+  // webIDL: readonly attribute DOMString url
+  void GetUrl(nsAString& aResult);
+
+  // webIDL: readonly attribute unsigned short readyState;
+  uint16_t GetReadyState() { return (uint16_t)mReadyState; }
+
+  // webIDL: readonly attribute unsigned long bufferedAmount;
+  uint32_t GetBufferedAmount() { return (uint32_t) mOutgoingBufferedAmount; }
+
+  // webIDL: attribute Function? onopen;
+  IMPL_EVENT_HANDLER(open)
+
+  // webIDL: attribute Function? onerror;
+  IMPL_EVENT_HANDLER(error)
+
+  // webIDL: attribute Function? onclose;
+  IMPL_EVENT_HANDLER(close)
+
+  // webIDL: readonly attribute DOMString extensions;
+  void GetExtensions(nsAString& aResult);
+
+  // webIDL: readonly attribute DOMString protocol;
+  void GetProtocol(nsAString& aResult);
+
+  // webIDL: void close(optional unsigned short code, optional DOMString reason):
+  void Close(const Optional<uint16_t>& aCode,
+             const Optional<nsAString>& aReason,
+             ErrorResult& aRv);
+
+  // webIDL: attribute Function? onmessage;
+  IMPL_EVENT_HANDLER(message)
+
+  // webIDL: attribute DOMString binaryType;
+  BinaryType GetBinaryType() { return mBinaryType; }
+  void SetBinaryType(BinaryType aData) { mBinaryType = aData; }
+
+  // webIDL: void send(DOMString|Blob|ArrayBufferView data);
+  void Send(const nsAString& aData,
+            ErrorResult& aRv);
+  void Send(nsIDOMBlob* aData,
+            ErrorResult& aRv);
+  void Send(ArrayBuffer& aData,
+            ErrorResult& aRv);
+  void Send(ArrayBufferView& aData,
+            ErrorResult& aRv);
+
+private: // constructor && distructor
+  WebSocket();
+  virtual ~WebSocket();
+
 protected:
+  nsresult Init(JSContext* aCx,
+                nsIPrincipal* aPrincipal,
+                nsPIDOMWindow* aOwnerWindow,
+                const nsAString& aURL,
+                nsTArray<nsString>& aProtocolArray);
+
+  void Send(nsIInputStream* aMsgStream,
+            const nsACString& aMsgString,
+            uint32_t aMsgLength,
+            bool aIsBinary,
+            ErrorResult& aRv);
+
   nsresult ParseURL(const nsString& aURL);
   nsresult EstablishConnection();
 
   // These methods when called can release the WebSocket object
   nsresult FailConnection(uint16_t reasonCode,
                           const nsACString& aReasonString = EmptyCString());
   nsresult CloseConnection(uint16_t reasonCode,
                            const nsACString& aReasonString = EmptyCString());
   nsresult Disconnect();
 
   nsresult ConsoleError();
-  nsresult PrintErrorOnConsole(const char       *aBundleURI,
-                               const PRUnichar  *aError,
-                               const PRUnichar **aFormatStrings,
-                               uint32_t          aFormatStringsLen);
+  nsresult PrintErrorOnConsole(const char* aBundleURI,
+                               const PRUnichar* aError,
+                               const PRUnichar** aFormatStrings,
+                               uint32_t aFormatStringsLen);
 
-  // Get msg info out of JS variable being sent (string, arraybuffer, blob)
-  nsresult GetSendParams(nsIVariant *aData, nsCString &aStringOut,
-                         nsCOMPtr<nsIInputStream> &aStreamOut,
-                         bool &aIsBinary, uint32_t &aOutgoingLength,
-                         JSContext *aCx);
-
-  nsresult DoOnMessageAvailable(const nsACString & aMsg, bool isBinary);
+  nsresult DoOnMessageAvailable(const nsACString& aMsg,
+                                bool isBinary);
 
   // ConnectionCloseEvents: 'error' event if needed, then 'close' event.
   // - These must not be dispatched while we are still within an incoming call
   //   from JS (ex: close()).  Set 'sync' to false in that case to dispatch in a
   //   separate new event.
-  nsresult ScheduleConnectionCloseEvents(nsISupports *aContext,
+  nsresult ScheduleConnectionCloseEvents(nsISupports* aContext,
                                          nsresult aStatusCode,
                                          bool sync);
   // 2nd half of ScheduleConnectionCloseEvents, sometimes run in its own event.
-  void     DispatchConnectionCloseEvents();
+  void DispatchConnectionCloseEvents();
 
   // These methods actually do the dispatch for various events.
   nsresult CreateAndDispatchSimpleEvent(const nsString& aName);
   nsresult CreateAndDispatchMessageEvent(const nsACString& aData,
                                          bool isBinary);
-  nsresult CreateAndDispatchCloseEvent(bool aWasClean, uint16_t aCode,
-                                       const nsString &aReason);
-  nsresult CreateResponseBlob(const nsACString& aData, JSContext *aCx,
-                              jsval &jsData);
+  nsresult CreateAndDispatchCloseEvent(bool aWasClean,
+                                       uint16_t aCode,
+                                       const nsString& aReason);
+  nsresult CreateResponseBlob(const nsACString& aData,
+                              JSContext* aCx,
+                              jsval& jsData);
 
-  // if there are "strong event listeners" (see comment in nsWebSocket.cpp) or
+  // if there are "strong event listeners" (see comment in WebSocket.cpp) or
   // outgoing not sent messages then this method keeps the object alive
   // when js doesn't have strong references to it.
   void UpdateMustKeepAlive();
   // ATTENTION, when calling this method the object can be released
   // (and possibly collected).
   void DontKeepAliveAnyMore();
 
   nsresult UpdateURI();
 
+protected: //data
+
   nsCOMPtr<nsIWebSocketChannel> mChannel;
 
   // related to the WebSocket constructor steps
   nsString mOriginalURL;
   nsString mEffectiveURL;   // after redirects
   bool mSecure; // if true it is using SSL and the wss scheme,
-                        // otherwise it is using the ws scheme with no SSL
+                // otherwise it is using the ws scheme with no SSL
 
   bool mKeepingAlive;
   bool mCheckMustKeepAlive;
   bool mOnCloseScheduled;
   bool mFailed;
   bool mDisconnected;
 
   // Set attributes of DOM 'onclose' message
@@ -164,30 +274,29 @@ protected:
   nsCString mEstablishedExtensions;
 
   uint16_t mReadyState;
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
 
   uint32_t mOutgoingBufferedAmount;
 
-  enum
-  {
-    WS_BINARY_TYPE_ARRAYBUFFER,
-    WS_BINARY_TYPE_BLOB,
-  } mBinaryType;
+  BinaryType mBinaryType;
 
   // Web Socket owner information:
   // - the script file name, UTF8 encoded.
   // - source code line number where the Web Socket object was constructed.
   // - the ID of the inner window where the script lives. Note that this may not
   //   be the same as the Web Socket owner window.
   // These attributes are used for error reporting.
   nsCString mScriptFile;
   uint32_t mScriptLine;
   uint64_t mInnerWindowID;
 
 private:
-  nsWebSocket(const nsWebSocket& x);   // prevent bad usage
-  nsWebSocket& operator=(const nsWebSocket& x);
+  WebSocket(const WebSocket& x) MOZ_DELETE;   // prevent bad usage
+  WebSocket& operator=(const WebSocket& x) MOZ_DELETE;
 };
 
+} //namespace dom
+} //namespace mozilla
+
 #endif
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -1,26 +1,27 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsDOMBlobBuilder.h"
 #include "jsfriendapi.h"
+#include "mozilla/dom/BlobBinding.h"
 #include "nsAutoPtr.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIMultiplexInputStream.h"
 #include "nsStringStream.h"
 #include "nsTArray.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
-#include "DictionaryHelpers.h"
 #include "nsIScriptError.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsDOMMultipartFile, nsDOMFile,
                              nsIJSNativeInitializer)
 
 NS_IMETHODIMP
 nsDOMMultipartFile::GetSize(uint64_t* aLength)
 {
   if (mLength == UINT64_MAX) {
@@ -176,24 +177,30 @@ nsDOMMultipartFile::Initialize(nsISuppor
 nsresult
 nsDOMMultipartFile::InitInternal(JSContext* aCx,
                                  uint32_t aArgc,
                                  jsval* aArgv,
                                  UnwrapFuncPtr aUnwrapFunc)
 {
   bool nativeEOL = false;
   if (aArgc > 1) {
-    mozilla::dom::BlobPropertyBag d;
-    nsresult rv = d.Init(aCx, &aArgv[1]);
-    NS_ENSURE_SUCCESS(rv, rv);
-    mContentType = d.type;
-    if (d.endings.EqualsLiteral("native")) {
-      nativeEOL = true;
-    } else if (!d.endings.EqualsLiteral("transparent")) {
-      return NS_ERROR_TYPE_ERR;
+    if (NS_IsMainThread()) {
+      BlobPropertyBag d;
+      if (!d.Init(aCx, aArgv[1])) {
+        return NS_ERROR_TYPE_ERR;
+      }
+      mContentType = d.type;
+      nativeEOL = d.endings == EndingTypesValues::Native;
+    } else {
+      BlobPropertyBagWorkers d;
+      if (!d.Init(aCx, aArgv[1])) {
+        return NS_ERROR_TYPE_ERR;
+      }
+      mContentType = d.type;
+      nativeEOL = d.endings == EndingTypesValues::Native;
     }
   }
 
   if (aArgc > 0) {
     if (!aArgv[0].isObject()) {
       return NS_ERROR_TYPE_ERR; // We're not interested
     }
 
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -2066,17 +2066,22 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSe
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSelectorTearoff)
 
 NS_IMETHODIMP
 nsNodeSelectorTearoff::QuerySelector(const nsAString& aSelector,
                                      nsIDOMElement **aReturn)
 {
   nsresult rv;
   nsIContent* result = mNode->QuerySelector(aSelector, &rv);
-  return result ? CallQueryInterface(result, aReturn) : rv;
+  if (!result) {
+    *aReturn = nullptr;
+    return rv;
+  }
+
+  return CallQueryInterface(result, aReturn);
 }
 
 NS_IMETHODIMP
 nsNodeSelectorTearoff::QuerySelectorAll(const nsAString& aSelector,
                                         nsIDOMNodeList **aReturn)
 {
   return mNode->QuerySelectorAll(aSelector, aReturn);
 }
--- 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;
   }
-
-  // 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);
 
+  nsCOMPtr<nsIContent> thisContent =
+    do_QueryInterface(static_cast<nsIImageLoadingContent *>(this));
+
+  nsIDocument* doc = thisContent->GetCurrentDoc();
+  if (!doc || !InActiveDocument(thisContent)) {
+    NS_ERROR("Shouldn't be calling "
+             "InstantiatePluginInstance without an active document");
+    return NS_ERROR_FAILURE;
+  }
+
   // 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;
+  // Flush layout so that the frame is created if possible and the plugin is
+  // initialized with the latest information.
+  doc->FlushPendingNotifications(Flush_Layout);
+  
+  if (!thisContent->GetPrimaryFrame()) {
+    LOG(("OBJLC [%p]: Not instantiating plugin with no frame", this));
+    return NS_OK;
   }
-  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;
   }
@@ -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/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -541,16 +541,17 @@ NS_INTERFACE_MAP_END
  ** CanvasRenderingContext2D impl
  **/
 
 
 // Initialize our static variables.
 uint32_t nsCanvasRenderingContext2DAzure::sNumLivingContexts = 0;
 uint8_t (*nsCanvasRenderingContext2DAzure::sUnpremultiplyTable)[256] = nullptr;
 uint8_t (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nullptr;
+DrawTarget* nsCanvasRenderingContext2DAzure::sErrorTarget = nullptr;
 
 namespace mozilla {
 namespace dom {
 
 bool
 AzureCanvasEnabled()
 {
   return gfxPlatform::GetPlatform()->SupportsAzureCanvas();
@@ -572,17 +573,17 @@ NS_NewCanvasRenderingContext2DAzure(nsID
   if (!ctx)
     return NS_ERROR_OUT_OF_MEMORY;
 
   *aResult = ctx.forget().get();
   return NS_OK;
 }
 
 nsCanvasRenderingContext2DAzure::nsCanvasRenderingContext2DAzure()
-  : mValid(false), mZero(false), mOpaque(false), mResetLayer(true)
+  : mZero(false), mOpaque(false), mResetLayer(true)
   , mIPC(false)
   , mIsEntireFrameInvalid(false)
   , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
   , mInvalidateCount(0)
 {
   sNumLivingContexts++;
   SetIsDOMBinding();
 }
@@ -595,16 +596,17 @@ nsCanvasRenderingContext2DAzure::~nsCanv
     mUserDatas[i]->Forget();
   }
   sNumLivingContexts--;
   if (!sNumLivingContexts) {
     delete[] sUnpremultiplyTable;
     delete[] sPremultiplyTable;
     sUnpremultiplyTable = nullptr;
     sPremultiplyTable = nullptr;
+    NS_IF_RELEASE(sErrorTarget);
   }
 }
 
 JSObject*
 nsCanvasRenderingContext2DAzure::WrapObject(JSContext *cx, JSObject *scope,
                                             bool *triedToWrap)
 {
   return CanvasRenderingContext2DBinding::Wrap(cx, scope, this, triedToWrap);
@@ -644,26 +646,25 @@ nsresult
 nsCanvasRenderingContext2DAzure::Reset()
 {
   if (mCanvasElement) {
     mCanvasElement->InvalidateCanvas();
   }
 
   // only do this for non-docshell created contexts,
   // since those are the ones that we created a surface for
-  if (mValid && !mDocShell) {
+  if (mTarget && IsTargetValid() && !mDocShell) {
     gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
   }
 
   mTarget = nullptr;
 
   // Since the target changes the backing texture will change, and this will
   // no longer be valid.
   mThebesSurface = nullptr;
-  mValid = false;
   mIsEntireFrameInvalid = false;
   mPredictManyRedrawCalls = false;
 
   return NS_OK;
 }
 
 static void
 WarnAboutUnexpectedStyle(nsHTMLCanvasElement* canvasElement)
@@ -830,189 +831,154 @@ nsCanvasRenderingContext2DAzure::RedrawU
     return;
   }
 
   mgfx::Rect newr =
     mTarget->GetTransform().TransformBounds(ToRect(r));
   Redraw(newr);
 }
 
-NS_IMETHODIMP
-nsCanvasRenderingContext2DAzure::SetDimensions(int32_t width, int32_t height)
+void
+nsCanvasRenderingContext2DAzure::EnsureTarget()
 {
-  RefPtr<DrawTarget> target;
-
-  // Zero sized surfaces cause issues, so just go with 1x1.
-  if (height == 0 || width == 0) {
-    mZero = true;
-    height = 1;
-    width = 1;
-  } else {
-    mZero = false;
-  }
-
-  // Check that the dimensions are sane
-  IntSize size(width, height);
+  if (mTarget) {
+    return;
+  }
+
+   // Check that the dimensions are sane
+  IntSize size(mWidth, mHeight);
   if (size.width <= 0xFFFF && size.height <= 0xFFFF &&
       size.width >= 0 && size.height >= 0) {
     SurfaceFormat format = GetSurfaceFormat();
     nsIDocument* ownerDoc = nullptr;
     if (mCanvasElement) {
       ownerDoc = mCanvasElement->OwnerDoc();
     }
 
     nsRefPtr<LayerManager> layerManager = nullptr;
 
     if (ownerDoc) {
       layerManager =
         nsContentUtils::PersistentLayerManagerForDocument(ownerDoc);
     }
 
-    if (layerManager) {
-      target = layerManager->CreateDrawTarget(size, format);
-    } else {
-      target = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format);
-    }
-  }
-
-  if (target) {
+     if (layerManager) {
+       mTarget = layerManager->CreateDrawTarget(size, format);
+     } else {
+       mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format);
+     }
+  }
+
+  if (mTarget) {
     if (gCanvasAzureMemoryReporter == nullptr) {
         gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
       NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter);
     }
 
-    gCanvasAzureMemoryUsed += width * height * 4;
+    gCanvasAzureMemoryUsed += mWidth * mHeight * 4;
     JSContext* context = nsContentUtils::GetCurrentJSContext();
     if (context) {
-      JS_updateMallocCounter(context, width * height * 4);
+      JS_updateMallocCounter(context, mWidth * mHeight * 4);
     }
-  }
-
-  return InitializeWithTarget(target, width, height);
+
+    mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
+    // always force a redraw, because if the surface dimensions were reset
+    // then the surface became cleared, and we need to redraw everything.
+    Redraw();
+  } else {
+    EnsureErrorTarget();
+    mTarget = sErrorTarget;
+  }
 }
 
-nsresult
-nsCanvasRenderingContext2DAzure::Initialize(int32_t width, int32_t height)
+NS_IMETHODIMP
+nsCanvasRenderingContext2DAzure::SetDimensions(int32_t width, int32_t height)
 {
-  mWidth = width;
-  mHeight = height;
-
-  if (!mValid) {
-    // Create a dummy target in the hopes that it will help us deal with users
-    // calling into us after having changed the size where the size resulted
-    // in an inability to create a correct DrawTarget.
-    mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
-  }
+  ClearTarget();
+
+  // Zero sized surfaces cause issues, so just go with 1x1.
+  if (height == 0 || width == 0) {
+    mZero = true;
+    mWidth = 1;
+    mHeight = 1;
+  } else {
+    mZero = false;
+    mWidth = width;
+    mHeight = height;
+  }
+
+  return NS_OK;
+}
+
+void
+nsCanvasRenderingContext2DAzure::ClearTarget()
+{
+  Reset();
 
   mResetLayer = true;
 
   // set up the initial canvas defaults
   mStyleStack.Clear();
   mPathBuilder = nullptr;
   mPath = nullptr;
   mDSPathBuilder = nullptr;
 
   ContextState *state = mStyleStack.AppendElement();
   state->globalAlpha = 1.0;
 
   state->colorStyles[STYLE_FILL] = NS_RGB(0,0,0);
   state->colorStyles[STYLE_STROKE] = NS_RGB(0,0,0);
   state->shadowColor = NS_RGBA(0,0,0,0);
-
-  if (mTarget) {
-    mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
-    // always force a redraw, because if the surface dimensions were reset
-    // then the surface became cleared, and we need to redraw everything.
-    Redraw();
-  }
-
-  return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-nsresult
-nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, int32_t width, int32_t height)
-{
-  Reset();
-
-  NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
-  mDocShell = nullptr;
-
-  // This first time this is called on this object is via
-  // nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
-  // non-null, otherwise we'll return an error here and GetContext won't
-  // return this context object and we'll never enter this code again.
-  // All other times this method is called, if target is null then
-  // mTarget won't be changed, i.e. it will remain non-null, or else it
-  // will be set to non-null.
-  // In all cases, any usable canvas context will have non-null mTarget.
-
-  if (target) {
-    mValid = true;
-    mTarget = target;
-  } else {
-    mValid = false;
-  }
-
-  return Initialize(width, height);
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, int32_t width, int32_t height)
 {
   mDocShell = shell;
   mThebesSurface = surface;
 
+  SetDimensions(width, height);
   mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, IntSize(width, height));
-  mValid = mTarget != nullptr;
-
-  return Initialize(width, height);
+  if (!mTarget) {
+    EnsureErrorTarget();
+    mTarget = sErrorTarget;
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
 {
-  if (isOpaque == mOpaque)
-    return NS_OK;
-
-  mOpaque = isOpaque;
-
-  if (mValid) {
-    /* If we've already been created, let SetDimensions take care of
-      * recreating our surface
-      */
-    return SetDimensions(mWidth, mHeight);
+  if (isOpaque != mOpaque) {
+    mOpaque = isOpaque;
+    ClearTarget();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::SetIsIPC(bool isIPC)
 {
-  if (isIPC == mIPC)
-      return NS_OK;
-
-  mIPC = isIPC;
-
-  if (mValid) {
-    /* If we've already been created, let SetDimensions take care of
-      * recreating our surface
-      */
-    return SetDimensions(mWidth, mHeight);
+  if (isIPC != mIPC) {
+    mIPC = isIPC;
+    ClearTarget();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter, uint32_t aFlags)
 {
   nsresult rv = NS_OK;
 
-  if (!mValid || !mTarget) {
+  EnsureTarget();
+  if (!IsTargetValid()) {
     return NS_ERROR_FAILURE;
   }
 
   nsRefPtr<gfxASurface> surface;
   
   if (NS_FAILED(GetThebesSurface(getter_AddRefs(surface)))) {
     return NS_ERROR_FAILURE;
   }
@@ -1046,17 +1012,18 @@ nsCanvasRenderingContext2DAzure::Render(
   return rv;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::GetInputStream(const char *aMimeType,
                                                 const PRUnichar *aEncoderOptions,
                                                 nsIInputStream **aStream)
 {
-  if (!mValid || !mTarget) {
+  EnsureTarget();
+  if (!IsTargetValid()) {
     return NS_ERROR_FAILURE;
   }
 
   nsRefPtr<gfxASurface> surface;
 
   if (NS_FAILED(GetThebesSurface(getter_AddRefs(surface)))) {
     return NS_ERROR_FAILURE;
   }
@@ -1133,16 +1100,17 @@ nsCanvasRenderingContext2DAzure::GetCanv
 
 //
 // state
 //
 
 void
 nsCanvasRenderingContext2DAzure::Save()
 {
+  EnsureTarget();
   mStyleStack[mStyleStack.Length() - 1].transform = mTarget->GetTransform();
   mStyleStack.SetCapacity(mStyleStack.Length() + 1);
   mStyleStack.AppendElement(CurrentState());
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::MozSave()
 {
@@ -1151,24 +1119,24 @@ nsCanvasRenderingContext2DAzure::MozSave
 }
 
 void
 nsCanvasRenderingContext2DAzure::Restore()
 {
   if (mStyleStack.Length() - 1 == 0)
     return;
 
+  TransformWillUpdate();
+
   for (uint32_t i = 0; i < CurrentState().clipsPushed.size(); i++) {
     mTarget->PopClip();
   }
 
   mStyleStack.RemoveElementAt(mStyleStack.Length() - 1);
 
-  TransformWillUpdate();
-
   mTarget->SetTransform(CurrentState().transform);
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::MozRestore()
 {
   Restore();
   return NS_OK;
@@ -1176,78 +1144,76 @@ nsCanvasRenderingContext2DAzure::MozRest
 
 //
 // transformations
 //
 
 void
 nsCanvasRenderingContext2DAzure::Scale(double x, double y, ErrorResult& error)
 {
-  if (!mTarget) {
-    error.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
   if (!FloatValidate(x,y)) {
     return;
   }
 
   TransformWillUpdate();
+  if (!IsTargetValid()) {
+    error.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   Matrix newMatrix = mTarget->GetTransform();
   mTarget->SetTransform(newMatrix.Scale(x, y));
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Scale(float x, float y)
 {
   ErrorResult rv;
   Scale((double)x, (double)y, rv);
   return rv.ErrorCode();
 }
 
 void
 nsCanvasRenderingContext2DAzure::Rotate(double angle, ErrorResult& error)
 {
-  if (!mTarget) {
-    error.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
   if (!FloatValidate(angle)) {
     return;
   }
 
   TransformWillUpdate();
+  if (!IsTargetValid()) {
+    error.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
 
   Matrix rotation = Matrix::Rotation(angle);
   mTarget->SetTransform(rotation * mTarget->GetTransform());
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Rotate(float angle)
 {
   ErrorResult rv;
   Rotate((double)angle, rv);
   return rv.ErrorCode();
 }
 
 void
 nsCanvasRenderingContext2DAzure::Translate(double x, double y, ErrorResult& error)
 {
-  if (!mTarget) {
-    error.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
   if (!FloatValidate(x,y)) {
     return;
   }
 
   TransformWillUpdate();
+  if (!IsTargetValid()) {
+    error.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   Matrix newMatrix = mTarget->GetTransform();
   mTarget->SetTransform(newMatrix.Translate(x, y));
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Translate(float x, float y)
 {
@@ -1256,26 +1222,25 @@ nsCanvasRenderingContext2DAzure::Transla
   return rv.ErrorCode();
 }
 
 void
 nsCanvasRenderingContext2DAzure::Transform(double m11, double m12, double m21,
                                            double m22, double dx, double dy,
                                            ErrorResult& error)
 {
-  if (!mTarget) {
-    error.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
   if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
     return;
   }
 
   TransformWillUpdate();
+  if (!IsTargetValid()) {
+    error.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   Matrix matrix(m11, m12, m21, m22, dx, dy);
   mTarget->SetTransform(matrix * mTarget->GetTransform());
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Transform(float m11, float m12, float m21, float m22, float dx, float dy)
 {
@@ -1286,26 +1251,25 @@ nsCanvasRenderingContext2DAzure::Transfo
 }
 
 void
 nsCanvasRenderingContext2DAzure::SetTransform(double m11, double m12,
                                               double m21, double m22,
                                               double dx, double dy,
                                               ErrorResult& error)
 {
-  if (!mTarget) {
-    error.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
   if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
     return;
   }
 
   TransformWillUpdate();
+  if (!IsTargetValid()) {
+    error.Throw(NS_ERROR_FAILURE);
+    return;
+  }
 
   Matrix matrix(m11, m12, m21, m22, dx, dy);
   mTarget->SetTransform(matrix);
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::SetTransform(float m11, float m12, float m21, float m22, float dx, float dy)
 {
@@ -1364,17 +1328,18 @@ ObjectToMatrix(JSContext* cx, JSObject& 
   return true;
 }
 
 void
 nsCanvasRenderingContext2DAzure::SetMozCurrentTransform(JSContext* cx,
                                                         JSObject& currentTransform,
                                                         ErrorResult& error)
 {
-  if (!mTarget) {
+  EnsureTarget();
+  if (!IsTargetValid()) {
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newCTM;
   if (ObjectToMatrix(cx, currentTransform, newCTM, error)) {
     mTarget->SetTransform(newCTM);
   }
@@ -1392,22 +1357,17 @@ nsCanvasRenderingContext2DAzure::SetMozC
   SetMozCurrentTransform(cx, matrix.toObject(), rv);
   return rv.ErrorCode();
 }
 
 JSObject*
 nsCanvasRenderingContext2DAzure::GetMozCurrentTransform(JSContext* cx,
                                                         ErrorResult& error) const
 {
-  if (!mTarget) {
-    error.Throw(NS_ERROR_FAILURE);
-    return NULL;
-  }
-
-  return MatrixToJSObject(cx, mTarget->GetTransform(), error);
+  return MatrixToJSObject(cx, mTarget ? mTarget->GetTransform() : Matrix(), error);
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::GetMozCurrentTransform(JSContext* cx,
                                                         jsval* matrix)
 {
   ErrorResult rv;
   JSObject* obj = GetMozCurrentTransform(cx, rv);
@@ -1417,17 +1377,18 @@ nsCanvasRenderingContext2DAzure::GetMozC
   return rv.ErrorCode();
 }
 
 void
 nsCanvasRenderingContext2DAzure::SetMozCurrentTransformInverse(JSContext* cx,
                                                                JSObject& currentTransform,
                                                                ErrorResult& error)
 {
-  if (!mTarget) {
+  EnsureTarget();
+  if (!IsTargetValid()) {
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newCTMInverse;
   if (ObjectToMatrix(cx, currentTransform, newCTMInverse, error)) {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     if (newCTMInverse.Invert()) {
@@ -1449,18 +1410,17 @@ nsCanvasRenderingContext2DAzure::SetMozC
   return rv.ErrorCode();
 }
 
 JSObject*
 nsCanvasRenderingContext2DAzure::GetMozCurrentTransformInverse(JSContext* cx,
                                                                ErrorResult& error) const
 {
   if (!mTarget) {
-    error.Throw(NS_ERROR_FAILURE);
-    return NULL;
+    return MatrixToJSObject(cx, Matrix(), error);
   }
 
   Matrix ctm = mTarget->GetTransform();
 
   if (!ctm.Invert()) {
     double NaN = JSVAL_TO_DOUBLE(JS_GetNaNValue(cx));
     ctm = Matrix(NaN, NaN, NaN, NaN, NaN, NaN);
   }
@@ -1897,16 +1857,17 @@ nsCanvasRenderingContext2DAzure::CreateP
     return NULL;
   }
 
   // Ignore nullptr cairo surfaces! See bug 666312.
   if (!res.mSurface->CairoSurface() || res.mSurface->CairoStatus()) {
     return NULL;
   }
 
+  EnsureTarget();
   RefPtr<SourceSurface> srcSurf =
     gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
 
   nsRefPtr<nsCanvasPatternAzure> pat =
     new nsCanvasPatternAzure(srcSurf, repeatMode, res.mPrincipal,
                              res.mIsWriteOnly, res.mCORSUsed);
 
   return pat.forget();
@@ -2000,17 +1961,17 @@ nsCanvasRenderingContext2DAzure::GetMozS
 //
 // rects
 //
 
 void
 nsCanvasRenderingContext2DAzure::ClearRect(double x, double y, double w,
                                            double h)
 {
-  if (!FloatValidate(x,y,w,h)) {
+  if (!FloatValidate(x,y,w,h) || !mTarget) {
     return;
   }
  
   mTarget->ClearRect(mgfx::Rect(x, y, w, h));
 
   RedrawUser(gfxRect(x, y, w, h));
 }
 
@@ -2074,16 +2035,17 @@ nsCanvasRenderingContext2DAzure::FillRec
           h = 0;
         }
       }
     }
   }
 
   mgfx::Rect bounds;
   
+  EnsureTarget();
   if (NeedToDrawShadow()) {
     bounds = mgfx::Rect(x, y, w, h);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     FillRect(mgfx::Rect(x, y, w, h),
              CanvasGeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
@@ -2105,27 +2067,32 @@ nsCanvasRenderingContext2DAzure::StrokeR
 {
   if (!FloatValidate(x,y,w,h)) {
     return;
   }
 
   const ContextState &state = CurrentState();
 
   mgfx::Rect bounds;
-  
+
+  if (!w && !h) {
+    return;
+  }
+
+  EnsureTarget();
+  if (!IsTargetValid()) {
+    return;
+  }
+
   if (NeedToDrawShadow()) {
     bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
                         w + state.lineWidth, h + state.lineWidth);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
-  if (!w && !h) {
-    return;
-  }
-
   if (!h) {
     CapStyle cap = CAP_BUTT;
     if (state.lineJoin == JOIN_ROUND) {
       cap = CAP_ROUND;
     }
     AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
       StrokeLine(Point(x, y), Point(x + w, y),
                   CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
@@ -2486,16 +2453,17 @@ nsCanvasRenderingContext2DAzure::EnsureW
         mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
       mPath = nullptr;
       mPathBuilder = nullptr;
       mPathTransformWillUpdate = false;
     }
     return;
   }
 
+  EnsureTarget();
   if (!mPath) {
     NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   } else if (!mPathTransformWillUpdate) {
     mPathBuilder = mPath->CopyToBuilder(fillRule);
   } else {
     mDSPathBuilder =
       mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
@@ -2504,16 +2472,17 @@ nsCanvasRenderingContext2DAzure::EnsureW
 }
 
 void
 nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* = true */)
 {
   FillRule fillRule = CurrentState().fillRule;
 
   if (!mPath && !mPathBuilder && !mDSPathBuilder) {
+    EnsureTarget();
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   }
 
   if (mPathBuilder) {
     mPath = mPathBuilder->Finish();
     mPathBuilder = nullptr;
   }
 
@@ -2549,16 +2518,18 @@ nsCanvasRenderingContext2DAzure::EnsureU
   }
 
   NS_ASSERTION(mPath, "mPath should exist");
 }
 
 void
 nsCanvasRenderingContext2DAzure::TransformWillUpdate()
 {
+  EnsureTarget();
+
   // Store the matrix that would transform the current path to device
   // space.
   if (mPath || mPathBuilder) {
     if (!mPathTransformWillUpdate) {
       // If the transform has already been updated, but a device space builder
       // has not been created yet mPathToDS contains the right transform to
       // transform the current mPath into device space.
       // We should leave it alone.
@@ -3032,16 +3003,17 @@ struct NS_STACK_CLASS nsCanvasBidiProces
     const gfxTextRun::GlyphRun *runs = mTextRun->GetGlyphRuns(&numRuns);
     const uint32_t appUnitsPerDevUnit = mAppUnitsPerDevPixel;
     const double devUnitsPerAppUnit = 1.0/double(appUnitsPerDevUnit);
     Point baselineOrigin =
       Point(point.x * devUnitsPerAppUnit, point.y * devUnitsPerAppUnit);
 
     float advanceSum = 0;
 
+    mCtx->EnsureTarget();
     for (uint32_t c = 0; c < numRuns; c++) {
       gfxFont *font = runs[c].mFont;
       uint32_t endRun = 0;
       if (c + 1 < numRuns) {
         endRun = runs[c + 1].mCharacterOffset;
       } else {
         endRun = mTextRun->GetLength();
       }
@@ -3232,18 +3204,24 @@ nsCanvasRenderingContext2DAzure::DrawOrM
   bool doDrawShadow = aOp == TEXT_DRAW_OPERATION_FILL && NeedToDrawShadow();
 
   nsCanvasBidiProcessorAzure processor;
 
   GetAppUnitsValues(&processor.mAppUnitsPerDevPixel, nullptr);
   processor.mPt = gfxPoint(aX, aY);
   processor.mThebes =
     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));
+
+  // If we don't have a target then we don't have a transform. A target won't
+  // be needed in the case where we're measuring the text size. This allows
+  // to avoid creating a target if it's only being used to measure text sizes.
+  if (mTarget) {
+    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;
     
   nscoord totalWidthCoord;
@@ -3323,16 +3301,17 @@ nsCanvasRenderingContext2DAzure::DrawOrM
 
   // correct bounding box to get it to be the correct size/position
   processor.mBoundingBox.width = totalWidth;
   processor.mBoundingBox.MoveBy(processor.mPt);
 
   processor.mPt.x *= processor.mAppUnitsPerDevPixel;
   processor.mPt.y *= processor.mAppUnitsPerDevPixel;
 
+  EnsureTarget();
   Matrix oldTransform = mTarget->GetTransform();
   // if text is over aMaxWidth, then scale the text horizontally such that its
   // width is precisely aMaxWidth
   if (aMaxWidth.WasPassed() && aMaxWidth.Value() > 0 &&
       totalWidth > aMaxWidth.Value()) {
     Matrix newTransform = oldTransform;
 
     // Translate so that the anchor point is at 0,0, then scale and then
@@ -3662,16 +3641,18 @@ nsCanvasRenderingContext2DAzure::DrawIma
                                            ErrorResult& error)
 {
   MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
 
   RefPtr<SourceSurface> srcSurf;
   gfxIntSize imgSize;
 
   Element* element;
+
+  EnsureTarget();
   if (image.IsHTMLCanvasElement()) {
     nsHTMLCanvasElement* canvas = image.GetAsHTMLCanvasElement();
     element = canvas;
     nsIntSize size = canvas->GetSize();
     if (size.width == 0 || size.height == 0) {
       error.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
       return;
     }
@@ -3923,16 +3904,17 @@ nsCanvasRenderingContext2DAzure::DrawWin
     return;
   }
 
   nsRefPtr<gfxASurface> drawSurf;
   GetThebesSurface(getter_AddRefs(drawSurf));
 
   nsRefPtr<gfxContext> thebes = new gfxContext(drawSurf);
 
+  EnsureTarget();
   Matrix matrix = mTarget->GetTransform();
   thebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21,
                               matrix._22, matrix._31, matrix._32));
 
   // We can't allow web apps to call this until we fix at least the
   // following potential security issues:
   // -- rendering cross-domain IFRAMEs and then extracting the results
   // -- rendering the user's theme and then extracting the results
@@ -4141,17 +4123,18 @@ nsCanvasRenderingContext2DAzure::EnsureU
 }
 
 
 already_AddRefed<ImageData>
 nsCanvasRenderingContext2DAzure::GetImageData(JSContext* aCx, double aSx,
                                               double aSy, double aSw,
                                               double aSh, ErrorResult& error)
 {
-  if (!mValid) {
+  EnsureTarget();
+  if (!IsTargetValid()) {
     error.Throw(NS_ERROR_FAILURE);
     return NULL;
   }
 
   if (!mCanvasElement && !mDocShell) {
     NS_ERROR("No canvas element and no docshell in GetImageData!!!");
     error.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return NULL;
@@ -4335,16 +4318,30 @@ nsCanvasRenderingContext2DAzure::EnsureP
   for (int a = 0; a <= 255; a++) {
     for (int c = 0; c <= 255; c++) {
       sPremultiplyTable[a][c] = (a * c + 254) / 255;
     }
   }
 }
 
 void
+nsCanvasRenderingContext2DAzure::EnsureErrorTarget()
+{
+  if (sErrorTarget) {
+    return;
+  }
+
+  RefPtr<DrawTarget> errorTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
+  NS_ABORT_IF_FALSE(errorTarget, "Failed to allocate the error target!");
+
+  sErrorTarget = errorTarget;
+  NS_ADDREF(sErrorTarget);
+}
+
+void
 nsCanvasRenderingContext2DAzure::FillRuleChanged()
 {
   if (mPath) {
     mPathBuilder = mPath->CopyToBuilder(CurrentState().fillRule);
     mPath = nullptr;
   }
 }
 
@@ -4402,20 +4399,16 @@ nsCanvasRenderingContext2DAzure::PutImag
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
                                                        unsigned char *aData, uint32_t aDataLen,
                                                        bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
                                                        int32_t dirtyWidth, int32_t dirtyHeight)
 {
-  if (!mValid) {
-    return NS_ERROR_FAILURE;
-  }
-
   if (w == 0 || h == 0) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
   IntRect dirtyRect;
   IntRect imageDataRect(0, 0, w, h);
 
   if (hasDirtyRect) {
@@ -4494,16 +4487,21 @@ nsCanvasRenderingContext2DAzure::PutImag
       *dst++ = a;
       *dst++ = sPremultiplyTable[a][r];
       *dst++ = sPremultiplyTable[a][g];
       *dst++ = sPremultiplyTable[a][b];
 #endif
     }
   }
 
+  EnsureTarget();
+  if (!IsTargetValid()) {
+    return NS_ERROR_FAILURE;
+  }
+
   RefPtr<SourceSurface> sourceSurface =
     mTarget->CreateSourceSurfaceFromData(imgsurf->Data(), IntSize(w, h), imgsurf->Stride(), FORMAT_B8G8R8A8);
 
 
   mTarget->CopySurface(sourceSurface,
                        IntRect(dirtyRect.x - x, dirtyRect.y - y,
                                dirtyRect.width, dirtyRect.height),
                        IntPoint(dirtyRect.x, dirtyRect.y));
@@ -4511,23 +4509,17 @@ nsCanvasRenderingContext2DAzure::PutImag
   Redraw(mgfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::GetThebesSurface(gfxASurface **surface)
 {
-  if (!mTarget) {
-    nsRefPtr<gfxASurface> tmpSurf =
-      gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR_ALPHA);
-    *surface = tmpSurf.forget().get();
-    return NS_OK;
-  }
-
+  EnsureTarget();
   if (!mThebesSurface) {
     mThebesSurface =
       gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);    
 
     if (!mThebesSurface) {
       return NS_ERROR_FAILURE;
     }
   } else {
@@ -4627,26 +4619,25 @@ nsCanvasRenderingContext2DAzure::SetMozI
 
 static uint8_t g2DContextLayerUserData;
 
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                                 CanvasLayer *aOldLayer,
                                                 LayerManager *aManager)
 {
-  if (!mValid) {
+  EnsureTarget();
+  if (!IsTargetValid()) {
     // No DidTransactionCallback will be received, so mark the context clean
     // now so future invalidations will be dispatched.
     MarkContextClean();
     return nullptr;
   }
 
-  if (mTarget) {
-    mTarget->Flush();
-  }
+  mTarget->Flush();
 
   if (!mResetLayer && aOldLayer) {
       CanvasRenderingContext2DUserDataAzure* userData =
       static_cast<CanvasRenderingContext2DUserDataAzure*>(
         aOldLayer->GetUserData(&g2DContextLayerUserData));
     if (userData && userData->IsForContext(this)) {
       NS_ADDREF(aOldLayer);
       return aOldLayer;
@@ -4702,10 +4693,10 @@ nsCanvasRenderingContext2DAzure::MarkCon
   mIsEntireFrameInvalid = false;
   mInvalidateCount = 0;
 }
 
 
 bool
 nsCanvasRenderingContext2DAzure::ShouldForceInactiveLayer(LayerManager *aManager)
 {
-    return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight));
+  return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight));
 }
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.h
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.h
@@ -561,16 +561,18 @@ protected:
     */
   static uint8_t (*sUnpremultiplyTable)[256];
 
   /**
     * Lookup table used to speed up PutImageData().
     */
   static uint8_t (*sPremultiplyTable)[256];
 
+  static mozilla::gfx::DrawTarget* sErrorTarget;
+
   // Some helpers.  Doesn't modify a color on failure.
   void SetStyleFromJSValue(JSContext* cx, JS::Value& value, Style whichStyle);
   void SetStyleFromString(const nsAString& str, Style whichStyle);
 
   void SetStyleFromGradient(nsCanvasGradientAzure *gradient, Style whichStyle)
   {
     CurrentState().SetGradientStyle(whichStyle, gradient);
   }
@@ -593,33 +595,60 @@ protected:
     */
   void EnsureUnpremultiplyTable();
 
   /**
     * Creates the premultiply lookup table, if it doesn't exist.
     */
   void EnsurePremultiplyTable();
 
+  /**
+   * Creates the error target, if it doesn't exist
+   */
+  static void EnsureErrorTarget();
+
   /* This function ensures there is a writable pathbuilder available, this
    * pathbuilder may be working in user space or in device space or
    * device space.
    * After calling this function mPathTransformWillUpdate will be false
    */
   void EnsureWritablePath();
 
   // Ensures a path in UserSpace is available.
   // If aCommitTransform is true, then any transform on the context will be
   // used for the path.
   void EnsureUserSpacePath(bool aCommitTransform = true);
 
+  /**
+   * Needs to be called before updating the transform. This makes a call to
+   * EnsureTarget() so you don't have to.
+   */
   void TransformWillUpdate();
 
   // Report the fillRule has changed.
   void FillRuleChanged();
 
+   /**
+   * Create the backing surfacing, if it doesn't exist. If there is an error
+   * in creating the target then it will put sErrorTarget in place. If there
+   * is in turn an error in creating the sErrorTarget then they would both
+   * be null so IsTargetValid() would still return null.
+   */
+  void EnsureTarget();
+
+  /*
+   * Disposes an old target and prepares to lazily create a new target.
+   */
+  void ClearTarget();
+
+  /**
+   * Check if the target is valid after calling EnsureTarget.
+   */
+  bool IsTargetValid() { return mTarget != sErrorTarget; }
+
   /**
     * Returns the surface format this canvas should be allocated using. Takes
     * into account mOpaque, platform requirements, etc.
     */
   mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
 
   void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
                  double sx, double sy, double sw, double sh,
@@ -658,20 +687,16 @@ protected:
     }
 
     return false;
   }
 
   // Member vars
   int32_t mWidth, mHeight;
 
-  // This is true when the canvas is valid, false otherwise, this occurs when
-  // for some reason initialization of the drawtarget fails. If the canvas
-  // is invalid certain behavior is expected.
-  bool mValid;
   // This is true when the canvas is valid, but of zero size, this requires
   // specific behavior on some operations.
   bool mZero;
 
   bool mOpaque;
 
   // This is true when the next time our layer is retrieved we need to
   // recreate it (i.e. our backing surface changed)
@@ -679,17 +704,19 @@ protected:
   // This is needed for drawing in drawAsyncXULElement
   bool mIPC;
 
   nsTArray<CanvasRenderingContext2DUserDataAzure*> mUserDatas;
 
   // If mCanvasElement is not provided, then a docshell is
   nsCOMPtr<nsIDocShell> mDocShell;
 
-  // our drawing surfaces, contexts, and layers
+  // This is created lazily so it is necessary to call EnsureTarget before
+  // accessing it. In the event of an error it will be equal to
+  // sErrorTarget.
   mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
 
   /**
     * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
     * Redraw is called, reset to false when Render is called.
     */
   bool mIsEntireFrameInvalid;
   /**
--- a/content/events/test/test_bug448602.html
+++ b/content/events/test/test_bug448602.html
@@ -16,24 +16,23 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">          
 <script type="application/javascript">
 
 /** Test for Bug 448602 **/
 
 
 function runTests() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 /*
   Disabled due to lack of present support for JSD in JM
   var jsdIDebuggerService = Components.interfaces.jsdIDebuggerService;
   var jsd = Components.classes['@mozilla.org/js/jsd/debugger-service;1']
                       .getService(jsdIDebuggerService);
 */
-  var els = Components.classes["@mozilla.org/eventlistenerservice;1"]
+  var els = SpecialPowers.wrap(Components).classes["@mozilla.org/eventlistenerservice;1"]
                       .getService(Components.interfaces.nsIEventListenerService);
 
   // Event listener info tests
   var root = document.getElementById("testroot");
   var infos = els.getListenerInfoFor(root, {});
   is(infos.length, 0, "Element shouldn't have listeners (1)");
 
   var listenerSource = 'alert(event);';
@@ -102,17 +101,17 @@ function runTests() {
   is(infos[0].type, "click", "Wrong type (4)");
   is(infos[0].capturing, false, "Wrong phase (4)");
   is(infos[0].allowsUntrusted, true, "Should allow untrusted events (3)");
 
   // Event target chain tests
   var l2 = document.getElementById("testlevel2");
   var l3 = document.getElementById("testlevel3");
   var textnode = l3.firstChild;
-  var chain = els.getEventTargetChainFor(textnode, {});
+  var chain = SpecialPowers.unwrap(els.getEventTargetChainFor(textnode, {}));
   ok(chain.length > 3, "Too short event target chain.");
   is(chain[0], textnode, "Wrong chain item (1)");
   is(chain[1], l3, "Wrong chain item (2)");
   is(chain[2], l2, "Wrong chain item (3)");
   is(chain[3], root, "Wrong chain item (4)");
 
   var hasDocumentInChain = false;
   var hasWindowInChain = false;
--- a/content/media/plugins/MPAPI.h
+++ b/content/media/plugins/MPAPI.h
@@ -95,16 +95,17 @@ struct AudioFrame {
 
 struct Decoder;
 
 struct PluginHost {
   bool (*Read)(Decoder *aDecoder, char *aBuffer, int64_t aOffset, uint32_t aCount, uint32_t* aBytes);
   uint64_t (*GetLength)(Decoder *aDecoder);
   void (*SetMetaDataReadMode)(Decoder *aDecoder);
   void (*SetPlaybackReadMode)(Decoder *aDecoder);
+  bool (*GetIntPref)(const char *aPref, int32_t *aResult);
 };
 
 struct Decoder {
   void *mResource;
   void *mPrivate;
 
   Decoder();
 
--- a/content/media/plugins/nsMediaPluginHost.cpp
+++ b/content/media/plugins/nsMediaPluginHost.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "mozilla/Preferences.h"
 #include "mozilla/TimeStamp.h"
 #include "nsTimeRanges.h"
 #include "MediaResource.h"
 #include "nsHTMLMediaElement.h"
 #include "nsMediaPluginHost.h"
 #include "nsXPCOMStrings.h"
 #include "nsISeekableStream.h"
 #include "pratom.h"
@@ -49,21 +50,44 @@ static void SetMetaDataReadMode(Decoder 
   GetResource(aDecoder)->SetReadMode(nsMediaCacheStream::MODE_METADATA);
 }
 
 static void SetPlaybackReadMode(Decoder *aDecoder)
 {
   GetResource(aDecoder)->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK);
 }
 
+class GetIntPrefEvent : public nsRunnable {
+public:
+  GetIntPrefEvent(const char* aPref, int32_t* aResult)
+    : mPref(aPref), mResult(aResult) {}
+  NS_IMETHOD Run() {
+    return Preferences::GetInt(mPref, mResult);
+  }
+private:
+  const char* mPref;
+  int32_t*    mResult;
+};
+
+static bool GetIntPref(const char* aPref, int32_t* aResult)
+{
+  // GetIntPref() is called on the decoder thread, but the Preferences API
+  // can only be called on the main thread. Post a runnable and wait.
+  NS_ENSURE_ARG_POINTER(aPref);
+  NS_ENSURE_ARG_POINTER(aResult);
+  nsCOMPtr<GetIntPrefEvent> event = new GetIntPrefEvent(aPref, aResult);
+  return NS_SUCCEEDED(NS_DispatchToMainThread(event, NS_DISPATCH_SYNC));
+}
+
 static PluginHost sPluginHost = {
   Read,
   GetLength,
   SetMetaDataReadMode,
-  SetPlaybackReadMode
+  SetPlaybackReadMode,
+  GetIntPref
 };
 
 void nsMediaPluginHost::TryLoad(const char *name)
 {
   PRLibrary *lib = PR_LoadLibrary(name);
   if (lib) {
     Manifest *manifest = static_cast<Manifest *>(PR_FindSymbol(lib, "MPAPI_MANIFEST"));
     if (manifest)
--- a/content/xbl/builtin/browser-base.inc
+++ b/content/xbl/builtin/browser-base.inc
@@ -7,11 +7,8 @@
       <handler event="keypress" keycode="VK_RIGHT" command="cmd_charNext" />
 
       <handler event="keypress" key="x" command="cmd_cut" modifiers="accel"/>
       <handler event="keypress" key="c" command="cmd_copy" modifiers="accel"/>
       <handler event="keypress" key="v" command="cmd_paste" modifiers="accel"/>
       <handler event="keypress" key="z" command="cmd_undo" modifiers="accel"/>
       <handler event="keypress" key="z" command="cmd_redo" modifiers="accel,shift" />
       <handler event="keypress" key="a" command="cmd_selectAll" modifiers="accel"/>
-
-      <handler event="keypress" key="/" command="cmd_findTypeText" modifiers="shift any"/>
-      <handler event="keypress" key="'" command="cmd_findTypeLinks" modifiers="shift any"/>
--- a/dom/apps/src/AppsUtils.jsm
+++ b/dom/apps/src/AppsUtils.jsm
@@ -19,16 +19,17 @@ let EXPORTED_SYMBOLS = ["AppsUtils"];
 function debug(s) {
   //dump("-*- AppsUtils.jsm: " + s + "\n");
 }
 
 let AppsUtils = {
   // Clones a app, without the manifest.
   cloneAppObject: function cloneAppObject(aApp) {
     return {
+      name: aApp.name,
       installOrigin: aApp.installOrigin,
       origin: aApp.origin,
       receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null,
       installTime: aApp.installTime,
       manifestURL: aApp.manifestURL,
       appStatus: aApp.appStatus,
       removable: aApp.removable,
       localId: aApp.localId,
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -174,16 +174,17 @@ let DOMApplicationRegistry = {
       cpmm.sendAsyncMessage("Activities:Unregister", json);
     }
   },
 
   _processManifestForId: function(aId) {
     let app = this.webapps[aId];
     this._readManifests([{ id: aId }], (function registerManifest(aResult) {
       let manifest = aResult[0].manifest;
+      app.name = manifest.name;
       this._registerSystemMessages(manifest, app);
       this._registerActivities(manifest, app);
     }).bind(this));
   },
 #endif
 
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "xpcom-shutdown") {
@@ -363,16 +364,17 @@ let DOMApplicationRegistry = {
           tmpDir.remove(true);
         } catch(e) {
         }
       }
     });
     this.webapps[id] = appObject;
 
     appObject.status = "installed";
+    appObject.name = app.manifest.name;
 
     let manifest = new DOMApplicationManifest(app.manifest, app.origin);
 
     if (!aFromSync)
       this._saveApps((function() {
         ppmm.broadcastAsyncMessage("Webapps:Install:Return:OK", aData);
         Services.obs.notifyObservers(this, "webapps-sync-install", appNote);
         this.children.forEach(function(aMsgMgr) {
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -166,17 +166,16 @@
 #include "nsIDOMXPathEvaluator.h"
 #include "nsIXSLTProcessor.h"
 #include "nsIXSLTProcessorPrivate.h"
 
 #include "nsIDOMLSProgressEvent.h"
 #include "nsIDOMParser.h"
 #include "nsIDOMSerializer.h"
 #include "nsXMLHttpRequest.h"
-#include "nsWebSocket.h"
 #include "nsEventSource.h"
 #include "nsIDOMSettingsManager.h"
 #include "nsIDOMContactManager.h"
 #include "nsIDOMApplicationRegistry.h"
 
 #ifdef MOZ_B2G_RIL
 #include "nsIWifi.h"
 #include "nsIWifiEventInits.h"
@@ -1613,19 +1612,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DesktopNotification, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DesktopNotificationCenter, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(WebSocket, nsEventTargetSH,
-                           EVENTTARGET_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(IDBFactory, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(IDBFileHandle, FileHandle, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBRequest, IDBEventTargetSH,
                            IDBEVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBDatabase, IDBEventTargetSH,
                            IDBEVENTTARGET_SCRIPTABLE_FLAGS)
@@ -1740,17 +1736,16 @@ struct nsContractIDMapData
     return rv;                                                                  \
   }
 
 NS_DEFINE_CONTRACT_CTOR(DOMParser, NS_DOMPARSER_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(FileReader, NS_FILEREADER_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(ArchiveReader, NS_ARCHIVEREADER_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(FormData, NS_FORMDATA_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(XMLSerializer, NS_XMLSERIALIZER_CONTRACTID)
-NS_DEFINE_CONTRACT_CTOR(WebSocket, NS_WEBSOCKET_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(XPathEvaluator, NS_XPATH_EVALUATOR_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(XSLTProcessor,
                         "@mozilla.org/document-transformer;1?type=xslt")
 NS_DEFINE_CONTRACT_CTOR(EventSource, NS_EVENTSOURCE_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(MutationObserver, NS_DOMMUTATIONOBSERVER_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(MozActivity, NS_DOMACTIVITY_CONTRACTID)
 
 #undef NS_DEFINE_CONTRACT_CTOR
@@ -1818,17 +1813,16 @@ static const nsConstructorFuncMapData kC
 #include "GeneratedEvents.h"
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, sms::SmsFilter::NewSmsFilter)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XMLHttpRequest, NS_XMLHttpRequestCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(DOMParser, DOMParserCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(FileReader, FileReaderCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ArchiveReader, ArchiveReaderCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(FormData, FormDataCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XMLSerializer, XMLSerializerCtor)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebSocket, WebSocketCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XPathEvaluator, XPathEvaluatorCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XSLTProcessor, XSLTProcessorCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(EventSource, EventSourceCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MutationObserver, MutationObserverCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozActivity, MozActivityCtor)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr;
@@ -2171,17 +2165,17 @@ nsDOMClassInfo::DefineStaticJSVals(JSCon
   return NS_OK;
 }
 
 // static
 bool
 nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
 {
   return xpc::WrapperFactory::IsXrayWrapper(obj) &&
-         !xpc::WrapperFactory::IsPartiallyTransparent(obj);
+         xpc::AccessCheck::wrapperSubsumes(obj);
 }
 
 nsDOMClassInfo::nsDOMClassInfo(nsDOMClassInfoData* aData) : mData(aData)
 {
 }
 
 nsDOMClassInfo::~nsDOMClassInfo()
 {
@@ -4353,21 +4347,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(DesktopNotification, nsIDOMDesktopNotification)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDesktopNotification)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DesktopNotificationCenter, nsIDOMDesktopNotificationCenter)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDesktopNotificationCenter)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(WebSocket, nsIWebSocket)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebSocket)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(IDBFactory, nsIIDBFactory)
     DOM_CLASSINFO_MAP_ENTRY(nsIIDBFactory)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(IDBFileHandle, nsIDOMFileHandle)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileHandle)
     DOM_CLASSINFO_MAP_ENTRY(nsIIDBFileHandle)
   DOM_CLASSINFO_MAP_END
@@ -6708,23 +6697,16 @@ ConstructorEnabled(const nsGlobalNameStr
              aStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo);
 
   // Don't expose chrome only constructors to content windows.
   if (aStruct->mChromeOnly &&
       !nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal())) {
     return false;
   }
 
-  // For now don't expose web sockets unless user has explicitly enabled them
-  if (aStruct->mDOMClassInfoID == eDOMClassInfo_WebSocket_id) {
-    if (!nsWebSocket::PrefEnabled()) {
-      return false;
-    }
-  }
-
   // For now don't expose server events unless user has explicitly enabled them
   if (aStruct->mDOMClassInfoID == eDOMClassInfo_EventSource_id) {
     if (!nsEventSource::PrefEnabled()) {
       return false;
     }
   }
 
   // Don't expose CSSSupportsRule unless @supports processing is enabled.
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -479,19 +479,16 @@ DOMCI_CLASS(ContentFrameMessageManager)
 DOMCI_CLASS(ChromeMessageBroadcaster)
 DOMCI_CLASS(ChromeMessageSender)
 
 DOMCI_CLASS(FormData)
 
 DOMCI_CLASS(DesktopNotification)
 DOMCI_CLASS(DesktopNotificationCenter)
 
-// WebSocket
-DOMCI_CLASS(WebSocket)
-
 DOMCI_CLASS(IDBFactory)
 DOMCI_CLASS(IDBFileHandle)
 DOMCI_CLASS(IDBRequest)
 DOMCI_CLASS(IDBDatabase)
 DOMCI_CLASS(IDBObjectStore)
 DOMCI_CLASS(IDBTransaction)
 DOMCI_CLASS(IDBCursor)
 DOMCI_CLASS(IDBCursorWithValue)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -14,16 +14,17 @@
 #include "nsIDocument.h"
 #include "nsFocusManager.h"
 #include "nsEventStateManager.h"
 #include "nsFrameManager.h"
 #include "nsRefreshDriver.h"
 #include "nsDOMTouchEvent.h"
 #include "nsIDOMTouchEvent.h"
 #include "nsObjectLoadingContent.h"
+#include "nsFrame.h"
 
 #include "nsIScrollableFrame.h"
 
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 
 #include "nsIFrame.h"
 #include "nsIWidget.h"
@@ -131,29 +132,37 @@ nsDOMWindowUtils::GetPresContext()
   nsRefPtr<nsPresContext> presContext;
   docShell->GetPresContext(getter_AddRefs(presContext));
   return presContext;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetImageAnimationMode(uint16_t *aMode)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   NS_ENSURE_ARG_POINTER(aMode);
   *aMode = 0;
   nsPresContext* presContext = GetPresContext();
   if (presContext) {
     *aMode = presContext->ImageAnimationMode();
     return NS_OK;
   }
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetImageAnimationMode(uint16_t aMode)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsPresContext* presContext = GetPresContext();
   if (presContext) {
     presContext->SetImageAnimationMode(aMode);
     return NS_OK;
   }
   return NS_ERROR_NOT_AVAILABLE;
 }
 
@@ -195,16 +204,20 @@ nsDOMWindowUtils::GetDocumentMetadata(co
   
   aValue.Truncate();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::Redraw(uint32_t aCount, uint32_t *aDurationOut)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   if (aCount == 0)
     aCount = 1;
 
   if (nsIPresShell* presShell = GetPresShell()) {
     nsIFrame *rootFrame = presShell->GetRootFrame();
 
     if (rootFrame) {
       nsRect r(nsPoint(0, 0), rootFrame->GetSize());
@@ -1114,16 +1127,20 @@ nsDOMWindowUtils::SendSimpleGestureEvent
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
                                    bool aIgnoreRootScrollFrame,
                                    bool aFlushLayout,
                                    nsIDOMElement** aReturn)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_STATE(doc);
 
   return doc->ElementFromPointHelper(aX, aY, aIgnoreRootScrollFrame, aFlushLayout,
                                      aReturn);
@@ -1237,27 +1254,36 @@ nsDOMWindowUtils::CompareCanvases(nsIDOM
 
   *retVal = different;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetIsMozAfterPaintPending(bool *aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  NS_ENSURE_ARG_POINTER(aResult);
   *aResult = false;
   nsPresContext* presContext = GetPresContext();
   if (!presContext)
     return NS_OK;
   *aResult = presContext->IsDOMPaintEventPending();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ClearMozAfterPaintEvents()
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsPresContext* presContext = GetPresContext();
   if (!presContext)
     return NS_OK;
   presContext->ClearMozAfterPaintEvents();
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1298,16 +1324,20 @@ nsDOMWindowUtils::SuppressEventHandling(
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aScrollY)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_STATE(doc);
 
   if (aFlushLayout) {
     doc->FlushPendingNotifications(Flush_Layout);
@@ -1326,16 +1356,20 @@ nsDOMWindowUtils::GetScrollXY(bool aFlus
   *aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetRootBounds(nsIDOMClientRect** aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   // Weak ref, since we addref it below
   nsClientRect* rect = new nsClientRect();
   NS_ADDREF(*aResult = rect);
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
@@ -1359,16 +1393,20 @@ nsDOMWindowUtils::GetRootBounds(nsIDOMCl
                 nsPresContext::AppUnitsToFloatCSSPixels(bounds.width),
                 nsPresContext::AppUnitsToFloatCSSPixels(bounds.height));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetIMEIsOpen(bool *aState)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   NS_ENSURE_ARG_POINTER(aState);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   // Open state should not be available when IME is not enabled.
   InputContext context = widget->GetInputContext();
@@ -1381,46 +1419,58 @@ nsDOMWindowUtils::GetIMEIsOpen(bool *aSt
   }
   *aState = (context.mIMEState.mOpen == IMEState::OPEN);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetIMEStatus(uint32_t *aState)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   NS_ENSURE_ARG_POINTER(aState);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   InputContext context = widget->GetInputContext();
   *aState = static_cast<uint32_t>(context.mIMEState.mEnabled);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetFocusedInputType(char** aType)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   NS_ENSURE_ARG_POINTER(aType);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
   InputContext context = widget->GetInputContext();
   *aType = ToNewCString(context.mHTMLInputType);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::FindElementWithViewId(nsViewID aID,
                                         nsIDOMElement** aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   if (aID == FrameMetrics::ROOT_SCROLL_ID) {
     nsPresContext* presContext = GetPresContext();
     if (!presContext) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     nsIDocument* document = presContext->Document();
     mozilla::dom::Element* rootElement = document->GetRootElement();
@@ -1805,70 +1855,89 @@ nsDOMWindowUtils::GetVisitedDependentCom
   static_cast<nsComputedDOMStyle*>(decl.get())->SetExposeVisitedStyle(false);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::EnterModalState()
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   window->EnterModalState();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::LeaveModalState()
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   window->LeaveModalState(nullptr);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::EnterModalStateWithWindow(nsIDOMWindow **aWindow)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   *aWindow = window->EnterModalState();
   NS_IF_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::LeaveModalStateWithWindow(nsIDOMWindow *aWindow)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   window->LeaveModalState(aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::IsInModalState(bool *retval)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   *retval = static_cast<nsGlobalWindow*>(window.get())->IsInModalState();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetParent(const JS::Value& aObject,
                             JSContext* aCx,
                             JS::Value* aParent)
 {
-  // This wasn't privileged in the past, but better to expose less than more.
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   // First argument must be an object.
   if (JSVAL_IS_PRIMITIVE(aObject)) {
     return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
@@ -1884,27 +1953,35 @@ nsDOMWindowUtils::GetParent(const JS::Va
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetOuterWindowID(uint64_t *aWindowID)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
   *aWindowID = window->WindowID();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetCurrentInnerWindowID(uint64_t *aWindowID)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
 
   NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
   nsGlobalWindow* inner =
     static_cast<nsGlobalWindow*>(window.get())->GetCurrentInnerWindowInternal();
   if (!inner) {
     return NS_ERROR_NOT_AVAILABLE;
@@ -1941,48 +2018,60 @@ nsDOMWindowUtils::ResumeTimeouts()
   window->ResumeTimeouts();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetLayerManagerType(nsAString& aType)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   LayerManager *mgr = widget->GetLayerManager();
   if (!mgr)
     return NS_ERROR_FAILURE;
 
   mgr->GetBackendName(aType);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StartFrameTimeRecording()
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   LayerManager *mgr = widget->GetLayerManager();
   if (!mgr)
     return NS_ERROR_FAILURE;
 
   mgr->StartFrameTimeRecording();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StopFrameTimeRecording(uint32_t *frameCount, float **frames)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   NS_ENSURE_ARG_POINTER(frameCount);
   NS_ENSURE_ARG_POINTER(frames);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   LayerManager *mgr = widget->GetLayerManager();
@@ -2103,16 +2192,20 @@ nsDOMWindowUtils::ComputeAnimationDistan
 }
 
 nsresult
 nsDOMWindowUtils::RenderDocument(const nsRect& aRect,
                                  uint32_t aFlags,
                                  nscolor aBackgroundColor,
                                  gfxContext* aThebesContext)
 {
+    if (!IsUniversalXPConnectCapable()) {
+      return NS_ERROR_DOM_SECURITY_ERR;
+    }
+
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
     // Get DOM Document
     nsresult rv;
     nsCOMPtr<nsIDOMDocument> ddoc;
     rv = window->GetDocument(getter_AddRefs(ddoc));
     NS_ENSURE_SUCCESS(rv, rv);
@@ -2127,16 +2220,20 @@ nsDOMWindowUtils::RenderDocument(const n
 
     // Render Document
     return presShell->RenderDocument(aRect, aFlags, aBackgroundColor, aThebesContext);
 }
 
 NS_IMETHODIMP 
 nsDOMWindowUtils::GetCursorType(int16_t *aCursor)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   NS_ENSURE_ARG_POINTER(aCursor);
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);  
 
   bool isSameDoc = false;
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
 
@@ -2187,16 +2284,20 @@ nsDOMWindowUtils::GoOnline()
     return NS_OK;
   }
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetDisplayDPI(float *aDPI)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
   *aDPI = widget->GetDPI();
 
   return NS_OK;
 }
@@ -2212,17 +2313,22 @@ nsDOMWindowUtils::GetOuterWindowWithId(u
 
   *aWindow = nsGlobalWindow::GetOuterWindowWithId(aWindowID);
   NS_IF_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
-                              nsIDOMFile **aDOMFile) {
+                              nsIDOMFile **aDOMFile)
+{
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   NS_ADDREF(*aDOMFile = new nsDOMFileFile(aFile));
   return NS_OK;
 }
 
 #ifdef DEBUG
 static bool
 CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)
 {
@@ -2301,16 +2407,20 @@ nsDOMWindowUtils::GetMayHaveTouchEventLi
   nsPIDOMWindow* innerWindow = window->GetCurrentInnerWindow();
   *aResult = innerWindow ? innerWindow->HasTouchEventListeners() : false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::CheckAndClearPaintedState(nsIDOMElement* aElement, bool* aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   if (!aElement) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsresult rv;
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2374,47 +2484,58 @@ GetFileOrBlob(const nsAString& aName, co
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetFile(const nsAString& aName, const jsval& aBlobParts,
                           const jsval& aParameters, JSContext* aCx,
                           uint8_t aOptionalArgCount, nsIDOMFile** aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsISupports> file;
   nsresult rv = GetFileOrBlob(aName, aBlobParts, aParameters, aCx,
                               aOptionalArgCount, getter_AddRefs(file));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMFile> result = do_QueryInterface(file);
   result.forget(aResult);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetBlob(const jsval& aBlobParts, const jsval& aParameters,
                           JSContext* aCx, uint8_t aOptionalArgCount,
                           nsIDOMBlob** aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsISupports> blob;
   nsresult rv = GetFileOrBlob(NullString(), aBlobParts, aParameters, aCx,
                               aOptionalArgCount, getter_AddRefs(blob));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMBlob> result = do_QueryInterface(blob);
   result.forget(aResult);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetFileId(const jsval& aFile, JSContext* aCx,
                             int64_t* aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
 
   if (!JSVAL_IS_PRIMITIVE(aFile)) {
     JSObject* obj = JSVAL_TO_OBJECT(aFile);
 
     nsISupports* nativeObj =
       nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
 
     nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(nativeObj);
@@ -2479,81 +2600,113 @@ nsDOMWindowUtils::GetFileReferences(cons
   *aRefCnt = *aDBRefCnt = *aSliceRefCnt = -1;
   *aResult = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::IsIncrementalGCEnabled(JSContext* cx, bool* aResult)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   *aResult = js::IsIncrementalGCEnabled(JS_GetRuntime(cx));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StartPCCountProfiling(JSContext* cx)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   js::StartPCCountProfiling(cx);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::StopPCCountProfiling(JSContext* cx)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   js::StopPCCountProfiling(cx);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::PurgePCCounts(JSContext* cx)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   js::PurgePCCounts(cx);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPCCountScriptCount(JSContext* cx, int32_t *result)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   *result = js::GetPCCountScriptCount(cx);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPCCountScriptSummary(int32_t script, JSContext* cx, nsAString& result)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   JSString *text = js::GetPCCountScriptSummary(cx, script);
   if (!text)
     return NS_ERROR_FAILURE;
 
   nsDependentJSString str;
   if (!str.init(cx, text))
     return NS_ERROR_FAILURE;
 
   result = str;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPCCountScriptContents(int32_t script, JSContext* cx, nsAString& result)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   JSString *text = js::GetPCCountScriptContents(cx, script);
   if (!text)
     return NS_ERROR_FAILURE;
 
   nsDependentJSString str;
   if (!str.init(cx, text))
     return NS_ERROR_FAILURE;
 
   result = str;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPaintingSuppressed(bool *aPaintingSuppressed)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
   nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIPresShell> presShell;
   docShell->GetPresShell(getter_AddRefs(presShell));
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
@@ -2611,37 +2764,122 @@ nsDOMWindowUtils::SetScrollPositionClamp
 
   return NS_OK;
 }
 
 nsresult
 nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
                                             const nsAString& aNewOrigin)
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_STATE(doc);
 
   doc->RemoteFrameFullscreenChanged(aFrameElement, aNewOrigin);
   return NS_OK;
 }
 
 nsresult
 nsDOMWindowUtils::RemoteFrameFullscreenReverted()
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_STATE(doc);
 
   doc->RemoteFrameFullscreenReverted();
   return NS_OK;
 }
 
 nsresult
 nsDOMWindowUtils::ExitFullscreen()
 {
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
   nsIDocument::ExitFullScreen(/* async = */ false);
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsDOMWindowUtils::SelectAtPoint(float aX, float aY, PRUint32 aSelectBehavior,
+                                bool *_retval)
+{
+  *_retval = false;
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsSelectionAmount amount;
+  switch (aSelectBehavior) {
+    case nsIDOMWindowUtils::SELECT_CHARACTER:
+      amount = eSelectCharacter;
+    break;
+    case nsIDOMWindowUtils::SELECT_CLUSTER:
+      amount = eSelectCluster;
+    break;
+    case nsIDOMWindowUtils::SELECT_WORD:
+      amount = eSelectWord;
+    break;
+    case nsIDOMWindowUtils::SELECT_LINE:
+      amount = eSelectLine;
+    break;
+    case nsIDOMWindowUtils::SELECT_BEGINLINE:
+      amount = eSelectBeginLine;
+    break;
+    case nsIDOMWindowUtils::SELECT_ENDLINE:
+      amount = eSelectEndLine;
+    break;
+    case nsIDOMWindowUtils::SELECT_PARAGRAPH:
+      amount = eSelectParagraph;
+    break;
+    case nsIDOMWindowUtils::SELECT_WORDNOSPACE:
+      amount = eSelectWordNoSpace;
+    break;
+  }
+
+  nsIPresShell* presShell = GetPresShell();
+  if (!presShell) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // The root frame for this content window
+  nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
+  if (!rootFrame) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // Get the target frame at the client coordinates passed to us
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  nsIntPoint pt(aX, aY);
+  nsPoint ptInRoot =
+    nsLayoutUtils::GetEventCoordinatesRelativeTo(widget, pt, rootFrame);
+  nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
+  // This can happen if the page hasn't loaded yet or if the point
+  // is outside the frame.
+  if (!targetFrame) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // Convert point to coordinates relative to the target frame, which is
+  // what targetFrame's SelectByTypeAtPoint expects.
+  nsPoint relPoint =
+    nsLayoutUtils::GetEventCoordinatesRelativeTo(widget, pt, targetFrame);
+
+  nsresult rv =
+    static_cast<nsFrame*>(targetFrame)->
+      SelectByTypeAtPoint(GetPresContext(), relPoint, amount, amount,
+                          nsFrame::SELECT_ACCUMULATE);
+  *_retval = !NS_FAILED(rv);
+  return NS_OK;
+}
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -231,16 +231,22 @@ DOMInterfaces = {
     'headerFile': 'nsXMLHttpRequest.h',
     'prefable': True
 },
 {
     'workers': True,
     'headerFile': 'mozilla/dom/workers/bindings/XMLHttpRequestUpload.h'
 }],
 
+'WebSocket': [
+{
+    'headerFile': 'WebSocket.h',
+    'implicitJSContext': [ 'constructor' ]
+}],
+
 ####################################
 # Test Interfaces of various sorts #
 ####################################
 
 'TestInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'resultNotAddRefed': [ 'receiveWeakSelf', 'receiveWeakNullableSelf',
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -332,30 +332,30 @@ DeviceStorageFile::Remove()
 
   nsCOMPtr<IOEventComplete> iocomplete = new IOEventComplete(this, "deleted");
   NS_DispatchToMainThread(iocomplete);
   return NS_OK;
 }
 
 void
 DeviceStorageFile::CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
-                                uint64_t aSince)
+                                PRTime aSince)
 {
   nsString rootPath;
   nsresult rv = mFile->GetPath(rootPath);
   if (NS_FAILED(rv)) {
     return;
   }
 
   return collectFilesInternal(aFiles, aSince, rootPath);
 }
 
 void
 DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles,
-                                        uint64_t aSince,
+                                        PRTime aSince,
                                         nsAString& aRootPath)
 {
   nsCOMPtr<nsISimpleEnumerator> e;
   mFile->GetDirectoryEntries(getter_AddRefs(e));
 
   if (!e) {
     return;
   }
@@ -842,17 +842,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(DOMRequest)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorageCursor, DOMRequest)
 NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorageCursor, DOMRequest)
 
 nsDOMDeviceStorageCursor::nsDOMDeviceStorageCursor(nsIDOMWindow* aWindow,
                                                    nsIPrincipal* aPrincipal,
                                                    DeviceStorageFile* aFile,
-                                                   uint64_t aSince)
+                                                   PRTime aSince)
   : DOMRequest(aWindow)
   , mOkToCallContinue(false)
   , mSince(aSince)
   , mFile(aFile)
   , mPrincipal(aPrincipal)
 {
 }
 
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -21,16 +21,17 @@ class nsPIDOMWindow;
 #include "nsInterfaceHashtable.h"
 #include "nsIPrincipal.h"
 #include "nsString.h"
 #include "nsWeakPtr.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIObserver.h"
 #include "mozilla/Mutex.h"
+#include "prtime.h"
 #include "DeviceStorage.h"
 
 
 #define POST_ERROR_EVENT_FILE_DOES_NOT_EXIST         "File location doesn't exists"
 #define POST_ERROR_EVENT_FILE_NOT_ENUMERABLE         "File location is not enumerable"
 #define POST_ERROR_EVENT_PERMISSION_DENIED           "Permission Denied"
 #define POST_ERROR_EVENT_ILLEGAL_FILE_NAME           "Illegal file name"
 #define POST_ERROR_EVENT_ILLEGAL_TYPE                "Illegal content type"
@@ -58,18 +59,18 @@ public:
   // we want to make sure that the names of file can't reach
   // outside of the type of storage the user asked for.
   bool IsSafePath();
   bool IsType(nsAString& aType);
 
   nsresult Remove();
   nsresult Write(nsIInputStream* aInputStream);
   nsresult Write(InfallibleTArray<uint8_t>& bits);
-  void CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, uint64_t aSince = 0);
-  void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, uint64_t aSince, nsAString& aRootPath);
+  void CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRTime aSince = 0);
+  void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, PRTime aSince, nsAString& aRootPath);
 
   static void DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar);
 
 private:
   void NormalizeFilePath();
   void AppendRelativePath();
 };
 
@@ -93,22 +94,22 @@ class nsDOMDeviceStorageCursor MOZ_FINAL
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSIDOMDEVICESTORAGECURSOR
 
   nsDOMDeviceStorageCursor(nsIDOMWindow* aWindow,
                            nsIPrincipal* aPrincipal,
                            DeviceStorageFile* aFile,
-                           uint64_t aSince);
+                           PRTime aSince);
 
 
   nsTArray<nsRefPtr<DeviceStorageFile> > mFiles;
   bool mOkToCallContinue;
-  uint64_t mSince;
+  PRTime mSince;
 
   virtual bool Recv__delete__(const bool& allow);
   virtual void IPDLRelease();
 
   void GetStorageType(nsAString & aType);
 
 private:
   ~nsDOMDeviceStorageCursor();
--- a/dom/identity/tests/head_identity.js
+++ b/dom/identity/tests/head_identity.js
@@ -8,18 +8,17 @@ const Cu = SpecialPowers.wrap(Components
 
 SpecialPowers.setBoolPref("toolkit.identity.debug", true);
 SpecialPowers.setBoolPref("dom.identity.enabled", true);
 
 const Services = Cu.import("resource://gre/modules/Services.jsm").Services;
 const DOMIdentity = Cu.import("resource://gre/modules/DOMIdentity.jsm")
                       .DOMIdentity;
 
-let util = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIDOMWindowUtils);
+let util = SpecialPowers.getDOMWindowUtils(window);
 let outerWinId = util.outerWindowID;
 
 const identity = navigator.id || navigator.mozId;
 
 let index = 0;
 
 // mimicking callback funtionality for ease of testing
 // this observer auto-removes itself after the observe function
--- a/dom/interfaces/apps/mozIApplication.idl
+++ b/dom/interfaces/apps/mozIApplication.idl
@@ -6,20 +6,23 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMApplicationRegistry.idl"
 
 /**
  * We expose Gecko-internal helpers related to "web apps" through this
  * sub-interface.
  */
-[scriptable, uuid(764e8930-ff06-4f23-9a6a-8523b93ac09f)]
+[scriptable, uuid(efe22f80-f973-11e1-8a00-b7888ac0d2b9)]
 interface mozIApplication: mozIDOMApplication
 {
   /* Return true if this app has |permission|. */
   boolean hasPermission(in string permission);
 
   /* Application status as defined in nsIPrincipal. */
   readonly attribute unsigned short appStatus;
 
   /* Returns the local id of the app (not the uuid used for sync). */
   readonly attribute unsigned long localId;
+
+  /* Name copied from the manifest */
+  readonly attribute DOMString name;
 };
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -34,17 +34,17 @@ interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 interface nsIDOMClientRect;
 
-[scriptable, uuid(f7222baa-7c4b-4079-a9e0-db13cf797f58)]
+[scriptable, uuid(8A7DA5AF-26FD-4449-8887-9BEADC938B0A)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -916,16 +916,43 @@ interface nsIDOMWindowUtils : nsISupport
    *                 |aOffset|.  Otherwise, set from |aOffset| to
    *                 |aOffset + aLength|.
    * @return True, if succeeded.  Otherwise, false.
    */
   boolean sendSelectionSetEvent(in unsigned long aOffset,
                                 in unsigned long aLength,
                                 in boolean aReverse);
 
+  /* Selection behaviors - mirror nsIFrame's nsSelectionAmount constants */
+  const unsigned long SELECT_CHARACTER   = 0;
+  const unsigned long SELECT_CLUSTER     = 1;
+  const unsigned long SELECT_WORD        = 2;
+  const unsigned long SELECT_LINE        = 3;
+  const unsigned long SELECT_BEGINLINE   = 4;
+  const unsigned long SELECT_ENDLINE     = 5;
+  const unsigned long SELECT_PARAGRAPH   = 6;
+  const unsigned long SELECT_WORDNOSPACE = 7;
+
+  /**
+   * Select content at a client point based on a selection behavior if the
+   * underlying content is selectable. Selection will accumulate with any
+   * existing selection, callers should clear selection prior if needed.
+   * May fire selection changed events. Calls nsFrame's SelectByTypeAtPoint.
+   *
+   * @param aX, aY The selection point in client coordinates.
+   * @param aSelectType The selection behavior requested.
+   * @return True if a selection occured, false otherwise.
+   * @throw NS_ERROR_DOM_SECURITY_ERR, NS_ERROR_UNEXPECTED for utils
+   * issues, and NS_ERROR_INVALID_ARG for coordinates that are outside
+   * this window.
+   */
+  boolean selectAtPoint(in float aX,
+                        in float aY,
+                        in unsigned long aSelectBehavior);
+
   /**
    * Perform the equivalent of:
    *   window.getComputedStyle(aElement, aPseudoElement).
    *     getPropertyValue(aPropertyName)
    * except that, when the link whose presence in history is allowed to
    * influence aElement's style is visited, get the value the property
    * would have if allowed all properties to change as a result of
    * :visited selectors (except for cases where getComputedStyle uses
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -90,16 +90,17 @@
 #endif
 
 #include "mozilla/dom/indexedDB/PIndexedDBChild.h"
 #include "mozilla/dom/sms/SmsChild.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
 
 #include "nsDOMFile.h"
 #include "nsIRemoteBlob.h"
+#include "ProcessUtils.h"
 #include "StructuredCloneUtils.h"
 #include "URIUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsContentUtils.h"
 #include "nsIPrincipal.h"
 
 using namespace base;
 using namespace mozilla::docshell;
@@ -291,16 +292,21 @@ ContentChild::Init(MessageLoop* aIOLoop,
 
     bool startBackground = true;
     SendGetProcessAttributes(&mID, &startBackground,
                              &mIsForApp, &mIsForBrowser);
     hal::SetProcessPriority(
         GetCurrentProcId(),
         startBackground ? hal::PROCESS_PRIORITY_BACKGROUND:
                           hal::PROCESS_PRIORITY_FOREGROUND);
+    if (mIsForApp && !mIsForBrowser) {
+        SetThisProcessName("(App)");
+    } else {
+        SetThisProcessName("Browser");
+    }
 
     return true;
 }
 
 void
 ContentChild::InitXPCOM()
 {
     nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
--- a/dom/ipc/CrashReporterParent.cpp
+++ b/dom/ipc/CrashReporterParent.cpp
@@ -34,24 +34,23 @@ CrashReporterParent::RecvAddLibraryMappi
                                              m.start_address(),
                                              m.mapping_length(),
                                              m.file_offset());
   }
 #endif
   return true;
 }
 
-bool
-CrashReporterParent::RecvAnnotateCrashReport(const nsCString& key,
-                                             const nsCString& data)
+void
+CrashReporterParent::AnnotateCrashReport(const nsCString& key,
+                                         const nsCString& data)
 {
 #ifdef MOZ_CRASHREPORTER
     mNotes.Put(key, data);
 #endif
-    return true;
 }
 
 bool
 CrashReporterParent::RecvAppendAppNotes(const nsCString& data)
 {
     mAppNotes.Append(data);
     return true;
 }
@@ -78,32 +77,16 @@ CrashReporterParent::SetChildData(const 
 {
     mInitialized = true;
     mMainThread = tid;
     mProcessType = processType;
 }
 
 #ifdef MOZ_CRASHREPORTER
 bool
-CrashReporterParent::GenerateHangCrashReport(const AnnotationTable* processNotes)
-{
-    if (mChildDumpID.IsEmpty())
-        return false;
-
-    GenerateChildData(processNotes);
-
-    CrashReporter::AnnotationTable notes;
-    notes.Init(4);
-    notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID));
-    if (!CrashReporter::AppendExtraData(mParentDumpID, notes))
-        NS_WARNING("problem appending parent data to .extra");
-    return true;
-}
-
-bool
 CrashReporterParent::GenerateCrashReportForMinidump(nsIFile* minidump,
     const AnnotationTable* processNotes)
 {
     if (!CrashReporter::GetIDFromMinidump(minidump, mChildDumpID))
         return false;
     return GenerateChildData(processNotes);
 }
 
--- a/dom/ipc/CrashReporterParent.h
+++ b/dom/ipc/CrashReporterParent.h
@@ -29,84 +29,72 @@ public:
   /* Attempt to generate a parent/child pair of minidumps from the given
      toplevel actor in the event of a hang. Returns true if successful,
      false otherwise.
   */
   template<class Toplevel>
   bool
   GeneratePairedMinidump(Toplevel* t);
 
-  /* Attempt to create a bare-bones crash report for a hang, along with extra
-     process-specific annotations present in the given AnnotationTable. Returns
-     true if successful, false otherwise.
-  */
-  bool
-  GenerateHangCrashReport(const AnnotationTable* processNotes);
-
   /* Attempt to create a bare-bones crash report, along with extra process-
      specific annotations present in the given AnnotationTable. Returns true if
      successful, false otherwise.
   */
   template<class Toplevel>
   bool
   GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
 
+  /**
+   * Add the .extra data for an existing crash report.
+   */
+  bool
+  GenerateChildData(const AnnotationTable* processNotes);
+
   bool
   GenerateCrashReportForMinidump(nsIFile* minidump,
                                  const AnnotationTable* processNotes);
 
   /* Instantiate a new crash reporter actor from a given parent that manages
      the protocol.
   */
   template<class Toplevel>
   static bool CreateCrashReporter(Toplevel* actor);
 #endif
   /* Initialize this reporter with data from the child process */
   void
     SetChildData(const NativeThreadId& id, const uint32_t& processType);
 
-  /* Returns the shared hang ID of a parent/child paired minidump.
-     GeneratePairedMinidump must be called first.
-  */
-  const nsString& HangID() {
-    return mHangID;
-  }
-  /* Returns the ID of the parent minidump.
-     GeneratePairedMinidump must be called first.
-  */
-  const nsString& ParentDumpID() {
-    return mParentDumpID;
-  }
   /* Returns the ID of the child minidump.
      GeneratePairedMinidump or GenerateCrashReport must be called first.
   */
   const nsString& ChildDumpID() {
     return mChildDumpID;
   }
 
+  void
+  AnnotateCrashReport(const nsCString& key, const nsCString& data);
+
  protected:
   virtual void ActorDestroy(ActorDestroyReason why);
 
   virtual bool
     RecvAddLibraryMappings(const InfallibleTArray<Mapping>& m);
   virtual bool
-    RecvAnnotateCrashReport(const nsCString& key, const nsCString& data);
+    RecvAnnotateCrashReport(const nsCString& key, const nsCString& data) {
+    AnnotateCrashReport(key, data);
+    return true;
+  }
   virtual bool
     RecvAppendAppNotes(const nsCString& data);
 
 #ifdef MOZ_CRASHREPORTER
-  bool
-  GenerateChildData(const AnnotationTable* processNotes);
-
   AnnotationTable mNotes;
 #endif
   nsCString mAppNotes;
-  nsString mHangID;
   nsString mChildDumpID;
-  nsString mParentDumpID;
   NativeThreadId mMainThread;
   time_t mStartTime;
   uint32_t mProcessType;
   bool mInitialized;
 };
 
 #ifdef MOZ_CRASHREPORTER
 template<class Toplevel>
@@ -115,24 +103,20 @@ CrashReporterParent::GeneratePairedMinid
 {
   CrashReporter::ProcessHandle child;
 #ifdef XP_MACOSX
   child = t->Process()->GetChildTask();
 #else
   child = t->OtherProcess();
 #endif
   nsCOMPtr<nsIFile> childDump;
-  nsCOMPtr<nsIFile> parentDump;
   if (CrashReporter::CreatePairedMinidumps(child,
                                            mMainThread,
-                                           &mHangID,
-                                           getter_AddRefs(childDump),
-                                           getter_AddRefs(parentDump)) &&
-      CrashReporter::GetIDFromMinidump(childDump, mChildDumpID) &&
-      CrashReporter::GetIDFromMinidump(parentDump, mParentDumpID)) {
+                                           getter_AddRefs(childDump)) &&
+      CrashReporter::GetIDFromMinidump(childDump, mChildDumpID)) {
     return true;
   }
   return false;
 }
 
 template<class Toplevel>
 inline bool
 CrashReporterParent::GenerateCrashReport(Toplevel* t,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -18,21 +18,23 @@
 #include "mozilla/dom/PContentChild.h"
 #include "mozilla/dom/PContentDialogChild.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layout/RenderFrameChild.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/unused.h"
+#include "mozIApplication.h"
 #include "nsComponentManagerUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsEmbedCID.h"
 #include "nsEventListenerManager.h"
+#include "nsIAppsService.h"
 #include "nsIBaseWindow.h"
 #include "nsIComponentManager.h"
 #include "nsIDOMClassInfo.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
@@ -672,16 +674,49 @@ TabChild::~TabChild()
       nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(false);
       if (elm) {
         elm->Disconnect();
       }
       mTabChildGlobal->mTabChild = nullptr;
     }
 }
 
+void
+TabChild::SetProcessNameToAppName()
+{
+  if (mIsBrowserElement || (mAppId == nsIScriptSecurityManager::NO_APP_ID)) {
+    return;
+  }
+  nsCOMPtr<nsIAppsService> appsService =
+    do_GetService(APPS_SERVICE_CONTRACTID);
+  if (!appsService) {
+    NS_WARNING("No AppsService");
+    return;
+  }
+  nsresult rv;
+  nsCOMPtr<mozIDOMApplication> domApp;
+  rv = appsService->GetAppByLocalId(mAppId, getter_AddRefs(domApp));
+  if (NS_FAILED(rv) || !domApp) {
+    NS_WARNING("GetAppByLocalId failed");
+    return;
+  }
+  nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
+  if (!app) {
+    NS_WARNING("app isn't a mozIApplication");
+    return;
+  }
+  nsAutoString appName;
+  rv = app->GetName(appName);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to retrieve app name");
+    return;
+  }
+  SetThisProcessName(NS_LossyConvertUTF16toASCII(appName).get());
+}
+
 bool
 TabChild::IsRootContentDocument()
 {
     if (!mIsBrowserElement && mAppId == nsIScriptSecurityManager::NO_APP_ID) {
         // We're the child side of a <xul:browser remote=true>.  This
         // is always a root content document.
         return true;
     }
@@ -693,16 +728,17 @@ TabChild::IsRootContentDocument()
     // bug is fixed, we need to revisit that assumption.
     return false;
 }
 
 bool
 TabChild::RecvLoadURL(const nsCString& uri)
 {
     printf("loading %s, %d\n", uri.get(), NS_IsMainThread());
+    SetProcessNameToAppName();
 
     nsresult rv = mWebNav->LoadURI(NS_ConvertUTF8toUTF16(uri).get(),
                                    nsIWebNavigation::LOAD_FLAGS_NONE,
                                    NULL, NULL, NULL);
     if (NS_FAILED(rv)) {
         NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
     }
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -43,16 +43,17 @@
 #include "nsIPrincipal.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsPIDOMWindow.h"
 #include "nsWeakReference.h"
 #include "nsITabChild.h"
 #include "mozilla/Attributes.h"
 #include "FrameMetrics.h"
+#include "ProcessUtils.h"
 
 struct gfxMatrix;
 
 namespace mozilla {
 namespace layout {
 class RenderFrameChild;
 }
 
@@ -304,16 +305,17 @@ private:
     bool UseDirectCompositor();
 
     void ActorDestroy(ActorDestroyReason why);
 
     enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS };
     bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS);
     bool InitRenderingState();
     void DestroyWindow();
+    void SetProcessNameToAppName();
 
     // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
     void DoFakeShow();
 
     // Wraps up a JSON object as a structured clone and sends it to the browser
     // chrome script.
     //
     // XXX/bug 780335: Do the work the browser chrome script does in C++ instead
--- a/dom/network/tests/marionette/manifest.ini
+++ b/dom/network/tests/marionette/manifest.ini
@@ -1,15 +1,9 @@
-
-[test_mobile_networks.js]
+[DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
+[test_mobile_networks.js]
 [test_mobile_voice_state.js]
-b2g = true
-browser = false
-qemu = true
-
 [test_mobile_iccinfo.js]
-b2g = true
-browser = false
-qemu = true
+[test_mobile_operator_names.js]
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_mobile_operator_names.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+
+SpecialPowers.addPermission("mobileconnection", true, document);
+
+let connection = navigator.mozMobileConnection;
+ok(connection instanceof MozMobileConnection,
+   "connection is instanceof " + connection.constructor);
+
+let voice = connection.voice;
+ok(voice, "voice connection valid");
+
+let network = voice.network;
+ok(network, "voice network info valid");
+
+let emulatorCmdPendingCount = 0;
+function setEmulatorOperatorNames(longName, shortName) {
+  emulatorCmdPendingCount++;
+
+  let cmd = "operator set 0 " + longName + "," + shortName;
+  runEmulatorCmd(cmd, function (result) {
+    emulatorCmdPendingCount--;
+
+    let re = new RegExp("^" + longName + "," + shortName + ",");
+    ok(result[0].match(re), "Long/short name should be changed.");
+  });
+}
+
+function checkValidMccMnc() {
+  is(network.mcc, 310, "network.mcc");
+  is(network.mnc, 260, "network.mnc");
+}
+
+function doTestMobileOperatorNames(longName, shortName, callback) {
+  log("Testing '" + longName + "', '" + shortName + "':");
+
+  checkValidMccMnc();
+
+  connection.addEventListener("voicechange", function onvoicechange() {
+    connection.removeEventListener("voicechange", onvoicechange);
+
+    is(network.longName, longName, "network.longName");
+    is(network.shortName, shortName, "network.shortName");
+
+    checkValidMccMnc();
+
+    setTimeout(callback, 0);
+  });
+
+  setEmulatorOperatorNames(longName, shortName);
+}
+
+function testMobileOperatorNames() {
+  doTestMobileOperatorNames("Mozilla", "B2G", function () {
+    doTestMobileOperatorNames("Mozilla", "", function () {
+      doTestMobileOperatorNames("", "B2G", function () {
+        doTestMobileOperatorNames("", "", function () {
+          doTestMobileOperatorNames("Android", "Android", cleanUp);
+        });
+      });
+    });
+  });
+}
+
+function cleanUp() {
+  if (emulatorCmdPendingCount > 0) {
+    setTimeout(cleanUp, 100);
+    return;
+  }
+
+  SpecialPowers.removePermission("mobileconnection", document);
+  finish();
+}
+
+testMobileOperatorNames();
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -3219,16 +3219,17 @@ nsresult nsPluginInstanceOwner::Init(nsI
   if (objFrame) {
     SetFrame(objFrame);
     // Some plugins require a specific sequence of shutdown and startup when
     // a page is reloaded. Shutdown happens usually when the last instance
     // is destroyed. Here we make sure the plugin instance in the old
     // document is destroyed before we try to create the new one.
     objFrame->PresContext()->EnsureVisible();
   } else {
+    NS_NOTREACHED("Should not be initializing plugin without a frame");
     return NS_ERROR_FAILURE;
   }
 
   // register context menu listener
   mCXMenuListener = new nsPluginDOMContextMenuListener();
   if (mCXMenuListener) {    
     mCXMenuListener->Init(aContent);
   }
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -169,38 +169,34 @@ PluginModuleParent::WriteExtraDataForMin
 
     //TODO: add plugin name and version: bug 539841
     // (as PluginName, PluginVersion)
     notes.Put(CS("PluginName"), CS(""));
     notes.Put(CS("PluginVersion"), CS(""));
 
     CrashReporterParent* crashReporter = CrashReporter();
     if (crashReporter) {
-        const nsString& hangID = crashReporter->HangID();
-        if (!hangID.IsEmpty()) {
-            notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(hangID));
 #ifdef XP_WIN
-            if (mPluginCpuUsageOnHang.Length() > 0) {
-              notes.Put(CS("NumberOfProcessors"),
-                        nsPrintfCString("%d", PR_GetNumberOfProcessors()));
+        if (mPluginCpuUsageOnHang.Length() > 0) {
+            notes.Put(CS("NumberOfProcessors"),
+                      nsPrintfCString("%d", PR_GetNumberOfProcessors()));
 
-              nsCString cpuUsageStr;
-              cpuUsageStr.AppendFloat(std::ceil(mPluginCpuUsageOnHang[0] * 100) / 100);
-              notes.Put(CS("PluginCpuUsage"), cpuUsageStr);
+            nsCString cpuUsageStr;
+            cpuUsageStr.AppendFloat(std::ceil(mPluginCpuUsageOnHang[0] * 100) / 100);
+            notes.Put(CS("PluginCpuUsage"), cpuUsageStr);
 
 #ifdef MOZ_CRASHREPORTER_INJECTOR
-              for (uint32_t i=1; i<mPluginCpuUsageOnHang.Length(); ++i) {
+            for (uint32_t i=1; i<mPluginCpuUsageOnHang.Length(); ++i) {
                 nsCString tempStr;
                 tempStr.AppendFloat(std::ceil(mPluginCpuUsageOnHang[i] * 100) / 100);
                 notes.Put(nsPrintfCString("CpuUsageFlashProcess%d", i), tempStr);
-              }
-#endif
             }
 #endif
         }
+#endif
     }
 }
 #endif  // MOZ_CRASHREPORTER
 
 int
 PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule)
 {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thead!");
@@ -292,24 +288,29 @@ GetProcessCpuUsage(const InfallibleTArra
 } // anonymous namespace
 #endif // #ifdef XP_WIN
 
 bool
 PluginModuleParent::ShouldContinueFromReplyTimeout()
 {
 #ifdef MOZ_CRASHREPORTER
     CrashReporterParent* crashReporter = CrashReporter();
+    crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("PluginHang"),
+                                       NS_LITERAL_CSTRING("1"));
     if (crashReporter->GeneratePairedMinidump(this)) {
-        mBrowserDumpID = crashReporter->ParentDumpID();
         mPluginDumpID = crashReporter->ChildDumpID();
         PLUGIN_LOG_DEBUG(
-                ("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
-                 NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
-                 NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
-                 NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
+                ("generated paired browser/plugin minidumps: %s)",
+                 NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
+
+        crashReporter->AnnotateCrashReport(
+            NS_LITERAL_CSTRING("additional_minidumps"),
+            NS_LITERAL_CSTRING("browser"));
+
+        // TODO: collect Flash minidumps here
     } else {
         NS_WARNING("failed to capture paired minidumps from hang");
     }
 #endif
 
 #ifdef XP_WIN
     // collect cpu usage for plugin processes
 
@@ -372,19 +373,19 @@ PluginModuleParent::ProcessFirstMinidump
 {
     CrashReporterParent* crashReporter = CrashReporter();
     if (!crashReporter)
         return;
 
     AnnotationTable notes;
     notes.Init(4);
     WriteExtraDataForMinidump(notes);
-        
-    if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
-        crashReporter->GenerateHangCrashReport(&notes);
+
+    if (!mPluginDumpID.IsEmpty()) {
+        crashReporter->GenerateChildData(&notes);
         return;
     }
 
     uint32_t sequence = PR_UINT32_MAX;
     nsCOMPtr<nsIFile> dumpFile;
     nsAutoCString flashProcessType;
     TakeMinidump(getter_AddRefs(dumpFile), &sequence);
 
--- a/dom/plugins/test/mochitest/hang_test.js
+++ b/dom/plugins/test/mochitest/hang_test.js
@@ -1,105 +1,82 @@
+
+Components.utils.import("resource://gre/modules/KeyValueParser.jsm");
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 var success = false;
 var observerFired = false;
 
-function parseKeyValuePairs(text) {
-  var lines = text.split('\n');
-  var data = {};
-  for (let i = 0; i < lines.length; i++) {
-    if (lines[i] == '')
-      continue;
-
-    // can't just .split() because the value might contain = characters
-    let eq = lines[i].indexOf('=');
-    if (eq != -1) {
-      let [key, value] = [lines[i].substring(0, eq),
-                          lines[i].substring(eq + 1)];
-      if (key && value)
-        data[key] = value.replace(/\\n/g, "\n").replace(/\\\\/g, "\\");
-    }
-  }
-  return data;
-}
-
-function parseKeyValuePairsFromFile(file) {
-  var fstream = Cc["@mozilla.org/network/file-input-stream;1"].
-                createInstance(Ci.nsIFileInputStream);
-  fstream.init(file, -1, 0, 0);
-  var is = Cc["@mozilla.org/intl/converter-input-stream;1"].
-           createInstance(Ci.nsIConverterInputStream);
-  is.init(fstream, "UTF-8", 1024, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-  var str = {};
-  var contents = '';
-  while (is.readString(4096, str) != 0) {
-    contents += str.value;
-  }
-  is.close();
-  fstream.close();
-  return parseKeyValuePairs(contents);
-}
-
-
 var testObserver = {
   idleHang: true,
 
   observe: function(subject, topic, data) {
     observerFired = true;
     ok(true, "Observer fired");
     is(topic, "plugin-crashed", "Checking correct topic");
     is(data,  null, "Checking null data");
     ok((subject instanceof Ci.nsIPropertyBag2), "got Propbag");
     ok((subject instanceof Ci.nsIWritablePropertyBag2), "got writable Propbag");
 
     var pluginId = subject.getPropertyAsAString("pluginDumpID");
     isnot(pluginId, "", "got a non-empty plugin crash id");
-    var browserId = subject.getPropertyAsAString("browserDumpID");
-    isnot(browserId, "", "got a non-empty browser crash id");
-    
-    // check dump and extra files
+
+    // check plugin dump and extra files
     let directoryService =
       Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
     let profD = directoryService.get("ProfD", Ci.nsIFile);
     profD.append("minidumps");
     let pluginDumpFile = profD.clone();
     pluginDumpFile.append(pluginId + ".dmp");
     ok(pluginDumpFile.exists(), "plugin minidump exists");
-    let browserDumpFile = profD.clone();
-    browserDumpFile.append(browserId + ".dmp");
-    ok(browserDumpFile.exists(), "browser minidump exists");
+
     let pluginExtraFile = profD.clone();
     pluginExtraFile.append(pluginId + ".extra");
     ok(pluginExtraFile.exists(), "plugin extra file exists");
-    let browserExtraFile = profD.clone();
-    browserExtraFile.append(browserId + ".extra");
-    ok(pluginExtraFile.exists(), "browser extra file exists");
-     
+
+    let extraData = parseKeyValuePairsFromFile(pluginExtraFile);
+
+    // check additional dumps
+
+    ok("additional_minidumps" in extraData, "got field for additional minidumps");
+    let additionalDumps = extraData.additional_minidumps.split(',');
+    ok(additionalDumps.indexOf('browser') >= 0, "browser in additional_minidumps");
+
+    let additionalDumpFiles = [];
+    for (let name of additionalDumps) {
+      let file = profD.clone();
+      file.append(pluginId + "-" + name + ".dmp");
+      ok(file.exists(), "additional dump '"+name+"' exists");
+      if (file.exists()) {
+        additionalDumpFiles.push(file);
+      }
+    }
+
     // check cpu usage field
-    let extraData = parseKeyValuePairsFromFile(pluginExtraFile);
+
     ok("PluginCpuUsage" in extraData, "got extra field for plugin cpu usage");
     let cpuUsage = parseFloat(extraData["PluginCpuUsage"]);
     if (this.idleHang) {
       ok(cpuUsage == 0, "plugin cpu usage is 0%");
     } else {
       ok(cpuUsage > 0, "plugin cpu usage is >0%");
     }
-    
+
     // check processor count field
     ok("NumberOfProcessors" in extraData, "got extra field for processor count");
     ok(parseInt(extraData["NumberOfProcessors"]) > 0, "number of processors is >0");
 
     // cleanup, to be nice
     pluginDumpFile.remove(false);
-    browserDumpFile.remove(false);
     pluginExtraFile.remove(false);
-    browserExtraFile.remove(false);
+    for (let file of additionalDumpFiles) {
+      file.remove(false);
+    }
   },
 
   QueryInterface: function(iid) {
     if (iid.equals(Ci.nsIObserver) ||
         iid.equals(Ci.nsISupportsWeakReference) ||
         iid.equals(Ci.nsISupports))
       return this;
     throw Components.results.NS_NOINTERFACE;
--- a/dom/plugins/test/mochitest/test_crashing.html
+++ b/dom/plugins/test/mochitest/test_crashing.html
@@ -1,24 +1,25 @@
 <head>
   <title>Plugin crashing</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 
 <body>
   <script class="testbody" type="application/javascript">
   SimpleTest.waitForExplicitFinish();
 
-  const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
-const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
-  if (isOSXLion || isOSXMtnLion) {
-    todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
-    SimpleTest.finish();
-  }
+  window.frameLoaded = function frameLoaded_toCrash() {
+    const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
+    const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
+    if (isOSXLion || isOSXMtnLion) {
+      todo(false, "Can't test plugin crash notification on OS X 10.7 or 10.8, see bug 705047");
+      SimpleTest.finish();
+      return;
+    }
 
-  window.frameLoaded = function frameLoaded_toCrash() {
     if (!SimpleTest.testPluginIsOOP()) {
       ok(true, "Skipping this test when test plugin is not OOP.");
       SimpleTest.finish();
       return;
     }
 
     SimpleTest.expectChildProcessCrash();
 
--- a/dom/plugins/test/testplugin/nptest.cpp
+++ b/dom/plugins/test/testplugin/nptest.cpp
@@ -1076,18 +1076,20 @@ NPP_SetWindow(NPP instance, NPWindow* wi
   void* oldWindow = instanceData->window.window;
   pluginDoSetWindow(instanceData, window);
   if (instanceData->hasWidget && oldWindow != instanceData->window.window) {
     pluginWidgetInit(instanceData, oldWindow);
   }
 
   if (instanceData->asyncDrawing == AD_BITMAP) {
     if (instanceData->frontBuffer &&
-        instanceData->frontBuffer->size.width == window->width &&
-        instanceData->frontBuffer->size.height == window->height) {
+	instanceData->frontBuffer->size.width >= 0 &&
+       (uint32_t)instanceData->frontBuffer->size.width == window->width &&
+       instanceData ->frontBuffer->size.height >= 0 &&
+       (uint32_t)instanceData->frontBuffer->size.height == window->height) {
           return NPERR_NO_ERROR;
     }
     if (instanceData->frontBuffer) {
       NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer);
       NPN_MemFree(instanceData->frontBuffer);
     }
     if (instanceData->backBuffer) {
       NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer);
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -2669,17 +2669,17 @@ let RIL = {
 
       // According to ril.h, the operator fields will be NULL when the operator
       // is not currently registered. We can avoid trying to parse the numeric
       // tuple in that case.
       if (DEBUG && !longName) {
         debug("Operator is currently unregistered");
       }
 
-      if (longName && shortName && networkTuple) {
+      if (networkTuple) {
         try {
           this._processNetworkTuple(networkTuple, this.operator);
         } catch (e) {
           debug("Error processing operator tuple: " + e);
         }
       }
 
       this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator);
--- a/dom/tests/mochitest/bugs/test_bug260264.html
+++ b/dom/tests/mochitest/bugs/test_bug260264.html
@@ -28,17 +28,16 @@ SimpleTest.waitForExplicitFinish();
 /**
  * These functions can be called without arguments to retrieve the current
  * value of the preference/privilege, or called with a single argument to set
  * the preference/privilege to a new value.
  *
  * In other words, they obey the interface that |hold| expects its |accessor|
  * parameter to obey.
  */
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 var popupMax = makePrefAccessor("dom.popup_maximum"),
     popupEvents = makePrefAccessor("dom.popup_allowed_events"),
     blockPopups = makePrefAccessor("dom.disable_open_during_load"),
     ownPopupPriv = makePopupPrivAccessor(location.href);
 
 var a = $("link"),
     checkOpened = function() { ok(window.open("http://example.com"), "not properly opened") },
     checkBlocked = function() { ok(!window.open("http://example.com"), "not properly blocked") };
@@ -129,17 +128,16 @@ function check_sanity() {
     hold(ownPopupPriv, ALLOW_ACTION, function(allow) {
       is(ownPopupPriv(), allow, "properly set to allow");
     });
     is(ownPopupPriv(), unknown, "properly reset to unknown");
   });
 }
 
 setTimeout(function() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   check_sanity();
   hold(blockPopups, true, run_tests);
   SimpleTest.finish();
 }, 200);
 
 </script>
 </pre>
 </body>
--- a/dom/tests/mochitest/bugs/test_bug534149.html
+++ b/dom/tests/mochitest/bugs/test_bug534149.html
@@ -14,23 +14,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 534149 **/
 function getIDs(iframe) {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   var win = iframe.contentWindow;
   // Force inner creation
   win.document;
 
-  var util = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                .getInterface(Components.interfaces.nsIDOMWindowUtils);
+  var util = SpecialPowers.getDOMWindowUtils(win);
   return [util.outerWindowID, util.currentInnerWindowID];
 }
 
 var i1 = document.createElement("iframe");
 var i2 = document.createElement("iframe");
 
 document.body.appendChild(i1);
 var [i1outer, i1inner] = getIDs(i1);
@@ -41,43 +39,39 @@ var [i2outer, i2inner] = getIDs(i2);
 is(i1inner, i1outer + 1, "For frame 1, inner should come right after outer");
 is(i2inner, i2outer + 1, "For frame 2, inner should come right after outer");
 is(i2outer, i1inner + 1, "Frame 2 comes right after frame 1");
 
 var innerWindowDestroyID;
 var outerWindowDestroyID;
 
 function outerObserver(id) {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   outerWindowDestroyID =
-    id.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
+    SpecialPowers.wrap(id).QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
 }
 function innerObserver(id) {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   innerWindowDestroyID =
-   id.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
+   SpecialPowers.wrap(id).QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
 }
 
 function removeFrame(iframe) {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var obsSvc = Components.classes["@mozilla.org/observer-service;1"]
+  var obsSvc = SpecialPowers.wrap(Components).classes["@mozilla.org/observer-service;1"]
                          .getService(Components.interfaces.nsIObserverService);
   obsSvc.addObserver(outerObserver, "outer-window-destroyed", false);
   obsSvc.addObserver(innerObserver, "inner-window-destroyed", false);
 
   iframe.parentNode.removeChild(iframe);
 }
 
 removeFrame(i1);
 SimpleTest.waitForExplicitFinish();
 SimpleTest.executeSoon(function() {
   is(innerWindowDestroyID, i1inner, "inner window of frame 1 should be destroyed");
   is(outerWindowDestroyID, i1outer, "outer window of frame 1 should be destroyed");
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var obsSvc = Components.classes["@mozilla.org/observer-service;1"]
+  var obsSvc = SpecialPowers.wrap(Components).classes["@mozilla.org/observer-service;1"]
                          .getService(Components.interfaces.nsIObserverService);
   obsSvc.removeObserver(outerObserver, "outer-window-destroyed");
   obsSvc.removeObserver(innerObserver, "inner-window-destroyed");
   SimpleTest.finish();
 });
   
 
 </script>
--- a/dom/tests/mochitest/bugs/test_bug61098.html
+++ b/dom/tests/mochitest/bugs/test_bug61098.html
@@ -46,19 +46,17 @@ function registerMockPromptService()
     {
       // The real prompt service puts the window into a modal state
       // immediately before showing a modal prompt, and leaves the modal state
       // when the prompt is dismissed by the user. This mock prompt doesn't
       // show anything to the user, so we only need to enter and immediately
       // leave the modal state -- this is done to trigger the necessary
       // accounting for triggering the "stop showing more prompts" code for
       // abusive pages.
-      var winUtils = this.domWindow
-                         .QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindowUtils);
+      var winUtils = SpecialPowers.getDOMWindowUtils(this.domWindow);
       var w = winUtils.enterModalStateWithWindow();
       winUtils.leaveModalStateWithWindow(w);
     },
 
     alert: function(aDialogTitle, aText)
     {
       this._toggleModalState();
       promptState = {method: "alert",
--- a/dom/tests/mochitest/bugs/utils_bug260264.js
+++ b/dom/tests/mochitest/bugs/utils_bug260264.js
@@ -47,23 +47,21 @@ function alter_host(uri, host) {
 function alter_file(uri, file) {
   return _alter_helper(uri, function(splat) {
     splat[splat.length - 1] = file;
   });
 }
 
 (function() {
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var prefService = Components.classes["@mozilla.org/preferences-service;1"]
+  var prefService = SpecialPowers.wrap(Components).classes["@mozilla.org/preferences-service;1"]
                               .getService(Components.interfaces.nsIPrefService),
-      pm = Components.classes["@mozilla.org/permissionmanager;1"]
+      pm = SpecialPowers.wrap(Components).classes["@mozilla.org/permissionmanager;1"]
                      .getService(Components.interfaces.nsIPermissionManager),
-      ioService = Components.classes["@mozilla.org/network/io-service;1"]
+      ioService = SpecialPowers.wrap(Components).classes["@mozilla.org/network/io-service;1"]
                             .getService(Components.interfaces.nsIIOService);
 
   ALLOW_ACTION = pm.ALLOW_ACTION;
   DENY_ACTION = pm.DENY_ACTION;
   UNKNOWN_ACTION = pm.UNKNOWN_ACTION;
 
   /**
    * This ridiculously over-engineered function makes an accessor function from
@@ -95,17 +93,17 @@ function alter_file(uri, file) {
       if (arguments.length > 0)
         branch['set' + kind](basePref, value);
       return oldValue;
     };
   };
 
   makePopupPrivAccessor = function(uri) {
     uri = ioService.newURI(uri, null, null);
-    var principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+    var principal = SpecialPowers.wrap(Components).classes["@mozilla.org/scriptsecuritymanager;1"]
                       .getService(Components.interfaces.nsIScriptSecurityManager)
                       .getNoAppCodebasePrincipal(uri);
 
     return function(permission) {
       var old = pm.testPermissionFromPrincipal(principal, "popup");
       if (arguments.length) {
         pm.removeFromPrincipal(principal, "popup");
         pm.addFromPrincipal(principal, "popup", permission);
--- a/dom/tests/mochitest/chrome/Makefile.in
+++ b/dom/tests/mochitest/chrome/Makefile.in
@@ -41,16 +41,18 @@ MOCHITEST_CHROME_FILES = \
 		test_focus_docnav.xul \
 		window_focus_docnav.xul \
 		test_clonewrapper.xul \
 		test_moving_nodeList.xul \
 		test_callback_wrapping.xul \
 		window_callback_wrapping.xul \
 		test_sandbox_postMessage.html \
 		test_sandbox_bindings.xul \
+		test_selectAtPoint.html \
+		selectAtPoint.html \
 		$(NULL)
 
 ifeq (WINNT,$(OS_ARCH))
 MOCHITEST_CHROME_FILES += \
 		test_sizemode_attribute.xul \
 		sizemode_attribute.xul \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/selectAtPoint.html
@@ -0,0 +1,271 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>nsIDOMWindowUtils::selectAtPoint test</title>
+<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+
+<script type="application/javascript;version=1.8">
+  let SimpleTest = window.opener.SimpleTest;
+  let Ci = Components.interfaces;
+
+  function ok() { window.opener.ok.apply(window.opener, arguments); }
+  function done() { window.opener.done.apply(window.opener, arguments); }
+
+  function dumpLn() {
+    for (let idx = 0; idx < arguments.length; idx++)
+      dump(arguments[idx] + " ");
+    dump("\n");
+  }
+
+  function getCharacterDims() {
+    let span = document.getElementById("measure");
+    let rect = span.getBoundingClientRect();
+    return { width: rect.right - rect.left,
+             height: rect.bottom - rect.top }; 
+  }
+
+  function setStart(aDWU, aX, aY, aSelectType)
+  {
+    // Clear any existing selection
+    let selection = document.getSelection();
+    selection.removeAllRanges();
+
+    // Select text
+    let result = aDWU.selectAtPoint(aX, aY, aSelectType);
+    ok(result == true, "selectAtPoint secceeded?");
+  }
+
+  function setEnd(aDWU, aX, aY, aSelectType)
+  {
+    // Select text
+    let result = aDWU.selectAtPoint(aX, aY, aSelectType);
+    ok(result == true, "selectAtPoint secceeded?");
+  }
+
+  function setSingle(aDWU, aX, aY, aSelectType, aSelectTypeStr, aExpectedSelectionText) {
+    // Clear any existing selection
+    let selection = document.getSelection();
+    selection.removeAllRanges();
+
+    // Select text
+    let result = aDWU.selectAtPoint(aX, aY, aSelectType);
+    ok(result == true, "selectAtPoint secceeded?");
+  }
+
+  function checkSelection(aDoc, aSelectTypeStr, aExpectedSelectionText) {
+    // Retrieve text selected
+    let selection = aDoc.getSelection();
+    let text = selection.toString();
+
+    // Test
+    let result = (text == aExpectedSelectionText);
+    ok(result, aSelectTypeStr + " selection text matches?");
+    if (!result) {
+      dumpLn(aSelectTypeStr + " selection text:", "[" + text + "] expected:[" + aExpectedSelectionText + "]" );
+    }
+  }
+
+  function doTest() {
+    let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                    .getInterface(Ci.nsIDOMWindowUtils);
+
+    let os = Components.classes["@mozilla.org/xre/app-info;1"]
+                       .getService(Ci.nsIXULRuntime).OS;
+    let isLinux = (os == "Linux");
+    let isMac = (os == "Darwin");
+    let isWindows = (os == "WINNT");
+
+    if (!isLinux && !isMac && !isWindows) {
+      done();
+      return;
+    }
+
+    window.scrollTo(0, 0);
+
+    // Trick to get character spacing - get the bounds around a
+    // single character trapped in a div.
+    let charDims = getCharacterDims();
+    // dumpLn("character dims:", charDims.width, charDims.height);
+
+    //
+    // Root frame selection
+    //
+
+    // First div in the main page
+
+    let div = document.getElementById("div1");
+    let rect = div.getBoundingClientRect();
+
+    // Centered on the first character in the sentence div
+    let targetPoint = { xPos: rect.left + (charDims.width / 2),
+                        yPos: rect.top + (charDims.height / 2) };
+
+    setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORDNOSPACE);
+    checkSelection(document, "SELECT_WORDNOSPACE", "ttestselection1");
+    setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORD);
+    if (isLinux || isMac) {
+      checkSelection(document, "SELECT_WORD", "ttestselection1");
+    } else if (isWindows) {
+      checkSelection(document, "SELECT_WORD", "ttestselection1 ");
+    }
+    setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_PARAGRAPH);
+    checkSelection(document, "SELECT_PARAGRAPH", "ttestselection1 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos. Ei munere officiis assentior pro, nibh decore ius at.");
+
+    // Centered on the second character in the sentence div
+    let targetPoint = { xPos: rect.left + (charDims.width + (charDims.width / 2)),
+                        yPos: rect.top + (charDims.height / 2) };
+    setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CHARACTER);
+    checkSelection(document, "SELECT_CHARACTER", "te");
+    setSingle(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CLUSTER);
+    checkSelection(document, "SELECT_CLUSTER", "te");
+
+    // Separate character blocks in a word 't(te)s(ts)election1'
+    let targetPoint = { xPos: rect.left + (charDims.width + (charDims.width / 2)),
+                        yPos: rect.top + (charDims.height / 2) };
+    setStart(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CHARACTER);
+    let targetPoint = { xPos: rect.left + ((charDims.width * 4) + (charDims.width / 2)),
+                        yPos: rect.top + (charDims.height / 2) };
+    setEnd(dwu, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_CHARACTER);
+    if (isLinux || isMac) {
+      // XXX I think this is a bug, the right hand selection is 4.5 characters over with a
+      // monspaced font. what we want: t(te)s(ts)election1 what we get: t(te)st(se)lection1
+      checkSelection(document, "split selection", "tese");
+    } else if (isWindows) {
+      checkSelection(document, "split selection", "tets");
+    }
+
+    // Trying to select where there's no text, should fail but not throw
+    let result = dwu.selectAtPoint(rect.left - 20, rect.top - 20, Ci.nsIDOMWindowUtils.SELECT_CHARACTER, false);
+    ok(result == false, "couldn't select?");
+
+    // Second div in the main page
+
+    let div = document.getElementById("div2");
+    let rect = div.getBoundingClientRect();
+
+    // Centered on the first line, first character in the paragraph div
+    let targetPoint = { xPos: rect.left + (charDims.width / 2),
+                        yPos: rect.top + (charDims.height / 2) };
+    setSingle(dwu, targetPoint.xPos + 50, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_PARAGRAPH);
+    checkSelection(document, "SELECT_PARAGRAPH", "Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos.");
+
+    //
+    // Inner IFRAME selection tests
+    //
+
+    let frame = document.getElementById("frame1");
+    let dwuFrame = frame.contentDocument
+                        .defaultView
+                        .QueryInterface(Ci.nsIInterfaceRequestor)
+                        .getInterface(Ci.nsIDOMWindowUtils);
+
+    frame.contentWindow.scrollTo(0, 0);
+
+    let rect = frame.getBoundingClientRect();
+
+    let targetPoint = { xPos: rect.left + (charDims.width / 2),
+                        yPos: rect.top + (charDims.height / 2) };
+    setSingle(dwuFrame, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORDNOSPACE);
+    checkSelection(frame.contentWindow.document, "SELECT_WORDNOSPACE", "ttestselection2");
+    setSingle(dwuFrame, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_WORD);
+    if (isLinux || isMac) {
+      checkSelection(frame.contentWindow.document, "SELECT_WORD", "ttestselection2");
+    } else if (isWindows) {
+      checkSelection(frame.contentWindow.document, "SELECT_WORD", "ttestselection2 ");
+    }
+    setSingle(dwuFrame, targetPoint.xPos, targetPoint.yPos, Ci.nsIDOMWindowUtils.SELECT_PARAGRAPH);
+    checkSelection(frame.contentWindow.document, "SELECT_PARAGRAPH", "ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.");
+
+    // Outside the frame should throw. This is a failure in coordinate setup of
+    // nsDOMWindowUtils::SelectAtPoint.
+    let thr = false;
+    try {
+      dwuFrame.selectAtPoint(rect.right + 50, rect.top, Ci.nsIDOMWindowUtils.SELECT_WORD, false);
+    } catch (ex)  { thr = true; }
+    ok(thr == true, "selectAtPoint expected throw?");
+    
+    done();
+  }
+
+  let frameLoad = false;
+  let pageLoad = false;
+  let painted = false;
+  function testReady() {
+    if (frameLoad && pageLoad && painted) 
+      doTest();
+  }
+
+  function onFrameLoad() {
+    frameLoad = true;
+    testReady();
+  }
+
+  function onPageLoad() {
+    pageLoad = true;
+    testReady();
+  }
+
+  function onPaint() {
+    window.removeEventListener("MozAfterPaint", onPaint, false);
+    painted = true;
+    testReady();
+  }
+
+  window.addEventListener("MozAfterPaint", onPaint, false);
+</script>
+
+<style type="text/css">
+
+body {
+  font-family: monospace;
+  margin-left: 40px;
+  margin-top: 40px;
+  padding: 0;
+}
+
+#div1 {
+  border: 1px solid red;
+  width: 400px;
+  height: 100px;
+}
+
+#frame1 {
+  display: block;
+  height: 100px;
+  width: 300px;
+  border: 1px solid blue;
+  padding: 0;
+  margin: 0;
+}
+
+#div2 {
+  border: 1px solid green;
+}
+
+#measure {
+  padding: 0px;
+  margin: 0px;
+  border: 1px solid red;
+}
+
+</style>
+</head>
+<body id="body" onload="onPageLoad();">
+
+<div id="div1">ttestselection1 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos. Ei munere officiis assentior pro, nibh decore ius at.</div>
+
+<br />
+
+<iframe id="frame1" src="data:text/html,<html><body style='margin: 0; padding: 0; font-family: monospace;' onload='window.parent.onFrameLoad();'><div id='sel2'>ttestselection2 Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut.</div><br/><br/></body></html>"></iframe>
+
+<br/>
+
+<div id="div2">Lorem ipsum dolor sit amet, at duo debet graeci, vivendum vulputate per ut. Ne labore incorrupte vix. Cu copiosae postulant tincidunt ius, in illud appetere contentiones eos.</div>
+
+<br />
+
+<span id="measure">t</span>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_selectAtPoint.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>nsIDOMWindowUtils::selectAtPoint test</title>
+  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+<script type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+  function done() {
+    testwindow.close();
+    SimpleTest.finish();
+  }
+  var testwindow = window.open("selectAtPoint.html", '_new', 'width=800,height=800');
+</script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</body>
+</html>
+
--- a/dom/tests/mochitest/general/test_domWindowUtils.html
+++ b/dom/tests/mochitest/general/test_domWindowUtils.html
@@ -20,20 +20,17 @@
 
 <body id="body">
 
 <div class="test" id="onscreen" style="top: 100px; background-color: red;"></div>
 <div class="test" id="offscreen" style="top: 100000px; background-color: green;"></div>
 
 <script type="application/javascript;version=1.8">
 
-// Enable privileges so we can use nsIDOMWindowUtils interface
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-var domWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                           .getInterface(Components.interfaces.nsIDOMWindowUtils);
+var domWindowUtils = SpecialPowers.getDOMWindowUtils(window);
 
 /*
   nsIDOMElement elementFromPoint(in long aX,
                                  in long aY,
                                  in boolean aIgnoreRootScrollFrame,
                                  in boolean aFlushLayout);
 */
 function testElementFromPoint() {
--- a/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html
+++ b/dom/tests/mochitest/general/test_domWindowUtils_scrollXY.html
@@ -19,22 +19,19 @@
     function doTests() {
       testScrollXY();
       testHiddenIframe();
 
       SimpleTest.finish();
     }
 
     function testScrollXY() {
-      // Enable privileges so we can use nsIDOMWindowUtils interface
-      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
       let iframe = document.getElementById("iframe");
       let cwindow = iframe.contentWindow;
-      let domWindowUtils = cwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                                  .getInterface(Components.interfaces.nsIDOMWindowUtils);
+      let domWindowUtils = SpecialPowers.getDOMWindowUtils(cwindow);
 
       function checkGetScrollXYState(flush, vals, testName) {
         let scrollX = {}, scrollY = {};
         domWindowUtils.getScrollXY(flush, scrollX, scrollY);
         is(scrollX.value, vals[0], "getScrollXY x for test: " + testName);
         is(scrollY.value, vals[1], "getScrollXY y for test: " + testName);
       }
 
@@ -59,18 +56,17 @@
       cwindow.document.body.style.height = 'auto';
       checkGetScrollXYState(false, [900, 1000], "didn't flush layout for getScrollXY");
       checkGetScrollXYState(true, [0, 0], "flushed layout for getScrollXY");
     }
 
     function testHiddenIframe() {
       let iframe = document.getElementById("hidden-iframe");
       let cwindow = iframe.contentWindow;
-      let domWindowUtils = cwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                                  .getInterface(Components.interfaces.nsIDOMWindowUtils);
+      let domWindowUtils = SpecialPowers.getDOMWindowUtils(cwindow);
 
       // make sure getScrollXY doesn't throw
       let scrollX = {}, scrollY = {};
       domWindowUtils.getScrollXY(false, scrollX, scrollY);
 
       is(scrollX.value, 0, "scrollX is zero for display:none iframe");
       is(scrollY.value, 0, "scrollY is zero for display:none iframe");
     }
--- a/dom/tests/mochitest/localstorage/frameQuotaSessionOnly.html
+++ b/dom/tests/mochitest/localstorage/frameQuotaSessionOnly.html
@@ -1,38 +1,37 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <title>slave for sessionStorage test</title>
 
 <script type="text/javascript" src="interOriginFrame.js"></script>
 <script type="text/javascript">
 
 const DOM_QUOTA_REACHED = 2152924150;
+const Cc = SpecialPowers.wrap(Components).classes;
 
 function checkException(func, exc)
 {
   var exceptionThrew = false;
   try {
     func();
   }
   catch (ex) {
     exceptionThrew = true;
     is(ex.result, exc, "Expected "+exc+" exception");
   }
   ok(exceptionThrew, "Exception "+exc+" threw at "+location);
 }
 
 function doStep()
 {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var io = Components.classes["@mozilla.org/network/io-service;1"]
+  var io = Cc["@mozilla.org/network/io-service;1"]
     .getService(Components.interfaces.nsIIOService);
   var uri = io.newURI(window.location, "", null);
-  var cp = Components.classes["@mozilla.org/cookie/permission;1"]
+  var cp = Cc["@mozilla.org/cookie/permission;1"]
     .getService(Components.interfaces.nsICookiePermission);
 
   cp.setAccess(uri, Components.interfaces.nsICookiePermission.ACCESS_SESSION);
 
   var query = location.search.substring(1);
   var queries = query.split("&");
 
   var operation = queries[0];
--- a/dom/tests/mochitest/localstorage/test_cookieBlock.html
+++ b/dom/tests/mochitest/localstorage/test_cookieBlock.html
@@ -4,22 +4,20 @@
 
 <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">
 
 function startTest()
 {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var io = Components.classes["@mozilla.org/network/io-service;1"]
+  var io = SpecialPowers.wrap(Components).classes["@mozilla.org/network/io-service;1"]
     .getService(Components.interfaces.nsIIOService);
   var uri = io.newURI(window.location, "", null);
-  var cp = Components.classes["@mozilla.org/cookie/permission;1"]
+  var cp = SpecialPowers.wrap(Components).classes["@mozilla.org/cookie/permission;1"]
     .getService(Components.interfaces.nsICookiePermission);
 
   cp.setAccess(uri, Components.interfaces.nsICookiePermission.ACCESS_DENY);
 
   try {
     localStorage.setItem("blocked", "blockedvalue");
     ok(false, "Exception for localStorage.setItem, ACCESS_DENY");
   }
--- a/dom/tests/mochitest/localstorage/test_cookieSession-phase1.html
+++ b/dom/tests/mochitest/localstorage/test_cookieSession-phase1.html
@@ -14,22 +14,20 @@
   storage.
  */
 
 function startTest()
 {
   localStorage.setItem("persistent1", "persistent value 1");
   localStorage.setItem("persistent2", "persistent value 2");
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var io = Components.classes["@mozilla.org/network/io-service;1"]
+  var io = SpecialPowers.wrap(Components).classes["@mozilla.org/network/io-service;1"]
     .getService(Components.interfaces.nsIIOService);
   var uri = io.newURI(window.location, "", null);
-  var cp = Components.classes["@mozilla.org/cookie/permission;1"]
+  var cp = SpecialPowers.wrap(Components).classes["@mozilla.org/cookie/permission;1"]
     .getService(Components.interfaces.nsICookiePermission);
   cp.setAccess(uri, Components.interfaces.nsICookiePermission.ACCESS_SESSION);
 
   localStorage.setItem("session only", "session value");
   is(localStorage.getItem("session only"), "session value");
   is(localStorage.getItem("persistent1"), "persistent value 1");
   is(localStorage.getItem("persistent2"), "persistent value 2");
 
--- a/dom/tests/mochitest/localstorage/test_cookieSession-phase2.html
+++ b/dom/tests/mochitest/localstorage/test_cookieSession-phase2.html
@@ -4,22 +4,20 @@
 
 <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">
 
 function startTest()
 {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var io = Components.classes["@mozilla.org/network/io-service;1"]
+  var io = SpecialPowers.wrap(Components).classes["@mozilla.org/network/io-service;1"]
     .getService(Components.interfaces.nsIIOService);
   var uri = io.newURI(window.location, "", null);
-  var cp = Components.classes["@mozilla.org/cookie/permission;1"]
+  var cp = SpecialPowers.wrap(Components).classes["@mozilla.org/cookie/permission;1"]
     .getService(Components.interfaces.nsICookiePermission);
 
   is(localStorage.getItem("session only"), "session value", "Value present when cookies in session-only mode");
   is(localStorage.getItem("persistent1"), "persistent value 1", "Persistent value present");
   is(localStorage.getItem("persistent2"), "persistent value 2", "Persistent value present");
 
   localStorage.setItem("persistent1", "changed persistent value 1");
   localStorage.removeItem("persistent2");
--- a/dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html
@@ -2,19 +2,17 @@
 <head>
 <title>localStorage cookies settings test</title>
 
 <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">
 
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
+window.Services = SpecialPowers.Services;
 
 // Set cookies behavior to "always reject".
 Services.prefs.setIntPref("network.cookie.cookieBehavior", 2);
 try {
   localStorage.setItem("contentkey", "test-value");
   ok(false, "Setting localStorageItem should throw a security exception");
 }
 catch(ex) {
--- a/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly2.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly2.html
@@ -3,64 +3,62 @@
 <title>localStorage and DOM quota test</title>
 
 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 <script type="text/javascript" src="interOriginTest.js"></script>
 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
 <script type="text/javascript">
 
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+const Cc = SpecialPowers.wrap(Components).classes;
 
 var currentTest = 1;
-var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+var prefs = Cc["@mozilla.org/preferences-service;1"]
             .getService(Components.interfaces.nsIPrefBranch);
-var io = Components.classes["@mozilla.org/network/io-service;1"]
+var io = Cc["@mozilla.org/network/io-service;1"]
   .getService(Components.interfaces.nsIIOService);
 var uri = io.newURI(window.location, "", null);
-var cp = Components.classes["@mozilla.org/cookie/permission;1"]
+var cp = Cc["@mozilla.org/cookie/permission;1"]
   .getService(Components.interfaces.nsICookiePermission);
 
 var quota, quotaOffline;
 
 function addOfflineApp(url)
 {
-  var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
+  var permissionManager = Cc["@mozilla.org/permissionmanager;1"]
     .getService(Components.interfaces.nsIPermissionManager);
-  var uri = Components.classes["@mozilla.org/network/io-service;1"]
+  var uri = Cc["@mozilla.org/network/io-service;1"]
     .getService(Components.interfaces.nsIIOService)
     .newURI(url, null, null);
-  var principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+  var principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
                     .getService(Components.interfaces.nsIScriptSecurityManager)
                     .getNoAppCodebasePrincipal(uri);
 
   permissionManager.addFromPrincipal(principal, "offline-app",
                                      Components.interfaces.nsIPermissionManager.ALLOW_ACTION);
 }
 
 function removeOfflineApp(url)
 {
-  var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
+  var permissionManager = Cc["@mozilla.org/permissionmanager;1"]
     .getService(Components.interfaces.nsIPermissionManager);
-  var uri = Components.classes["@mozilla.org/network/io-service;1"]
+  var uri = Cc["@mozilla.org/network/io-service;1"]
     .getService(Components.interfaces.nsIIOService)
     .newURI(url, null, null);
-  var principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+  var principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
                     .getService(Components.interfaces.nsIScriptSecurityManager)
                     .getNoAppCodebasePrincipal(uri);
 
   permissionManager.removeFromPrincipal(principal, "offline-app");
 }
 
 function doNextTest()
 {
   slave = frame;
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
   switch (currentTest)
   {
     // Initialy setup the quota to testing value of 1024B and
     // set a 500 bytes key with name length 1 (allocate 501 bytes)
     case 1:
       try {
         quota = prefs.getIntPref("dom.storage.default_quota");
       } catch (ex) {
new file mode 100644
--- /dev/null
+++ b/dom/webidl/Blob.webidl
@@ -0,0 +1,37 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/2006/webapi/FileAPI/#blob
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+/*
+[Constructor, Constructor((ArrayBuffer or ArrayBufferView or Blob or DOMString)[] blobParts, optional BlobPropertyBag options)] 
+interface Blob {
+
+  readonly attribute unsigned long long size;
+  readonly attribute DOMString type;
+
+  //slice Blob into byte-ranged chunks
+
+  Blob slice(optional long long start,
+             optional long long end,
+             optional DOMString contentType);
+  void close(); 
+
+};
+*/
+
+enum EndingTypes{"transparent", "native"};
+
+dictionary BlobPropertyBag {
+
+  DOMString type = "";
+  EndingTypes endings = "transparent";
+
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -5,24 +5,26 @@
 webidl_base = $(topsrcdir)/dom/webidl
 
 generated_webidl_files = \
   CSS2Properties.webidl \
   $(NULL)
 
 webidl_files = \
   AudioContext.webidl \
+  Blob.webidl \
   CanvasRenderingContext2D.webidl \
   CSSStyleDeclaration.webidl \
   Function.webidl \
   EventListener.webidl \
   EventTarget.webidl \
   Performance.webidl \
   PerformanceNavigation.webidl \
   PerformanceTiming.webidl \
+  WebSocket.webidl \
   XMLHttpRequest.webidl \
   XMLHttpRequestEventTarget.webidl \
   XMLHttpRequestUpload.webidl \
   $(NULL)
 
 ifdef MOZ_WEBGL
 webidl_files += \
   WebGLRenderingContext.webidl \
new file mode 100644
--- /dev/null
+++ b/dom/webidl/WebSocket.webidl
@@ -0,0 +1,69 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/html/#network
+ *
+ * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera Software ASA.
+ * You are granted a license to use, reproduce and create derivative works of this document.
+ */
+
+enum BinaryType { "blob", "arraybuffer" };
+
+[PrefControlled,
+ Constructor(DOMString url),
+ Constructor(DOMString url, DOMString protocols),
+ Constructor(DOMString url, sequence<DOMString> protocols)]
+interface WebSocket : EventTarget {
+
+  readonly attribute DOMString url;
+
+  // ready state
+  const unsigned short CONNECTING = 0;
+  const unsigned short OPEN = 1;
+  const unsigned short CLOSING = 2;
+  const unsigned short CLOSED = 3;
+
+  readonly attribute unsigned short readyState;
+
+  readonly attribute unsigned long bufferedAmount;
+
+  // networking
+
+  [TreatNonCallableAsNull, SetterThrows]
+  attribute Function? onopen;
+
+  [TreatNonCallableAsNull, SetterThrows]
+  attribute Function? onerror;
+
+  [TreatNonCallableAsNull, SetterThrows]
+  attribute Function? onclose;
+
+  readonly attribute DOMString extensions;
+
+  readonly attribute DOMString protocol;
+
+  [Throws]
+  void close([Clamp] optional unsigned short code, optional DOMString reason);
+
+  // messaging
+
+  [TreatNonCallableAsNull, SetterThrows]
+  attribute Function? onmessage;
+
+  attribute BinaryType binaryType;
+
+  [Throws]
+  void send(DOMString data);
+
+  [Throws]
+  void send(Blob data);
+
+  [Throws]
+  void send(ArrayBuffer data);
+
+  [Throws]
+  void send(ArrayBufferView data);
+};
--- a/dom/workers/test/test_blobConstructor.html
+++ b/dom/workers/test/test_blobConstructor.html
@@ -21,27 +21,28 @@ Tests of DOM Worker Blob constructor
 <script class="testbody" type="text/javascript">
 (function() {
   onerror = function(e) {
     ok(false, "Main Thread had an error: " + event.data);
     SimpleTest.finish();
   };
   function f() {
     onmessage = function(e) {
-      var b = new Blob([e.data, "World"],{});
+      var b = new Blob([e.data, "World"],{type: "text/plain"});
       var fr = new FileReaderSync();
-      postMessage(fr.readAsText(b));
+      postMessage({text: fr.readAsText(b), type: b.type});
     };
   }
   var b = new Blob([f,"f();"]);
   var u = URL.createObjectURL(b);
   var w = new Worker(u);
   w.onmessage = function(e) {
     URL.revokeObjectURL(u);
-    is(e.data, fr.result);
+    is(e.data.text, fr.result);
+    is(e.data.type, "text/plain");
     SimpleTest.finish();
   };
   w.onerror = function(e) {
     is(e.target, w);
     ok(false, "Worker had an error: " + e.data);
     SimpleTest.finish();
   };
 
--- a/editor/libeditor/html/tests/test_root_element_replacement.html
+++ b/editor/libeditor/html/tests/test_root_element_replacement.html
@@ -84,19 +84,17 @@ function onLoadIFrame()
   var frameDoc = gIFrame.contentWindow.document;
 
   var selCon = SpecialPowers.wrap(gIFrame).contentWindow.
     QueryInterface(Components.interfaces.nsIInterfaceRequestor).
     getInterface(Components.interfaces.nsIWebNavigation).
     QueryInterface(Components.interfaces.nsIInterfaceRequestor).
     getInterface(Components.interfaces.nsISelectionDisplay).
     QueryInterface(Components.interfaces.nsISelectionController);
-  var utils = window.
-    QueryInterface(Components.interfaces.nsIInterfaceRequestor).
-    getInterface(Components.interfaces.nsIDOMWindowUtils);
+  var utils = SpecialPowers.getDOMWindowUtils(window);
   const nsIDOMNode = Components.interfaces.nsIDOMNode;
 
   // move focus to the HTML editor
   const kTest = kTests[gTestIndex];
   ok(true, "Running " + kTest.description);
   if (kTest.args.length == 1) {
     kTest.initializer(frameDoc, gSetFocusToIFrame, kTest.args[0]);
     ok(selCon.caretVisible, "caret isn't visible -- " + kTest.description);
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -95,16 +95,121 @@ ToOutsideIntRect(const gfxRect &aRect)
 static nsIntRect
 ToInsideIntRect(const gfxRect& aRect)
 {
   gfxRect r = aRect;
   r.RoundIn();
   return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
 }
 
+// A context helper for BasicLayerManager::PaintLayer() that holds all the
+// painting context together in a data structure so it can be easily passed
+// around. It also uses ensures that the Transform and Opaque rect are restored
+// to their former state on destruction.
+
+class PaintContext {
+public:
+  PaintContext(gfxContext* aTarget, Layer* aLayer,
+               LayerManager::DrawThebesLayerCallback aCallback,
+               void* aCallbackData, ReadbackProcessor* aReadback)
+   : mTarget(aTarget)
+   , mTargetMatrixSR(aTarget)
+   , mLayer(aLayer)
+   , mCallback(aCallback)
+   , mCallbackData(aCallbackData)
+   , mReadback(aReadback)
+   , mPushedOpaqueRect(false)
+  {}
+
+  ~PaintContext()
+  {
+    // Matrix is restored by mTargetMatrixSR
+    if (mPushedOpaqueRect)
+    {
+      ClearOpaqueRect();
+    }
+  }
+
+  // Applies the effective 2D transform and returns true if it is a 2D
+  // transform. If it's a 3D transform then it applies an identity and returns
+  // false.
+  bool Apply2DTransform()
+  {
+    const gfx3DMatrix& effectiveTransform = mLayer->GetEffectiveTransform();
+
+    // Will return an identity matrix for 3d transforms.
+    bool is2D = effectiveTransform.CanDraw2D(&mTransform);
+    mTarget->SetMatrix(mTransform);
+
+    return is2D;
+  }
+
+  // Set the opaque rect to match the bounds of the visible region.
+  void AnnotateOpaqueRect()
+  {
+    const nsIntRegion& visibleRegion = mLayer->GetEffectiveVisibleRegion();
+    const nsIntRect& bounds = visibleRegion.GetBounds();
+    nsRefPtr<gfxASurface> currentSurface = mTarget->CurrentSurface();
+
+    if (mTarget->IsCairo()) {
+      const gfxRect& targetOpaqueRect = currentSurface->GetOpaqueRect();
+
+      // Try to annotate currentSurface with a region of pixels that have been
+      // (or will be) painted opaque, if no such region is currently set.
+      if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
+          (mLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
+          !mTransform.HasNonAxisAlignedTransform()) {
+        currentSurface->SetOpaqueRect(
+            mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height)));
+        mPushedOpaqueRect = true;
+      }
+    } else {
+      DrawTarget *dt = mTarget->GetDrawTarget();
+      const IntRect& targetOpaqueRect = dt->GetOpaqueRect();
+
+      // Try to annotate currentSurface with a region of pixels that have been
+      // (or will be) painted opaque, if no such region is currently set.
+      if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
+          (mLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
+          !mTransform.HasNonAxisAlignedTransform()) {
+
+        gfx::Rect opaqueRect = dt->GetTransform().TransformBounds(
+          gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height));
+        opaqueRect.RoundIn();
+        IntRect intOpaqueRect;
+        if (opaqueRect.ToIntRect(&intOpaqueRect)) {
+          mTarget->GetDrawTarget()->SetOpaqueRect(intOpaqueRect);
+          mPushedOpaqueRect = true;
+        }
+      }
+    }
+  }
+
+  // Clear the Opaque rect. Although this doesn't really restore it to it's
+  // previous state it will happen on the exit path of the PaintLayer() so when
+  // painting is complete the opaque rect qill be clear.
+  void ClearOpaqueRect() {
+    if (mTarget->IsCairo()) {
+      nsRefPtr<gfxASurface> currentSurface = mTarget->CurrentSurface();
+      currentSurface->SetOpaqueRect(gfxRect());
+    } else {
+      mTarget->GetDrawTarget()->SetOpaqueRect(IntRect());
+    }
+  }
+
+  gfxContext* mTarget;
+  gfxContextMatrixAutoSaveRestore mTargetMatrixSR;
+  Layer* mLayer;
+  LayerManager::DrawThebesLayerCallback mCallback;
+  void* mCallbackData;
+  ReadbackProcessor* mReadback;
+  gfxMatrix mTransform;
+  bool mPushedOpaqueRect;
+};
+
 BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
 #ifdef DEBUG
   mPhase(PHASE_NONE),
 #endif
   mWidget(aWidget)
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
   , mCachedSurfaceInUse(false)
   , mTransactionIncomplete(false)
@@ -685,252 +790,194 @@ Transform3D(gfxASurface* aSource, gfxCon
   }
 
   // If we haven't actually drawn to aDest then return our temporary image so that
   // the caller can do this.
   aDrawOffset = destRect.TopLeft();
   return destImage.forget(); 
 }
 
+void
+BasicLayerManager::PaintSelfOrChildren(PaintContext& aPaintContext,
+                                       gfxContext* aGroupTarget)
+{
+  BasicImplData* data = ToData(aPaintContext.mLayer);
 
+  if (aPaintContext.mLayer->GetFirstChild() &&
+      aPaintContext.mLayer->GetMaskLayer() &&
+      HasShadowManager()) {
+    // 'paint' the mask so that it gets sent to the shadow layer tree
+    static_cast<BasicImplData*>(aPaintContext.mLayer->GetMaskLayer()->ImplData())
+      ->Paint(nullptr, nullptr);
+  }
+
+  /* Only paint ourself, or our children - This optimization relies on this! */
+  Layer* child = aPaintContext.mLayer->GetFirstChild();
+  if (!child) {
+    if (aPaintContext.mLayer->AsThebesLayer()) {
+      data->PaintThebes(aGroupTarget, aPaintContext.mLayer->GetMaskLayer(),
+          aPaintContext.mCallback, aPaintContext.mCallbackData,
+          aPaintContext.mReadback);
+    } else {
+      data->Paint(aGroupTarget, aPaintContext.mLayer->GetMaskLayer());
+    }
+  } else {
+    ReadbackProcessor readback;
+    ContainerLayer* container =
+        static_cast<ContainerLayer*>(aPaintContext.mLayer);
+    if (IsRetained()) {
+      readback.BuildUpdates(container);
+    }
+    nsAutoTArray<Layer*, 12> children;
+    container->SortChildrenBy3DZOrder(children);
+    for (uint32_t i = 0; i < children.Length(); i++) {
+      PaintLayer(aGroupTarget, children.ElementAt(i), aPaintContext.mCallback,
+          aPaintContext.mCallbackData, &readback);
+      if (mTransactionIncomplete)
+        break;
+    }
+  }
+}
+
+void
+BasicLayerManager::FlushGroup(PaintContext& aPaintContext, bool aNeedsClipToVisibleRegion)
+{
+  // If we're doing our own double-buffering, we need to avoid drawing
+  // the results of an incomplete transaction to the destination surface ---
+  // that could cause flicker. Double-buffering is implemented using a
+  // temporary surface for one or more container layers, so we need to stop
+  // those temporary surfaces from being composited to aTarget.
+  // ApplyDoubleBuffering guarantees that this container layer can't
+  // intersect any other leaf layers, so if the transaction is not yet marked
+  // incomplete, the contents of this container layer are the final contents
+  // for the window.
+  if (!mTransactionIncomplete) {
+    if (aNeedsClipToVisibleRegion) {
+      gfxUtils::ClipToRegion(aPaintContext.mTarget,
+                             aPaintContext.mLayer->GetEffectiveVisibleRegion());
+    }
+    BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aPaintContext.mLayer);
+    AutoSetOperator setOperator(aPaintContext.mTarget, container->GetOperator());
+    PaintWithMask(aPaintContext.mTarget, aPaintContext.mLayer->GetEffectiveOpacity(),
+                  HasShadowManager() ? nullptr : aPaintContext.mLayer->GetMaskLayer());
+  }
+}
 
 void
 BasicLayerManager::PaintLayer(gfxContext* aTarget,
                               Layer* aLayer,
                               DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               ReadbackProcessor* aReadback)
 {
+  PaintContext paintContext(aTarget, aLayer, aCallback, aCallbackData, aReadback);
+
   RenderTraceScope trace("BasicLayerManager::PaintLayer", "707070");
 
   const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
-  const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
   // aLayer might not be a container layer, but if so we take care not to use
   // the container variable
   BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aLayer);
   bool needsGroup = aLayer->GetFirstChild() &&
                     container->UseIntermediateSurface();
   BasicImplData* data = ToData(aLayer);
   bool needsClipToVisibleRegion =
     data->GetClipToVisibleRegion() && !aLayer->AsThebesLayer();
   NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() ||
                container->GetOperator() == gfxContext::OPERATOR_OVER,
                "non-OVER operator should have forced UseIntermediateSurface");
   NS_ASSERTION(!aLayer->GetFirstChild() || !aLayer->GetMaskLayer() ||
                container->UseIntermediateSurface(),
                "ContainerLayer with mask layer should force UseIntermediateSurface");
 
-  // If needsSaveRestore is false, we should still save and restore
-  // the CTM
+  gfxContextAutoSaveRestore contextSR;
   bool needsSaveRestore = needsGroup || clipRect || needsClipToVisibleRegion;
-  gfxMatrix savedMatrix;
   if (needsSaveRestore) {
-    aTarget->Save();
+    contextSR.SetContext(aTarget);
 
     if (clipRect) {
       aTarget->NewPath();
       aTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), true);
       aTarget->Clip();
     }
   }
-  savedMatrix = aTarget->CurrentMatrix();
 
-  gfxMatrix transform;
-  // Will return an identity matrix for 3d transforms, and is handled separately below.
-  bool is2D = effectiveTransform.CanDraw2D(&transform);
+  bool is2D = paintContext.Apply2DTransform();
   NS_ABORT_IF_FALSE(is2D || needsGroup || !aLayer->GetFirstChild(), "Must PushGroup for 3d transforms!");
-  if (is2D) {
-    aTarget->SetMatrix(transform);
-  } else {
-    aTarget->SetMatrix(gfxMatrix());
-  }
 
   const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
   // If needsGroup is true, we'll clip to the visible region after we've popped the group
   if (needsClipToVisibleRegion && !needsGroup) {
     gfxUtils::ClipToRegion(aTarget, visibleRegion);
     // Don't need to clip to visible region again
     needsClipToVisibleRegion = false;
   }
-
-  bool pushedTargetOpaqueRect = false;
-  nsRefPtr<gfxASurface> currentSurface = aTarget->CurrentSurface();
-  DrawTarget *dt = aTarget->GetDrawTarget();
-  const nsIntRect& bounds = visibleRegion.GetBounds();
   
   if (is2D) {
-    if (aTarget->IsCairo()) {
-      const gfxRect& targetOpaqueRect = currentSurface->GetOpaqueRect();
-
-      // Try to annotate currentSurface with a region of pixels that have been
-      // (or will be) painted opaque, if no such region is currently set.
-      if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
-          (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
-          !transform.HasNonAxisAlignedTransform()) {
-        currentSurface->SetOpaqueRect(
-            aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height)));
-        pushedTargetOpaqueRect = true;
-      }
-    } else {
-      const IntRect& targetOpaqueRect = dt->GetOpaqueRect();
+    paintContext.AnnotateOpaqueRect();
+  }
 
-      // Try to annotate currentSurface with a region of pixels that have been
-      // (or will be) painted opaque, if no such region is currently set.
-      if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
-          (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
-          !transform.HasNonAxisAlignedTransform()) {
-
-        gfx::Rect opaqueRect = dt->GetTransform().TransformBounds(
-          gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height));
-        opaqueRect.RoundIn();
-        IntRect intOpaqueRect;
-        if (opaqueRect.ToIntRect(&intOpaqueRect)) {
-          aTarget->GetDrawTarget()->SetOpaqueRect(intOpaqueRect);
-          pushedTargetOpaqueRect = true;
-        }
-      }
-    }
+  bool clipIsEmpty = !aTarget || aTarget->GetClipExtents().IsEmpty();
+  if (clipIsEmpty) {
+    PaintSelfOrChildren(paintContext, aTarget);
+    return;
   }
 
-  nsRefPtr<gfxContext> groupTarget;
-  nsRefPtr<gfxASurface> untransformedSurface;
-  bool clipIsEmpty = !aTarget || aTarget->GetClipExtents().IsEmpty();
-  if (!is2D && !clipIsEmpty) {
-    untransformedSurface = 
-      gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), 
+  if (is2D) {
+    if (needsGroup) {
+      nsRefPtr<gfxContext> groupTarget = PushGroupForLayer(aTarget, aLayer, aLayer->GetEffectiveVisibleRegion(),
+                                      &needsClipToVisibleRegion);
+      PaintSelfOrChildren(paintContext, groupTarget);
+      PopGroupToSourceWithCachedSurface(aTarget, groupTarget);
+      FlushGroup(paintContext, needsClipToVisibleRegion);
+    } else {
+      PaintSelfOrChildren(paintContext, aTarget);
+    }
+  } else {
+    const nsIntRect& bounds = visibleRegion.GetBounds();
+    nsRefPtr<gfxASurface> untransformedSurface =
+      gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height),
                                                          gfxASurface::CONTENT_COLOR_ALPHA);
     if (!untransformedSurface) {
-      if (pushedTargetOpaqueRect) {
-        if (aTarget->IsCairo()) {
-          currentSurface->SetOpaqueRect(gfxRect(0, 0, 0, 0));
-        } else {
-          dt->SetOpaqueRect(IntRect());
-        }
-      }
-      NS_ASSERTION(needsSaveRestore, "Should always need to restore with 3d transforms!");
-      aTarget->Restore();
       return;
     }
     untransformedSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
-    groupTarget = new gfxContext(untransformedSurface);
-  } else if (needsGroup && !clipIsEmpty) {
-    groupTarget = PushGroupForLayer(aTarget, aLayer, aLayer->GetEffectiveVisibleRegion(),
-                                    &needsClipToVisibleRegion);
-  } else {
-    groupTarget = aTarget;
-  }
-
-  if (aLayer->GetFirstChild() &&
-      aLayer->GetMaskLayer() &&
-      HasShadowManager()) {
-    // 'paint' the mask so that it gets sent to the shadow layer tree
-    static_cast<BasicImplData*>(aLayer->GetMaskLayer()->ImplData())
-      ->Paint(nullptr, nullptr);
-  }
+    nsRefPtr<gfxContext> groupTarget = new gfxContext(untransformedSurface);
 
-  /* Only paint ourself, or our children - This optimization relies on this! */
-  Layer* child = aLayer->GetFirstChild();
-  if (!child) {
-#ifdef MOZ_LAYERS_HAVE_LOG
-    MOZ_LAYERS_LOG(("%s (0x%p) is covered: %i\n", __FUNCTION__,
-                   (void*)aLayer, data->IsHidden()));
-#endif
-    if (aLayer->AsThebesLayer()) {
-      data->PaintThebes(groupTarget,
-                        aLayer->GetMaskLayer(),
-                        aCallback, aCallbackData,
-                        aReadback);
-    } else {
-      data->Paint(groupTarget, aLayer->GetMaskLayer());
-    }
-  } else {
-    ReadbackProcessor readback;
-    ContainerLayer* container = static_cast<ContainerLayer*>(aLayer);
-    if (IsRetained()) {
-      readback.BuildUpdates(container);
-    }
-  
-    nsAutoTArray<Layer*, 12> children;
-    container->SortChildrenBy3DZOrder(children);
-
-    for (uint32_t i = 0; i < children.Length(); i++) {
-      PaintLayer(groupTarget, children.ElementAt(i), aCallback, aCallbackData, &readback);
-      if (mTransactionIncomplete)
-        break;
-    }
-  }
+    PaintSelfOrChildren(paintContext, groupTarget);
 
-  if (needsGroup) {
-    bool blitComplete = false;
-    if (is2D) {
-      PopGroupToSourceWithCachedSurface(aTarget, groupTarget);
-    } else {
-      // Temporary fast fix for bug 725886
-      // Revert these changes when 725886 is ready
-      if (!clipIsEmpty) {
-        NS_ABORT_IF_FALSE(untransformedSurface, 
-                          "We should always allocate an untransformed surface with 3d transforms!");
-        gfxPoint offset;
-        bool dontBlit = needsClipToVisibleRegion || mTransactionIncomplete ||
-                          aLayer->GetEffectiveOpacity() != 1.0f;
+    // Temporary fast fix for bug 725886
+    // Revert these changes when 725886 is ready
+    NS_ABORT_IF_FALSE(untransformedSurface,
+                      "We should always allocate an untransformed surface with 3d transforms!");
+    gfxPoint offset;
+    bool dontBlit = needsClipToVisibleRegion || mTransactionIncomplete ||
+                      aLayer->GetEffectiveOpacity() != 1.0f;
 #ifdef DEBUG
-        if (aLayer->GetDebugColorIndex() != 0) {
-          gfxRGBA  color((aLayer->GetDebugColorIndex() & 1) ? 1.0 : 0.0,
-                         (aLayer->GetDebugColorIndex() & 2) ? 1.0 : 0.0,
-                         (aLayer->GetDebugColorIndex() & 4) ? 1.0 : 0.0,
-                         1.0);
-
-          nsRefPtr<gfxContext> temp = new gfxContext(untransformedSurface);
-          temp->SetColor(color);
-          temp->Paint();
-        }
-#endif
-
-        nsRefPtr<gfxASurface> result =
-          Transform3D(untransformedSurface, aTarget, bounds,
-                      effectiveTransform, offset, dontBlit);
+    if (aLayer->GetDebugColorIndex() != 0) {
+      gfxRGBA  color((aLayer->GetDebugColorIndex() & 1) ? 1.0 : 0.0,
+                     (aLayer->GetDebugColorIndex() & 2) ? 1.0 : 0.0,
+                     (aLayer->GetDebugColorIndex() & 4) ? 1.0 : 0.0,
+                     1.0);
 
-        blitComplete = !result;
-        if (result) {
-          aTarget->SetSource(result, offset);
-        }
-      }
+      nsRefPtr<gfxContext> temp = new gfxContext(untransformedSurface);
+      temp->SetColor(color);
+      temp->Paint();
     }
-    // If we're doing our own double-buffering, we need to avoid drawing
-    // the results of an incomplete transaction to the destination surface ---
-    // that could cause flicker. Double-buffering is implemented using a
-    // temporary surface for one or more container layers, so we need to stop
-    // those temporary surfaces from being composited to aTarget.
-    // ApplyDoubleBuffering guarantees that this container layer can't
-    // intersect any other leaf layers, so if the transaction is not yet marked
-    // incomplete, the contents of this container layer are the final contents
-    // for the window.
-    if (!mTransactionIncomplete && !blitComplete) {
-      if (needsClipToVisibleRegion) {
-        gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
-      }
-      AutoSetOperator setOperator(aTarget, container->GetOperator());
-      PaintWithMask(aTarget, aLayer->GetEffectiveOpacity(),
-                    HasShadowManager() ? nullptr : aLayer->GetMaskLayer());
+#endif
+    const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
+    nsRefPtr<gfxASurface> result =
+      Transform3D(untransformedSurface, aTarget, bounds,
+                  effectiveTransform, offset, dontBlit);
+
+    if (result) {
+      aTarget->SetSource(result, offset);
+      FlushGroup(paintContext, needsClipToVisibleRegion);
     }
   }
-
-  if (pushedTargetOpaqueRect) {
-    if (aTarget->IsCairo()) {
-      currentSurface->SetOpaqueRect(gfxRect(0, 0, 0, 0));
-    } else {
-      dt->SetOpaqueRect(IntRect());
-    }
-  }
-
-  if (needsSaveRestore) {
-    aTarget->Restore();
-  } else {
-    aTarget->SetMatrix(savedMatrix);
-  }
 }
 
 void
 BasicLayerManager::ClearCachedResources()
 {
   if (mRoot) {
     ClearLayer(mRoot);
   }
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -23,16 +23,17 @@ namespace layers {
 class BasicShadowableLayer;
 class ShadowThebesLayer;
 class ShadowContainerLayer;
 class ShadowImageLayer;
 class ShadowCanvasLayer;
 class ShadowColorLayer;
 class ReadbackProcessor;
 class ImageFactory;
+class PaintContext;
 
 /**
  * This is a cairo/Thebes-only, main-thread-only implementation of layers.
  * 
  * In each transaction, the client sets up the layer tree and then during
  * the drawing phase, each ThebesLayer is painted directly into the target
  * context (with appropriate clipping and Push/PopGroups performed
  * between layers).
@@ -154,16 +155,25 @@ public:
   virtual int32_t GetMaxTextureSize() const { return PR_INT32_MAX; }
 
 protected:
   enum TransactionPhase {
     PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
   };
   TransactionPhase mPhase;
 
+  // This is the main body of the PaintLayer routine which will if it has
+  // children, recurse into PaintLayer() otherwise it will paint using the
+  // underlying Paint() method of the Layer. It will not do both.
+  void PaintSelfOrChildren(PaintContext& aPaintContext, gfxContext* aGroupTarget);
+
+  // Paint the group onto the underlying target. This is used by PaintLayer to
+  // flush the group to the underlying target.
+  void FlushGroup(PaintContext& aPaintContext, bool aNeedsClipToVisibleRegion);
+
   // Paints aLayer to mTarget.
   void PaintLayer(gfxContext* aTarget,
                   Layer* aLayer,
                   DrawThebesLayerCallback aCallback,
                   void* aCallbackData,
                   ReadbackProcessor* aReadback);
 
   // Clear the contents of a layer
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -495,20 +495,20 @@ gfxWindowsPlatform::UpdateRenderMode()
              * need to remember to release this because the nsRefPtr will
              * AddRef it.
              */
             IDWriteFactory *factory;
             HRESULT hr = createDWriteFactory(
                 DWRITE_FACTORY_TYPE_SHARED,
                 __uuidof(IDWriteFactory),
                 reinterpret_cast<IUnknown**>(&factory));
-            mDWriteFactory = factory;
-            factory->Release();
 
-            if (SUCCEEDED(hr)) {
+            if (SUCCEEDED(hr) && factory) {
+                mDWriteFactory = factory;
+                factory->Release();
                 hr = mDWriteFactory->CreateTextAnalyzer(
                     getter_AddRefs(mDWriteAnalyzer));
             }
 
             SetupClearTypeParams();
 
             if (hr == S_OK)
               reporter.SetSuccessful();
--- a/ipc/glue/Makefile.in
+++ b/ipc/glue/Makefile.in
@@ -100,16 +100,22 @@ CPPSRCS += \
   CrossProcessMutex_unimplemented.cpp \
   $(NULL)
 endif #}
 
 ifeq ($(OS_TARGET),Android)
 CPPSRCS += SharedMemoryBasic_android.cpp
 endif #}
 
+ifeq ($(OS_ARCH),Linux)
+CPPSRCS += ProcessUtils_linux.cpp
+else
+CPPSRCS += ProcessUtils_none.cpp
+endif
+
 include $(topsrcdir)/ipc/app/defs.mk
 DEFINES += -DMOZ_CHILD_PROCESS_NAME=\"$(MOZ_CHILD_PROCESS_NAME)\"
 DEFINES += -DMOZ_CHILD_PROCESS_BUNDLE=\"$(MOZ_CHILD_PROCESS_BUNDLE)\"
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/ipc/glue/ProcessUtils.h
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_ipc_ProcessUtils_h
+#define mozilla_ipc_ProcessUtils_h
+
+namespace mozilla {
+namespace ipc {
+
+void SetThisProcessName(const char *aName);
+
+} // namespace ipc
+} // namespace mozilla
+
+#endif // ifndef mozilla_ipc_ProcessUtils_h
+
new file mode 100644
--- /dev/null
+++ b/ipc/glue/ProcessUtils_linux.cpp
@@ -0,0 +1,20 @@
+/* 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 "ProcessUtils.h"
+
+#include "nsString.h"
+
+#include <sys/prctl.h>
+
+namespace mozilla {
+namespace ipc {
+
+void SetThisProcessName(const char *aName)
+{
+  prctl(PR_SET_NAME, (unsigned long)aName, 0uL, 0uL, 0uL);
+}
+
+} // namespace ipc
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/glue/ProcessUtils_none.cpp
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ProcessUtils.h"
+
+namespace mozilla {
+namespace ipc {
+
+void SetThisProcessName(const char *aString)
+{
+  (void)aString;
+}
+
+} // namespace ipc
+} // namespace mozilla
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -375,23 +375,17 @@ endif
 ifndef PROGOBJS
 PROGOBJS		= $(OBJS)
 endif
 
 ifndef HOST_PROGOBJS
 HOST_PROGOBJS		= $(HOST_OBJS)
 endif
 
-# MAKE_DIRS: List of directories to build while looping over directories.
-# A Makefile that needs $(MDDEPDIR) created but doesn't set any of these
-# variables we know to check can just set NEED_MDDEPDIR explicitly.
-ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)$(NEED_MDDEPDIR))
-MAKE_DIRS       += $(CURDIR)/$(MDDEPDIR)
-GARBAGE_DIRS    += $(CURDIR)/$(MDDEPDIR)
-endif
+GARBAGE_DIRS    += $(wildcard $(CURDIR)/$(MDDEPDIR))
 
 #
 # Tags: emacs (etags), vi (ctags)
 # TAG_PROGRAM := ctags -L -
 #
 TAG_PROGRAM		= xargs etags -a
 
 #
@@ -947,17 +941,17 @@ endif # Sun Studio on Solaris
 $(HOST_CMOBJS): host_%.$(OBJ_SUFFIX): %.m
 	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
 $(HOST_CMMOBJS): host_%.$(OBJ_SUFFIX): %.mm
 	$(REPORT_BUILD)
 	$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
 
-$(COBJS): %.$(OBJ_SUFFIX): %.c
+$(COBJS): %.$(OBJ_SUFFIX): %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
 # DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
 # 'moc' only knows about #defines it gets on the command line (-D...), not in
 # included headers like mozilla-config.h
 moc_%.cpp: %.h
@@ -977,55 +971,55 @@ ifdef ASFILES
 endif
 
 $(SOBJS): %.$(OBJ_SUFFIX): %.S
 	$(AS) -o $@ $(ASFLAGS) -c $<
 
 #
 # Please keep the next two rules in sync.
 #
-$(CCOBJS): %.$(OBJ_SUFFIX): %.cc
+$(CCOBJS): %.$(OBJ_SUFFIX): %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-$(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp
+$(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-$(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm
+$(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
 
-$(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m
+$(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m $(call mkdir_deps,$(MDDEPDIR))
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CC)
 	$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
 
-%.s: %.cpp
+%.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-%.s: %.cc
+%.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
 
-%.s: %.c
+%.s: %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS)
 
-%.i: %.cpp
+%.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
 
-%.i: %.cc
+%.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
 
-%.i: %.c
+%.i: %.c $(call mkdir_deps,$(MDDEPDIR))
 	$(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i
 
-%.i: %.mm
+%.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
 	$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i
 
 %.res: %.rc
 	@echo Creating Resource file: $@
 ifeq ($(OS_ARCH),OS2)
 	$(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@
 else
 ifdef GNU_CC
@@ -1351,28 +1345,30 @@ endif
 
 ################################################################################
 # Copy testing-only JS modules to appropriate destination.
 #
 # For each file defined in TESTING_JS_MODULES, copy it to
 # objdir/_tests/modules/. If TESTING_JS_MODULE_DIR is defined, that path
 # wlll be appended to the output directory.
 
+ifdef ENABLE_TESTS
 ifdef TESTING_JS_MODULES
 testmodulesdir = $(DEPTH)/_tests/modules/$(TESTING_JS_MODULE_DIR)
 
 GENERATED_DIRS += $(testmodulesdir)
 
 ifndef NO_DIST_INSTALL
 TESTING_JS_MODULES_FILES := $(TESTING_JS_MODULES)
 TESTING_JS_MODULES_DEST := $(testmodulesdir)
 INSTALL_TARGETS += TESTING_JS_MODULES
 endif
 
 endif
+endif
 
 ################################################################################
 # SDK
 
 ifneq (,$(SDK_LIBRARY))
 ifndef NO_DIST_INSTALL
 SDK_LIBRARY_FILES := $(SDK_LIBRARY)
 SDK_LIBRARY_DEST := $(SDK_LIB_DIR)
@@ -1477,19 +1473,16 @@ endif
 #   processes could simultaneously try to create the same directory.
 #
 #   We use $(CURDIR) in the rule's target to ensure that we don't find
 #   a dependency directory in the source tree via VPATH (perhaps from
 #   a previous build in the source tree) and thus neglect to create a
 #   dependency directory in the object directory, where we really need
 #   it.
 
-$(CURDIR)/$(MDDEPDIR):
-	$(MKDIR) -p $@
-
 ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
 MDDEPEND_FILES		:= $(strip $(wildcard $(foreach file,$(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS) $(TARGETS) $(XPIDLSRCS:.idl=.h) $(XPIDLSRCS:.idl=.xpt),$(MDDEPDIR)/$(notdir $(file)).pp) $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES))))
 
 ifneq (,$(MDDEPEND_FILES))
 # The script mddepend.pl checks the dependencies and writes to stdout
 # one rule to force out-of-date objects. For example,
 #   foo.o boo.o: FORCE
 # The script has an advantage over including the *.pp files directly
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -109,17 +109,18 @@ frontend::CompileScript(JSContext *cx, H
     bool savedCallerFun = options.compileAndGo && callerFrame && callerFrame->isFunctionFrame();
     Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun,
                                                   options, staticLevel, ss, 0, length));
     if (!script)
         return NULL;
 
     // Global/eval script bindings are always empty (all names are added to the
     // scope dynamically via JSOP_DEFFUN/VAR).
-    if (!script->bindings.initWithTemporaryStorage(cx, 0, 0, NULL))
+    InternalHandle<Bindings*> bindings(script, &script->bindings);
+    if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, NULL))
         return NULL;
 
     // We can specialize a bit for the given scope chain if that scope chain is the global object.
     JSObject *globalScope = scopeChain && scopeChain == &scopeChain->global() ? (JSObject*) scopeChain : NULL;
     JS_ASSERT_IF(globalScope, globalScope->isNative());
     JS_ASSERT_IF(globalScope, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalScope->getClass()));
 
     BytecodeEmitter bce(/* parent = */ NULL, &parser, &sc, script, callerFrame, !!globalScope,
@@ -322,17 +323,18 @@ frontend::CompileFunctionBody(JSContext 
     if (!FoldConstants(cx, pn, &parser))
         return false;
 
     Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), false, options,
                                                   staticLevel, ss, 0, length));
     if (!script)
         return false;
 
-    if (!funpc.generateFunctionBindings(cx, &script->bindings))
+    InternalHandle<Bindings*> bindings(script, &script->bindings);
+    if (!funpc.generateFunctionBindings(cx, bindings))
         return false;
 
     BytecodeEmitter funbce(/* parent = */ NULL, &parser, &funsc, script, /* callerFrame = */ NULL,
                            /* hasGlobalScope = */ false, options.lineno);
     if (!funbce.init())
         return false;
 
     if (!NameFunctions(cx, pn))
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -291,32 +291,35 @@ AppendPackedBindings(const ParseContext 
                        (pc->sc->bindingsAccessedDynamically() &&
                         pc->decls().lookupFirst(name) == dn);
 
         *dst = Binding(name, kind, aliased);
     }
 }
 
 bool
-ParseContext::generateFunctionBindings(JSContext *cx, Bindings *bindings) const
+ParseContext::generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const
 {
     JS_ASSERT(sc->inFunction());
 
     unsigned count = args_.length() + vars_.length();
     Binding *packedBindings = cx->tempLifoAlloc().newArrayUninitialized<Binding>(count);
     if (!packedBindings) {
         js_ReportOutOfMemory(cx);
         return false;
     }
 
     AppendPackedBindings(this, args_, packedBindings);
     AppendPackedBindings(this, vars_, packedBindings + args_.length());
 
-    if (!bindings->initWithTemporaryStorage(cx, args_.length(), vars_.length(), packedBindings))
+    if (!Bindings::initWithTemporaryStorage(cx, bindings, args_.length(), vars_.length(),
+                                            packedBindings))
+    {
         return false;
+    }
 
     if (bindings->hasAnyAliasedBindings() || sc->funHasExtensibleScope())
         sc->funbox()->fun()->flags |= JSFUN_HEAVYWEIGHT;
 
     return true;
 }
 
 Parser::Parser(JSContext *cx, const CompileOptions &options,
@@ -1252,17 +1255,19 @@ LeaveFunction(ParseNode *fn, Parser *par
                 outer_dn->pn_dflags |= dn->pn_dflags & ~PND_PLACEHOLDER;
             }
 
             /* Mark the outer dn as escaping. */
             outer_dn->pn_dflags |= PND_CLOSED;
         }
     }
 
-    if (!funpc->generateFunctionBindings(cx, &funbox->bindings))
+    InternalHandle<Bindings*> bindings =
+        InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
+    if (!funpc->generateFunctionBindings(cx, bindings))
         return false;
 
     funpc->lexdeps.releaseMap(cx);
     return true;
 }
 
 /*
  * DefineArg is called for both the arguments of a regular function definition
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -146,17 +146,17 @@ struct ParseContext                 /* t
      *    the use/def nodes, but the emitter occasionally needs 'bindings' for
      *    various scope-related queries.
      *  - Bindings provide the initial js::Shape to use when creating a dynamic
      *    scope object (js::CallObject) for the function. This shape is used
      *    during dynamic name lookup.
      *  - Sometimes a script's bindings are accessed at runtime to retrieve the
      *    contents of the lexical scope (e.g., from the debugger).
      */
-    bool generateFunctionBindings(JSContext *cx, Bindings *bindings) const;
+    bool generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const;
 
   public:
     ParseNode       *yieldNode;     /* parse node for a yield expression that might
                                        be an error if we turn out to be inside a
                                        generator expression */
     FunctionBox     *functionList;
 
     // A strict mode error found in this scope or one of its children. It is
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -6,19 +6,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jsgc_root_h__
 #define jsgc_root_h__
 
 #ifdef __cplusplus
 
 #include "mozilla/TypeTraits.h"
+#include "mozilla/GuardObjects.h"
 
 #include "js/TemplateLib.h"
-#include "js/Utility.h"
+
+#include "jspubtd.h"
 
 namespace js {
 namespace gc {
 struct Cell;
 } /* namespace gc */
 } /* namespace js */
 
 namespace JS {
@@ -239,16 +241,83 @@ typedef MutableHandle<jsid>         Muta
 /*
  * Raw pointer used as documentation that a parameter does not need to be
  * rooted.
  */
 typedef JSObject *                  RawObject;
 typedef JSString *                  RawString;
 typedef Value                       RawValue;
 
+/*
+ * InternalHandle is a handle to an internal pointer into a gcthing. Use
+ * InternalHandle when you have a pointer to a direct field of a gcthing, or
+ * when you need a parameter type for something that *may* be a pointer to a
+ * direct field of a gcthing.
+ */
+class InternalHandleBase
+{
+  protected:
+    static void * const zeroPointer;
+};
+
+template <typename T>
+class InternalHandle { };
+
+template <typename T>
+class InternalHandle<T*> : public InternalHandleBase
+{
+    void * const *holder;
+    size_t offset;
+
+  public:
+    /*
+     * Create an InternalHandle using a Handle to the gcthing containing the
+     * field in question, and a pointer to the field.
+     */
+    template<typename H>
+    InternalHandle(const Handle<H> &handle, T *field)
+      : holder((void**)handle.address()), offset(uintptr_t(field) - uintptr_t(handle.get()))
+    {
+    }
+
+    /*
+     * Create an InternalHandle to a field within a Rooted<>.
+     */
+    template<typename R>
+    InternalHandle(const Rooted<R> &root, T *field)
+      : holder((void**)root.address()), offset(uintptr_t(field) - uintptr_t(root.get()))
+    {
+    }
+
+    T *get() const { return reinterpret_cast<T*>(uintptr_t(*holder) + offset); }
+
+    const T& operator *() const { return *get(); }
+    T* operator ->() const { return get(); }
+
+    static InternalHandle<T*> fromMarkedLocation(T *fieldPtr) {
+        return InternalHandle(fieldPtr);
+    }
+
+  private:
+    /*
+     * Create an InternalHandle to something that is not a pointer to a
+     * gcthing, and so does not need to be rooted in the first place. Use these
+     * InternalHandles to pass pointers into functions that also need to accept
+     * regular InternalHandles to gcthing fields.
+     *
+     * Make this private to prevent accidental misuse; this is only for
+     * fromMarkedLocation().
+     */
+    InternalHandle(T *field)
+      : holder(reinterpret_cast<void * const *>(&zeroPointer)),
+        offset(uintptr_t(field))
+    {
+    }
+};
+
 extern mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
 
 /*
  * By default, pointers should use the inheritance hierarchy to find their
  * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
  * Rooted<T> may be used without the class definition being available.
  */
 template <typename T>
@@ -389,17 +458,17 @@ typedef Rooted<Value>        RootedValue
 /*
  * Mark a stack location as a root for the rooting analysis, without actually
  * rooting it in release builds. This should only be used for stack locations
  * of GC things that cannot be relocated by a garbage collection, and that
  * are definitely reachable via another path.
  */
 class SkipRoot
 {
-#if defined(DEBUG) && defined(JSGC_ROOT_ANALYSIS)
+#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
 
     SkipRoot **stack, *prev;
     const uint8_t *start;
     const uint8_t *end;
 
     template <typename T>
     void init(ContextFriendFields *cx, const T *ptr, size_t count)
     {
@@ -441,67 +510,61 @@ class SkipRoot
         JS_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
 #endif /* DEBUG && JSGC_ROOT_ANALYSIS */
 
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
-/*
- * This typedef is to annotate parameters that we have manually verified do not
- * need rooting, as opposed to parameters that have not yet been considered.
- */
-typedef JSObject *RawObject;
-
-#ifdef DEBUG
-JS_FRIEND_API(bool) IsRootingUnnecessaryForContext(JSContext *cx);
-JS_FRIEND_API(void) SetRootingUnnecessaryForContext(JSContext *cx, bool value);
-JS_FRIEND_API(bool) RelaxRootChecksForContext(JSContext *cx);
-#endif
+JS_FRIEND_API(void) EnterAssertNoGCScope();
+JS_FRIEND_API(void) LeaveAssertNoGCScope();
+JS_FRIEND_API(bool) InNoGCScope();
 
-class AssertRootingUnnecessary {
-    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
-#ifdef DEBUG
-    JSContext *cx;
-    bool prev;
-#endif
+/*
+ * The scoped guard object AutoAssertNoGC forces the GC to assert if a GC is
+ * attempted while the guard object is live.  If you have a GC-unsafe operation
+ * to perform, use this guard object to protect your opertion.
+ */
+class AutoAssertNoGC
+{
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+
 public:
-    AssertRootingUnnecessary(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
-    {
-        JS_GUARD_OBJECT_NOTIFIER_INIT;
+    AutoAssertNoGC(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
+        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 #ifdef DEBUG
-        this->cx = cx;
-        prev = IsRootingUnnecessaryForContext(cx);
-        SetRootingUnnecessaryForContext(cx, true);
+        EnterAssertNoGCScope();
 #endif
     }
 
-    ~AssertRootingUnnecessary() {
+    ~AutoAssertNoGC() {
 #ifdef DEBUG
-        SetRootingUnnecessaryForContext(cx, prev);
+        LeaveAssertNoGCScope();
 #endif
     }
 };
 
 #if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
 extern void
 CheckStackRoots(JSContext *cx);
 #endif
 
+JS_FRIEND_API(bool) NeedRelaxedRootChecks();
+
 /*
  * Hook for dynamic root analysis. Checks the native stack and poisons
  * references to GC things which have not been rooted.
  */
 inline void MaybeCheckStackRoots(JSContext *cx, bool relax = true)
 {
 #ifdef DEBUG
-    JS_ASSERT(!IsRootingUnnecessaryForContext(cx));
+    JS_ASSERT(!InNoGCScope());
 # if defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
-    if (relax && RelaxRootChecksForContext(cx))
+    if (relax && NeedRelaxedRootChecks())
         return;
     CheckStackRoots(cx);
 # endif
 #endif
 }
 
 /* Base class for automatic read-only object rooting during compilation. */
 class CompilerRootNode
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -740,17 +740,50 @@ JS_IsBuiltinFunctionConstructor(JSFuncti
  */
 static JSBool js_NewRuntimeWasCalled = JS_FALSE;
 
 /*
  * Thread Local Storage slot for storing the runtime for a thread.
  */
 namespace JS {
 mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
-}
+
+#ifdef DEBUG
+JS_FRIEND_API(void)
+EnterAssertNoGCScope()
+{
+    ++TlsRuntime.get()->gcAssertNoGCDepth;
+}
+
+JS_FRIEND_API(void)
+LeaveAssertNoGCScope()
+{
+    --TlsRuntime.get()->gcAssertNoGCDepth;
+    JS_ASSERT(TlsRuntime.get()->gcAssertNoGCDepth >= 0);
+}
+
+JS_FRIEND_API(bool)
+InNoGCScope()
+{
+    return TlsRuntime.get()->gcAssertNoGCDepth > 0;
+}
+
+JS_FRIEND_API(bool)
+NeedRelaxedRootChecks()
+{
+    return TlsRuntime.get()->gcRelaxRootChecks;
+}
+#else
+JS_FRIEND_API(void) EnterAssertNoGCScope() {}
+JS_FRIEND_API(void) LeaveAssertNoGCScope() {}
+JS_FRIEND_API(bool) InNoGCScope() { return false; }
+JS_FRIEND_API(bool) NeedRelaxedRootChecks() { return false; }
+#endif
+
+} /* namespace JS */
 
 static const JSSecurityCallbacks NullSecurityCallbacks = { };
 
 JSRuntime::JSRuntime()
   : atomsCompartment(NULL),
 #ifdef JS_THREADSAFE
     ownerThread_(NULL),
 #endif
@@ -817,16 +850,20 @@ JSRuntime::JSRuntime()
     gcSweepPhase(0),
     gcSweepCompartmentIndex(0),
     gcSweepKindIndex(0),
     gcArenasAllocatedDuringSweep(NULL),
     gcInterFrameGC(0),
     gcSliceBudget(SliceBudget::Unlimited),
     gcIncrementalEnabled(true),
     gcExactScanningEnabled(true),
+#ifdef DEBUG
+    gcRelaxRootChecks(false),
+    gcAssertNoGCDepth(0),
+#endif
     gcPoke(false),
     heapState(Idle),
 #ifdef JS_GC_ZEAL
     gcZeal_(0),
     gcZealFrequency(0),
     gcNextScheduled(0),
     gcDeterministicOnly(false),
     gcIncrementalLimit(0),
@@ -3475,17 +3512,17 @@ JS_NewObject(JSContext *cx, JSClass *jsc
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
-    AssertRootingUnnecessary safe(cx);
+    AutoAssertNoGC nogc;
     if (obj) {
         if (clasp->ext.equality)
             MarkTypeObjectFlags(cx, obj, OBJECT_FLAG_SPECIAL_EQUALITY);
     }
 
     JS_ASSERT_IF(obj, obj->getParent());
     return obj;
 }
@@ -3503,17 +3540,17 @@ JS_NewObjectWithGivenProto(JSContext *cx
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
-    AssertRootingUnnecessary safe(cx);
+    AutoAssertNoGC nogc;
     if (obj)
         MarkTypeObjectUnknownProperties(cx, obj->type());
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObjectForConstructor(JSContext *cx, JSClass *clasp, const jsval *vp)
 {
@@ -4703,17 +4740,17 @@ JS_NewPropertyIterator(JSContext *cx, JS
     iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
     return iterobj;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_NextProperty(JSContext *cx, JSObject *iterobjArg, jsid *idp)
 {
     RootedObject iterobj(cx, iterobjArg);
-    AssertRootingUnnecessary safe(cx);
+    AutoAssertNoGC nogc;
     int32_t i;
     Shape *shape;
     JSIdArray *ida;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, iterobj);
     i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1056,17 +1056,16 @@ class JS_PUBLIC_API(AutoGCRooter) {
         IDVECTOR =    -15, /* js::AutoIdVector */
         OBJVECTOR =   -16, /* js::AutoObjectVector */
         STRINGVECTOR =-17, /* js::AutoStringVector */
         SCRIPTVECTOR =-18, /* js::AutoScriptVector */
         PROPDESC =    -19, /* js::PropDesc::AutoRooter */
         SHAPERANGE =  -20, /* js::Shape::Range::AutoRooter */
         STACKSHAPE =  -21, /* js::StackShape::AutoRooter */
         STACKBASESHAPE=-22,/* js::StackBaseShape::AutoRooter */
-        BINDINGS =    -23, /* js::Bindings::AutoRooter */
         GETTERSETTER =-24, /* js::AutoRooterGetterSetter */
         REGEXPSTATICS=-25, /* js::RegExpStatics::AutoRooter */
         NAMEVECTOR =  -26, /* js::AutoNameVector */
         HASHABLEVALUE=-27,
         IONMASM =     -28, /* js::ion::MacroAssembler */
         IONALLOC =    -29  /* js::ion::AutoTempAllocatorRooter */
     };
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1195,19 +1195,16 @@ JSContext::JSContext(JSRuntime *rt)
     hasVersionOverride(false),
     throwing(false),
     exception(UndefinedValue()),
     runOptions(0),
     reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
     localeCallbacks(NULL),
     resolvingList(NULL),
     generatingError(false),
-#ifdef DEBUG
-    rootingUnnecessary(false),
-#endif
     compartment(NULL),
     enterCompartmentDepth_(0),
     savedFrameChains_(),
     defaultCompartmentObject_(NULL),
     stack(thisDuringConstruction()),
     parseMapPool_(NULL),
     cycleDetectorSet(thisDuringConstruction()),
     argumentFormatMap(NULL),
@@ -1233,17 +1230,17 @@ JSContext::JSContext(JSRuntime *rt)
 #ifdef DEBUG
     stackIterAssertionEnabled(true),
 #endif
     activeCompilations(0)
 {
     PodZero(&link);
 #ifdef JSGC_ROOT_ANALYSIS
     PodArrayZero(thingGCRooters);
-#ifdef DEBUG
+#if defined(JS_GC_ZEAL) && defined(DEBUG) && !defined(JS_THREADSAFE)
     skipGCRooters = NULL;
 #endif
 #endif
 }
 
 JSContext::~JSContext()
 {
     /* Free the stuff hanging off of cx. */
@@ -1259,40 +1256,16 @@ JSContext::~JSContext()
         JSArgumentFormatMap *temp = map;
         map = map->next;
         js_free(temp);
     }
 
     JS_ASSERT(!resolvingList);
 }
 
-#ifdef DEBUG
-namespace JS {
-
-JS_FRIEND_API(void)
-SetRootingUnnecessaryForContext(JSContext *cx, bool value)
-{
-    cx->rootingUnnecessary = value;
-}
-
-JS_FRIEND_API(bool)
-IsRootingUnnecessaryForContext(JSContext *cx)
-{
-    return cx->rootingUnnecessary;
-}
-
-JS_FRIEND_API(bool)
-RelaxRootChecksForContext(JSContext *cx)
-{
-    return cx->runtime->relaxRootChecks;
-}
-
-} /* namespace JS */
-#endif
-
 /*
  * Since this function is only called in the context of a pending exception,
  * the caller must subsequently take an error path. If wrapping fails, it will
  * set a new (uncatchable) exception to be used in place of the original.
  */
 void
 JSContext::wrapPendingException()
 {
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -650,24 +650,23 @@ struct JSRuntime : js::RuntimeFriendFiel
 #ifdef DEBUG
     struct SavedGCRoot {
         void *thing;
         JSGCTraceKind kind;
 
         SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {}
     };
     js::Vector<SavedGCRoot, 0, js::SystemAllocPolicy> gcSavedRoots;
+
+    bool                gcRelaxRootChecks;
+    int                 gcAssertNoGCDepth;
 #endif
 
     bool                gcPoke;
 
-#ifdef DEBUG
-    bool                relaxRootChecks;
-#endif
-
     enum HeapState {
         Idle,       // doing nothing with the GC heap
         Tracing,    // tracing the GC heap without collecting, e.g. IterateCompartments()
         Collecting  // doing a GC of the heap
     };
 
     HeapState           heapState;
 
@@ -1237,20 +1236,16 @@ struct JSContext : js::ContextFriendFiel
     /* Locale specific callbacks for string conversion. */
     JSLocaleCallbacks   *localeCallbacks;
 
     js::AutoResolving   *resolvingList;
 
     /* True if generating an error, to prevent runaway recursion. */
     bool                generatingError;
 
-#ifdef DEBUG
-    bool                rootingUnnecessary;
-#endif
-
     /* The current compartment. */
     JSCompartment       *compartment;
 
     inline void setCompartment(JSCompartment *c) { compartment = c; }
 
     /*
      * "Entering" a compartment changes cx->compartment (which changes
      * cx->global). Note that this does not push any StackFrame which means
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -107,16 +107,18 @@
 #if JS_TRACE_LOGGING
 #include "TraceLogging.h"
 #endif
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 
+void * const JS::InternalHandleBase::zeroPointer = NULL;
+
 namespace js {
 namespace gc {
 
 /*
  * Lower limit after which we limit the heap growth
  */
 const size_t GC_ALLOCATION_THRESHOLD = 30 * 1024 * 1024;
 
@@ -2443,22 +2445,16 @@ AutoGCRooter::trace(JSTracer *trc)
         }
         if ((rooter->base->flags & BaseShape::HAS_SETTER_OBJECT) && rooter->base->rawSetter) {
             MarkObjectRoot(trc, (JSObject**) &rooter->base->rawSetter,
                            "StackBaseShape::AutoRooter setter");
         }
         return;
       }
 
-      case BINDINGS: {
-        Bindings::AutoRooter *rooter = static_cast<Bindings::AutoRooter *>(this);
-        rooter->trace(trc);
-        return;
-      }
-
       case GETTERSETTER: {
         AutoRooterGetterSetter::Inner *rooter = static_cast<AutoRooterGetterSetter::Inner *>(this);
         if ((rooter->attrs & JSPROP_GETTER) && *rooter->pgetter)
             MarkObjectRoot(trc, (JSObject**) rooter->pgetter, "AutoRooterGetterSetter getter");
         if ((rooter->attrs & JSPROP_SETTER) && *rooter->psetter)
             MarkObjectRoot(trc, (JSObject**) rooter->psetter, "AutoRooterGetterSetter setter");
         return;
       }
@@ -2509,22 +2505,16 @@ AutoGCRooter::traceAll(JSTracer *trc)
 void
 Shape::Range::AutoRooter::trace(JSTracer *trc)
 {
     if (r->cursor)
         MarkShapeRoot(trc, const_cast<Shape**>(&r->cursor), "Shape::Range::AutoRooter");
 }
 
 void
-Bindings::AutoRooter::trace(JSTracer *trc)
-{
-    bindings->trace(trc);
-}
-
-void
 RegExpStatics::AutoRooter::trace(JSTracer *trc)
 {
     if (statics->matchPairsInput)
         MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchPairsInput),
                        "RegExpStatics::AutoRooter matchPairsInput");
     if (statics->pendingInput)
         MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
                        "RegExpStatics::AutoRooter pendingInput");
@@ -4963,26 +4953,26 @@ JS::CheckStackRoots(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime;
 
     if (rt->gcZeal_ != ZealStackRootingSafeValue && rt->gcZeal_ != ZealStackRootingValue)
         return;
     if (rt->gcZeal_ == ZealStackRootingSafeValue && !rt->gcExactScanningEnabled)
         return;
 
-    // If this assertion fails, it means that an AssertRootingUnnecessary was
-    // placed around code that could trigger GC, and is therefore wrong. The
-    // AssertRootingUnnecessary should be removed and the code it was guarding
-    // should be modified to properly root any gcthings, and very possibly any
-    // code calling that function should also be modified if it was improperly
+    // If this assertion fails, it means that an AutoAssertNoGC was placed
+    // around code that could trigger GC, and is therefore wrong. The
+    // AutoAssertNoGC should be removed and the code it was guarding should be
+    // modified to properly root any gcthings, and very possibly any code
+    // calling that function should also be modified if it was improperly
     // assuming that GC could not happen at all within the called function.
-    // (The latter may not apply if the AssertRootingUnnecessary only protected
-    // a portion of a function, so the callers were already assuming that GC
-    // could happen.)
-    JS_ASSERT(!cx->rootingUnnecessary);
+    // (The latter may not apply if the AutoAssertNoGC only protected a portion
+    // of a function, so the callers were already assuming that GC could
+    // happen.)
+    JS_ASSERT(!InNoGCScope());
 
     // GCs can't happen when analysis/inference/compilation are active.
     if (cx->compartment->activeAnalysis)
         return;
 
     // Can switch to the atoms compartment during analysis.
     if (IsAtomsCompartment(cx->compartment)) {
         for (CompartmentsIter c(rt); !c.done(); c.next()) {
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -5639,17 +5639,17 @@ JSObject::splicePrototype(JSContext *cx,
 TypeObject *
 JSObject::makeLazyType(JSContext *cx)
 {
     JS_ASSERT(hasLazyType());
 
     RootedObject self(cx, this);
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(getClass());
     TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, key, getProto());
-    AssertRootingUnnecessary safe(cx);
+    AutoAssertNoGC nogc;
     if (!type) {
         if (cx->typeInferenceEnabled())
             cx->compartment->types.setPendingNukeTypes(cx);
         return self->type_;
     }
 
     if (!cx->typeInferenceEnabled()) {
         /* This can only happen if types were previously nuked. */
--- a/js/src/jspropertycacheinlines.h
+++ b/js/src/jspropertycacheinlines.h
@@ -26,17 +26,17 @@
  * We must lock pobj on a hit in order to close races with threads that might
  * be deleting a property from its scope, or otherwise invalidating property
  * caches (on all threads) by re-generating JSObject::shape().
  */
 JS_ALWAYS_INLINE void
 js::PropertyCache::test(JSContext *cx, jsbytecode *pc, JSObject *&obj,
                         JSObject *&pobj, PropertyCacheEntry *&entry, PropertyName *&name)
 {
-    AssertRootingUnnecessary assert(cx);
+    AutoAssertNoGC nogc;
 
     JS_ASSERT(this == &cx->propertyCache());
 
     Shape *kshape = obj->lastProperty();
     entry = &table[hash(pc, kshape)];
     PCMETER(pctestentry = entry);
     PCMETER(tests++);
     JS_ASSERT(&obj != &pobj);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -56,58 +56,61 @@ Bindings::argumentsVarIndex(JSContext *c
     PropertyName *arguments = cx->runtime->atomState.argumentsAtom;
     BindingIter bi(*this);
     while (bi->name() != arguments)
         bi++;
     return bi.frameIndex();
 }
 
 bool
-Bindings::initWithTemporaryStorage(JSContext *cx, unsigned numArgs, unsigned numVars, Binding *bindingArray)
+Bindings::initWithTemporaryStorage(JSContext *cx, InternalHandle<Bindings*> self,
+                                   unsigned numArgs, unsigned numVars,
+                                   Binding *bindingArray)
 {
-    JS_ASSERT(!callObjShape_);
-    JS_ASSERT(bindingArrayAndFlag_ == TEMPORARY_STORAGE_BIT);
+    JS_ASSERT(!self->callObjShape_);
+    JS_ASSERT(self->bindingArrayAndFlag_ == TEMPORARY_STORAGE_BIT);
 
     if (numArgs > UINT16_MAX || numVars > UINT16_MAX) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                             numArgs_ > numVars_ ?
+                             self->numArgs_ > self->numVars_ ?
                              JSMSG_TOO_MANY_FUN_ARGS :
                              JSMSG_TOO_MANY_LOCALS);
         return false;
     }
 
     JS_ASSERT(!(uintptr_t(bindingArray) & TEMPORARY_STORAGE_BIT));
-    bindingArrayAndFlag_ = uintptr_t(bindingArray) | TEMPORARY_STORAGE_BIT;
-    numArgs_ = numArgs;
-    numVars_ = numVars;
+    self->bindingArrayAndFlag_ = uintptr_t(bindingArray) | TEMPORARY_STORAGE_BIT;
+    self->numArgs_ = numArgs;
+    self->numVars_ = numVars;
 
     /*
      * Get the initial shape to use when creating CallObjects for this script.
      * Since unaliased variables are, by definition, only accessed by local
      * operations and never through the scope chain, only give shapes to
      * aliased variables. While the debugger may observe any scope object at
      * any time, such accesses are mediated by DebugScopeProxy (see
      * DebugScopeProxy::handleUnaliasedAccess).
      */
 
     JS_STATIC_ASSERT(CallObject::RESERVED_SLOTS == 2);
     gc::AllocKind allocKind = gc::FINALIZE_OBJECT2_BACKGROUND;
     JS_ASSERT(gc::GetGCKindSlots(allocKind) == CallObject::RESERVED_SLOTS);
-    callObjShape_ = EmptyShape::getInitialShape(cx, &CallClass, NULL, cx->global(),
-                                                allocKind, BaseShape::VAROBJ | BaseShape::DELEGATE);
+    self->callObjShape_ =
+        EmptyShape::getInitialShape(cx, &CallClass, NULL, cx->global(),
+                                    allocKind, BaseShape::VAROBJ | BaseShape::DELEGATE);
 
 #ifdef DEBUG
     HashSet<PropertyName *> added(cx);
     if (!added.init())
         return false;
 #endif
 
-    BindingIter bi(*this);
+    BindingIter bi(*self);
     unsigned slot = CallObject::RESERVED_SLOTS;
-    for (unsigned i = 0, n = count(); i < n; i++, bi++) {
+    for (unsigned i = 0, n = self->count(); i < n; i++, bi++) {
         if (!bi->aliased())
             continue;
 
 #ifdef DEBUG
         /* The caller ensures no duplicate aliased names. */
         JS_ASSERT(!added.has(bi->name()));
         if (!added.put(bi->name()))
             return false;
@@ -119,18 +122,18 @@ Bindings::initWithTemporaryStorage(JSCon
             return false;
 
         RootedId id(cx, NameToId(bi->name()));
         unsigned attrs = JSPROP_PERMANENT | JSPROP_ENUMERATE |
                          (bi->kind() == CONSTANT ? JSPROP_READONLY : 0);
         unsigned frameIndex = bi.frameIndex();
         StackShape child(nbase, id, slot++, 0, attrs, Shape::HAS_SHORTID, frameIndex);
 
-        callObjShape_ = callObjShape_->getChildBinding(cx, child);
-        if (!callObjShape_)
+        self->callObjShape_ = self->callObjShape_->getChildBinding(cx, child);
+        if (!self->callObjShape_)
             return false;
     }
     JS_ASSERT(!bi);
 
     return true;
 }
 
 uint8_t *
@@ -140,32 +143,34 @@ Bindings::switchToScriptStorage(Binding 
     JS_ASSERT(!(uintptr_t(newBindingArray) & TEMPORARY_STORAGE_BIT));
 
     PodCopy(newBindingArray, bindingArray(), count());
     bindingArrayAndFlag_ = uintptr_t(newBindingArray);
     return reinterpret_cast<uint8_t *>(newBindingArray + count());
 }
 
 bool
-Bindings::clone(JSContext *cx, uint8_t *dstScriptData, HandleScript srcScript)
+Bindings::clone(JSContext *cx, InternalHandle<Bindings*> self,
+                uint8_t *dstScriptData,
+                HandleScript srcScript)
 {
     /* The clone has the same bindingArray_ offset as 'src'. */
     Bindings &src = srcScript->bindings;
     ptrdiff_t off = (uint8_t *)src.bindingArray() - srcScript->data;
     JS_ASSERT(off >= 0);
     JS_ASSERT(off <= (srcScript->code - srcScript->data));
     Binding *dstPackedBindings = (Binding *)(dstScriptData + off);
 
     /*
      * Since atoms are shareable throughout the runtime, we can simply copy
      * the source's bindingArray directly.
      */
-    if (!initWithTemporaryStorage(cx, src.numArgs(), src.numVars(), src.bindingArray()))
+    if (!initWithTemporaryStorage(cx, self, src.numArgs(), src.numVars(), src.bindingArray()))
         return false;
-    switchToScriptStorage(dstPackedBindings);
+    self->switchToScriptStorage(dstPackedBindings);
     return true;
 }
 
 template<XDRMode mode>
 static bool
 XDRScriptBindings(XDRState<mode> *xdr, LifoAllocScope &las, unsigned numArgs, unsigned numVars,
                   HandleScript script)
 {
@@ -206,17 +211,18 @@ XDRScriptBindings(XDRState<mode> *xdr, L
 
             PropertyName *name = atoms[i].toString()->asAtom().asPropertyName();
             BindingKind kind = BindingKind(u8 >> 1);
             bool aliased = bool(u8 & 1);
 
             bindingArray[i] = Binding(name, kind, aliased);
         }
 
-        if (!script->bindings.initWithTemporaryStorage(cx, numArgs, numVars, bindingArray))
+        InternalHandle<Bindings*> bindings(script, &script->bindings);
+        if (!Bindings::initWithTemporaryStorage(cx, bindings, numArgs, numVars, bindingArray))
             return false;
     }
 
     return true;
 }
 
 bool
 Bindings::bindingIsAliased(unsigned bindingIndex)
@@ -2073,18 +2079,19 @@ js::CloneScript(JSContext *cx, HandleObj
 
     uint8_t *data = AllocScriptData(cx, size);
     if (!data)
         return NULL;
 
     /* Bindings */
 
     Bindings bindings;
-    Bindings::AutoRooter bindingRooter(cx, &bindings);
-    if (!bindings.clone(cx, data, src))
+    InternalHandle<Bindings*> bindingsHandle =
+        InternalHandle<Bindings*>::fromMarkedLocation(&bindings);
+    if (!Bindings::clone(cx, bindingsHandle, data, src))
         return NULL;
 
     /* Objects */
 
     AutoObjectVector objects(cx);
     if (nobjects != 0) {
         HeapPtrObject *vector = src->objects()->vector;
         for (unsigned i = 0; i < nobjects; i++) {
@@ -2139,16 +2146,17 @@ js::CloneScript(JSContext *cx, HandleObj
            .setVersion(src->getVersion());
     JSScript *dst = JSScript::Create(cx, enclosingScope, src->savedCallerFun,
                                      options, src->staticLevel,
                                      src->scriptSource(), src->sourceStart, src->sourceEnd);
     if (!dst) {
         js_free(data);
         return NULL;
     }
+    AutoAssertNoGC nogc;
 
     dst->bindings = bindings;
 
     /* This assignment must occur before all the Rebase calls. */
     dst->data = data;
     memcpy(data, src->data, size);
 
     dst->code = Rebase<jsbytecode>(dst, src, src->code);
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -163,24 +163,27 @@ class Bindings
     inline Bindings();
 
     /*
      * Initialize a Bindings with a pointer into temporary storage.
      * bindingArray must have length numArgs+numVars. Before the temporary
      * storage is release, switchToScriptStorage must be called, providing a
      * pointer into the Binding array stored in script->data.
      */
-    bool initWithTemporaryStorage(JSContext *cx, unsigned numArgs, unsigned numVars, Binding *bindingArray);
+    static bool initWithTemporaryStorage(JSContext *cx, InternalHandle<Bindings*> self,
+                                         unsigned numArgs, unsigned numVars,
+                                         Binding *bindingArray);
+
     uint8_t *switchToScriptStorage(Binding *newStorage);
 
     /*
      * Clone srcScript's bindings (as part of js::CloneScript). dstScriptData
      * is the pointer to what will eventually be dstScript->data.
      */
-    bool clone(JSContext *cx, uint8_t *dstScriptData, HandleScript srcScript);
+    static bool clone(JSContext *cx, InternalHandle<Bindings*> self, uint8_t *dstScriptData, HandleScript srcScript);
 
     unsigned numArgs() const { return numArgs_; }
     unsigned numVars() const { return numVars_; }
     unsigned count() const { return numArgs() + numVars(); }
 
     /* Return the initial shape of call objects created for this scope. */
     Shape *callObjShape() const { return callObjShape_; }
 
@@ -189,36 +192,16 @@ class Bindings
 
     /* Return whether the binding at bindingIndex is aliased. */
     bool bindingIsAliased(unsigned bindingIndex);
 
     /* Return whether this scope has any aliased bindings. */
     bool hasAnyAliasedBindings() const { return !callObjShape_->isEmptyShape(); }
 
     void trace(JSTracer *trc);
-    class AutoRooter;
-};
-
-class Bindings::AutoRooter : private AutoGCRooter
-{
-  public:
-    explicit AutoRooter(JSContext *cx, Bindings *bindings_
-                        JS_GUARD_OBJECT_NOTIFIER_PARAM)
-      : AutoGCRooter(cx, BINDINGS), bindings(bindings_), skip(cx, bindings_)
-    {
-        JS_GUARD_OBJECT_NOTIFIER_INIT;
-    }
-
-    friend void AutoGCRooter::trace(JSTracer *trc);
-    void trace(JSTracer *trc);
-
-  private:
-    Bindings *bindings;
-    SkipRoot skip;
-    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 class ScriptCounts
 {
     friend struct ::JSScript;
     friend struct ScriptAndCounts;
     /*
      * This points to a single block that holds an array of PCCounts followed
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3538,17 +3538,17 @@ RelaxRootChecks(JSContext *cx, unsigned 
 {
     if (argc > 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS,
                              "relaxRootChecks");
         return false;
     }
 
 #ifdef DEBUG
-    cx->runtime->relaxRootChecks = true;
+    cx->runtime->gcRelaxRootChecks = true;
 #endif
 
     return true;
 }
 
 static JSBool
 GetMaxArgs(JSContext *cx, unsigned arg, jsval *vp)
 {
--- a/js/xpconnect/src/XPCWrapper.cpp
+++ b/js/xpconnect/src/XPCWrapper.cpp
@@ -2,17 +2,19 @@
 /* vim: set ts=2 sw=2 et tw=78: */
 /* 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 "XPCWrapper.h"
 #include "AccessCheck.h"
 #include "WrapperFactory.h"
+#include "AccessCheck.h"
 
+using namespace xpc;
 namespace XPCNativeWrapper {
 
 static inline
 JSBool
 ThrowException(nsresult ex, JSContext *cx)
 {
   XPCThrower::Throw(ex, cx);
 
@@ -32,18 +34,17 @@ UnwrapNW(JSContext *cx, unsigned argc, j
   }
 
   JSObject *obj = JSVAL_TO_OBJECT(v);
   if (!js::IsWrapper(obj)) {
     JS_SET_RVAL(cx, vp, v);
     return true;
   }
 
-  if (xpc::WrapperFactory::IsXrayWrapper(obj) &&
-      !xpc::WrapperFactory::IsPartiallyTransparent(obj)) {
+  if (WrapperFactory::IsXrayWrapper(obj) && AccessCheck::isChrome(obj)) {
     return JS_GetProperty(cx, obj, "wrappedJSObject", vp);
   }
 
   JS_SET_RVAL(cx, vp, v);
   return true;
 }
 
 static JSBool
--- a/js/xpconnect/src/dictionary_helper_gen.conf
+++ b/js/xpconnect/src/dictionary_helper_gen.conf
@@ -5,17 +5,16 @@
 # Dictionary interface name, interface file name
 dictionaries = [
      [ 'EventInit', 'nsIDOMEvent.idl' ],
      [ 'UIEventInit', 'nsIDOMUIEvent.idl' ],
      [ 'MouseEventInit', 'nsIDOMMouseEvent.idl' ],
      [ 'WheelEventInit', 'nsIDOMWheelEvent.idl' ],
      [ 'IDBObjectStoreParameters', 'nsIIDBDatabase.idl' ],
      [ 'IDBIndexParameters', 'nsIIDBObjectStore.idl' ],
-     [ 'BlobPropertyBag', 'nsIDOMFile.idl' ],
      [ 'MutationObserverInit', 'nsIDOMMutationObserver.idl' ],
      [ 'WifiConnectionInfoEventInit', 'nsIWifiEventInits.idl' ],
      [ 'WifiStatusChangeEventInit', 'nsIWifiEventInits.idl' ],
      [ 'GeoPositionOptions', 'nsIDOMGeoGeolocation.idl' ],
      [ 'DOMFileMetadataParameters', 'nsIDOMLockedFile.idl' ],
      [ 'XMLHttpRequestParameters', 'nsIXMLHttpRequest.idl' ],
      [ 'DeviceStorageEnumerationParameters', 'nsIDOMDeviceStorage.idl' ],
      [ 'CameraSize', 'nsIDOMCameraManager.idl' ],
--- a/js/xpconnect/src/dictionary_helper_gen.py
+++ b/js/xpconnect/src/dictionary_helper_gen.py
@@ -407,28 +407,26 @@ def write_cpp(iface, fd):
         fd.write("  if (found) {\n")
         write_getter(a, iface, fd)
         fd.write("  }\n")
     fd.write("  return NS_OK;\n")
     fd.write("}\n\n")
     
     fd.write("nsresult\n%s::Init(JSContext* aCx, const jsval* aVal)\n" % iface.name)
     fd.write("{\n"
+             "  MOZ_ASSERT(NS_IsMainThread());\n"
              "  if (!aCx || !aVal) {\n"
              "    return NS_OK;\n"
              "  }\n"
              "  if (!aVal->isObject()) {\n"
              "    return aVal->isNullOrUndefined() ? NS_OK : NS_ERROR_TYPE_ERR;\n"
              "  }\n\n"
              "  JSObject* obj = &aVal->toObject();\n"
-             "  Maybe<nsCxPusher> pusher;\n"
-             "  if (NS_IsMainThread()) {\n"
-             "    pusher.construct();\n"
-             "    NS_ENSURE_STATE(pusher.ref().Push(aCx, false));\n"
-             "  }\n"
+             "  nsCxPusher pusher;\n"
+             "  NS_ENSURE_STATE(pusher.Push(aCx, false));\n"
              "  JSAutoRequest ar(aCx);\n"
              "  JSAutoCompartment ac(aCx, obj);\n")
 
     fd.write("  return %s_InitInternal(*this, aCx, obj);\n}\n\n" %
                  iface.name)
 
 
 if __name__ == '__main__':
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -424,19 +424,16 @@ members = [
     '-nsIXMLHttpRequest.getAllResponseHeaders',
     '-nsIXMLHttpRequest.getResponseHeader',
     '-nsIXMLHttpRequest.setRequestHeader',
     '-nsIXMLHttpRequest.overrideMimeType',
     # nsIXMLHttpRequestUpload doesn't live in its own IDL file, so
     # can't be quickstubbed
     '-nsIXMLHttpRequest.upload',
 
-    # WebSocket
-    'nsIWebSocket.*',
-
     # webgl
     'nsIDOMWebGLRenderingContext.*',
     # getContextAttributes is directly manipulating its return value
     '-nsIDOMWebGLRenderingContext.getContextAttributes',
 
     # Audio
     'nsIDOMNotifyAudioAvailableEvent.frameBuffer',
     'nsIDOMNotifyAudioAvailableEvent.time',
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -4375,38 +4375,48 @@ GetCompartmentPrivate(JSObject *object)
 {
     MOZ_ASSERT(object);
     JSCompartment *compartment = js::GetObjectCompartment(object);
 
     MOZ_ASSERT(compartment);
     return GetCompartmentPrivate(compartment);
 }
 
-inline bool IsUniversalXPConnectEnabled(JSContext *cx)
+inline bool IsUniversalXPConnectEnabled(JSCompartment *compartment)
 {
-    JSCompartment *compartment = js::GetContextCompartment(cx);
-    if (!compartment)
-        return false;
     CompartmentPrivate *priv =
       static_cast<CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
     if (!priv)
         return false;
     return priv->universalXPConnectEnabled;
 }
 
-inline void EnableUniversalXPConnect(JSContext *cx)
+inline bool IsUniversalXPConnectEnabled(JSContext *cx)
+{
+    JSCompartment *compartment = js::GetContextCompartment(cx);
+    if (!compartment)
+        return false;
+    return IsUniversalXPConnectEnabled(compartment);
+}
+
+inline bool EnableUniversalXPConnect(JSContext *cx)
 {
     JSCompartment *compartment = js::GetContextCompartment(cx);
     if (!compartment)
-        return;
+        return true;
     CompartmentPrivate *priv =
       static_cast<CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
     if (!priv)
-        return;
+        return true;
     priv->universalXPConnectEnabled = true;
+
+    // Recompute all the cross-compartment wrappers leaving the newly-privileged
+    // compartment.
+    return js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
+                                 js::AllCompartments());
 }
 
 }
 
 /***************************************************************************/
 // Inlines use the above - include last.
 
 #include "XPCInlines.h"
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -47,16 +47,26 @@ AccessCheck::subsumes(JSCompartment *a, 
 
     bool subsumes;
     nsresult rv = aprin->Subsumes(bprin, &subsumes);
     NS_ENSURE_SUCCESS(rv, false);
 
     return subsumes;
 }
 
+// Does the compartment of the wrapper subsumes the compartment of the wrappee?
+bool
+AccessCheck::wrapperSubsumes(JSObject *wrapper)
+{
+    MOZ_ASSERT(js::IsWrapper(wrapper));
+    JSObject *wrapped = js::UnwrapObject(wrapper);
+    return AccessCheck::subsumes(js::GetObjectCompartment(wrapper),
+                                 js::GetObjectCompartment(wrapped));
+}
+
 bool
 AccessCheck::isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper)
 {
     // The caller must ensure that the given wrapper wraps a Location object.
     MOZ_ASSERT(WrapperFactory::IsLocationObject(js::UnwrapObject(wrapper)));
 
     // Location objects are parented to the outer window for which they
     // were created. This gives us an easy way to determine whether our
@@ -87,16 +97,22 @@ AccessCheck::isChrome(JSCompartment *com
     }
 
     bool privileged;
     nsIPrincipal *principal = GetCompartmentPrincipal(compartment);
     return NS_SUCCEEDED(ssm->IsSystemPrincipal(principal, &privileged)) && privileged;
 }
 
 bool
+AccessCheck::isChrome(JSObject *obj)
+{
+    return isChrome(js::GetObjectCompartment(obj));
+}
+
+bool
 AccessCheck::callerIsChrome()
 {
     nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
     if (!ssm)
         return false;
     bool subjectIsSystem;
     nsresult rv = ssm->SubjectPrincipalIsSystem(&subjectIsSystem);
     return NS_SUCCEEDED(rv) && subjectIsSystem;
@@ -200,17 +216,17 @@ AccessCheck::isCrossOriginAccessPermitte
 
     if (act == Wrapper::CALL)
         return true;
 
     JSObject *obj = Wrapper::wrappedObject(wrapper);
 
     // PUNCTURE Is always denied for cross-origin access.
     if (act == Wrapper::PUNCTURE) {
-        return nsContentUtils::CallerHasUniversalXPConnect();
+        return false;
     }
 
     const char *name;
     js::Class *clasp = js::GetObjectClass(obj);
     NS_ASSERTION(Jsvalify(clasp) != &XrayUtils::HolderClass, "shouldn't have a holder here");
     if (clasp->ext.innerObject)
         name = "Window";
     else
@@ -265,17 +281,17 @@ AccessCheck::isSystemOnlyAccessPermitted
     static const char prefix[] = "chrome://global/";
     const char *filename;
     if (script &&
         (filename = JS_GetScriptFilename(cx, script)) &&
         !strncmp(filename, prefix, ArrayLength(prefix) - 1)) {
         return true;
     }
 
-    return NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) && privileged;
+    return false;
 }
 
 bool
 AccessCheck::needsSystemOnlyWrapper(JSObject *obj)
 {
     if (!IS_WN_WRAPPER(obj))
         return false;
 
@@ -290,28 +306,17 @@ AccessCheck::isScriptAccessOnly(JSContex
 
     unsigned flags;
     JSObject *obj = js::UnwrapObject(wrapper, true, &flags);
 
     // If the wrapper indicates script-only access, we are done.
     if (flags & WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG) {
         if (flags & WrapperFactory::SOW_FLAG)
             return !isSystemOnlyAccessPermitted(cx);
-
-        if (flags & WrapperFactory::PARTIALLY_TRANSPARENT)
-            return !XrayUtils::IsTransparent(cx, wrapper);
-
-        nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
-        if (!ssm)
-            return true;
-
-        // Bypass script-only status if UniversalXPConnect is enabled.
-        bool privileged;
-        return !NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) ||
-               !privileged;
+        return true;
     }
 
     // In addition, chrome objects can explicitly opt-in by setting .scriptOnly to true.
     if (js::GetProxyHandler(wrapper) ==
         &FilteringWrapper<CrossCompartmentSecurityWrapper,
         CrossOriginAccessiblePropertiesOnly>::singleton) {
         jsid scriptOnlyId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_SCRIPTONLY);
         jsval scriptOnly;
@@ -351,43 +356,16 @@ Deny(JSContext *cx, jsid id, Wrapper::Ac
     // Refuse to perform the action and just return the default value.
     if (act == Wrapper::GET)
         return true;
     // If its a set, deny it and throw an exception.
     AccessCheck::deny(cx, id);
     return false;
 }
 
-bool
-PermitIfUniversalXPConnect(JSContext *cx, jsid id, Wrapper::Action act,
-                           ExposedPropertiesOnly::Permission &perm)
-{
-    // If UniversalXPConnect is enabled, allow access even if __exposedProps__ doesn't
-    // exists.
-    nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
-    if (!ssm) {
-        return false;
-    }
-
-    // Double-check that the subject principal according to CAPS is a content
-    // principal rather than the system principal. If it isn't, this check is
-    // meaningless.
-    NS_ASSERTION(!AccessCheck::callerIsChrome(), "About to do a meaningless security check!");
-
-    bool privileged;
-    if (NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) &&
-        privileged) {
-        perm = ExposedPropertiesOnly::PermitPropertyAccess;
-        return true; // Allow
-    }
-
-    // Deny
-    return Deny(cx, id, act);
-}
-
 static bool
 IsInSandbox(JSContext *cx, JSObject *obj)
 {
     JSAutoCompartment ac(cx, obj);
     JSObject *global = JS_GetGlobalForObject(cx, obj);
     return !strcmp(js::GetObjectJSClass(global)->name, "Sandbox");
 }
 
@@ -399,22 +377,22 @@ ExposedPropertiesOnly::check(JSContext *
 
     if (act == Wrapper::CALL) {
         perm = PermitObjectAccess;
         return true;
     }
 
     perm = DenyAccess;
     if (act == Wrapper::PUNCTURE)
-        return PermitIfUniversalXPConnect(cx, id, act, perm); // Deny
+        return Deny(cx, id, act);
 
     jsid exposedPropsId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS);
 
     // We need to enter the wrappee's compartment to look at __exposedProps__,
-    // but we need to be in the wrapper's compartment to check UniversalXPConnect.
+    // but we want to be in the wrapper's compartment if we call Deny().
     //
     // Unfortunately, |cx| can be in either compartment when we call ::check. :-(
     JSAutoCompartment ac(cx, wrappedObject);
 
     JSBool found = false;
     if (!JS_HasPropertyById(cx, wrappedObject, exposedPropsId, &found))
         return false;
 
@@ -446,32 +424,32 @@ ExposedPropertiesOnly::check(JSContext *
                     doc->WarnOnceAbout(nsIDocument::eNoExposedProps,
                                        /* asError = */ true);
                 }
             }
 
             perm = PermitPropertyAccess;
             return true;
         }
-        return PermitIfUniversalXPConnect(cx, id, act, perm); // Deny
+        return Deny(cx, id, act);
     }
 
     if (id == JSID_VOID) {
         // This will force the caller to call us back for individual property accesses.
         perm = PermitPropertyAccess;
         return true;
     }
 
     JS::Value exposedProps;
     if (!JS_LookupPropertyById(cx, wrappedObject, exposedPropsId, &exposedProps))
         return false;
 
     if (exposedProps.isNullOrUndefined()) {
         JSAutoCompartment wrapperAC(cx, wrapper);
-        return PermitIfUniversalXPConnect(cx, id, act, perm); // Deny
+        return Deny(cx, id, act);
     }
 
     if (!exposedProps.isObject()) {
         JS_ReportError(cx, "__exposedProps__ must be undefined, null, or an Object");
         return false;
     }
 
     JSObject *hallpass = &exposedProps.toObject();
@@ -480,17 +458,17 @@ ExposedPropertiesOnly::check(JSContext *
 
     JSPropertyDescriptor desc;
     memset(&desc, 0, sizeof(desc));
     if (!JS_GetPropertyDescriptorById(cx, hallpass, id, JSRESOLVE_QUALIFIED, &desc)) {
         return false; // Error
     }
     if (desc.obj == NULL || !(desc.attrs & JSPROP_ENUMERATE)) {
         JSAutoCompartment wrapperAC(cx, wrapper);
-        return PermitIfUniversalXPConnect(cx, id, act, perm); // Deny
+        return Deny(cx, id, act);
     }
 
     if (!JSVAL_IS_STRING(desc.value)) {
         JS_ReportError(cx, "property must be a string");
         return false;
     }
 
     JSString *str = JSVAL_TO_STRING(desc.value);
@@ -526,17 +504,17 @@ ExposedPropertiesOnly::check(JSContext *
     if (access == NO_ACCESS) {
         JS_ReportError(cx, "specified properties must have a permission bit set");
         return false;
     }
 
     if ((act == Wrapper::SET && !(access & WRITE)) ||
         (act != Wrapper::SET && !(access & READ))) {
         JSAutoCompartment wrapperAC(cx, wrapper);
-        return PermitIfUniversalXPConnect(cx, id, act, perm); // Deny
+        return Deny(cx, id, act);
     }
 
     perm = PermitPropertyAccess;
     return true; // Allow
 }
 
 bool
 ComponentsObjectPolicy::check(JSContext *cx, JSObject *wrapper, jsid id, Wrapper::Action act,
@@ -553,12 +531,20 @@ ComponentsObjectPolicy::check(JSContext 
             JS_FlatStringEqualsAscii(flatId, "interfacesByID") ||
             JS_FlatStringEqualsAscii(flatId, "results"))
         {
             perm = PermitPropertyAccess;
             return true;
         }
     }
 
-    return PermitIfUniversalXPConnect(cx, id, act, perm);  // Deny
+    // We don't have any way to recompute same-compartment Components wrappers,
+    // so we need this dynamic check. This can go away when we expose Components
+    // as SpecialPowers.wrap(Components) during automation.
+    if (xpc::IsUniversalXPConnectEnabled(cx)) {
+        perm = PermitPropertyAccess;
+        return true;
+    }
+
+    return Deny(cx, id, act);
 }
 
 }
--- a/js/xpconnect/wrappers/AccessCheck.h
+++ b/js/xpconnect/wrappers/AccessCheck.h
@@ -14,17 +14,19 @@
 
 class nsIPrincipal;
 
 namespace xpc {
 
 class AccessCheck {
   public:
     static bool subsumes(JSCompartment *a, JSCompartment *b);
+    static bool wrapperSubsumes(JSObject *wrapper);
     static bool isChrome(JSCompartment *compartment);
+    static bool isChrome(JSObject *obj);
     static bool callerIsChrome();
     static nsIPrincipal *getPrincipal(JSCompartment *compartment);
     static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id,
                                              js::Wrapper::Action act);
     static bool isSystemOnlyAccessPermitted(JSContext *cx);
     static bool isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper);
 
     static bool needsSystemOnlyWrapper(JSObject *obj);
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -120,24 +120,20 @@ FilteringWrapper<Base, Policy>::enter(JS
 #define CW FilteringWrapper<SameCompartmentSecurityWrapper, \
                             ComponentsObjectPolicy>
 #define XCW FilteringWrapper<CrossCompartmentSecurityWrapper, \
                             ComponentsObjectPolicy>
 template<> SOW SOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                               WrapperFactory::SOW_FLAG);
 template<> SCSOW SCSOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                                   WrapperFactory::SOW_FLAG);
-template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
-                              WrapperFactory::PARTIALLY_TRANSPARENT);
-template<> PXOW PXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
-                                WrapperFactory::PARTIALLY_TRANSPARENT);
-template<> DXOW DXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
-                                WrapperFactory::PARTIALLY_TRANSPARENT);
-template<> NNXOW NNXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
-                                  WrapperFactory::PARTIALLY_TRANSPARENT);
+template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
+template<> PXOW PXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
+template<> DXOW DXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
+template<> NNXOW NNXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
 template<> LW  LW::singleton(WrapperFactory::SHADOWING_FORBIDDEN);
 template<> XLW XLW::singleton(WrapperFactory::SHADOWING_FORBIDDEN);
 
 template<> CW CW::singleton(0);
 template<> XCW XCW::singleton(0);
 
 template class SOW;
 template class XOW;
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -344,16 +344,18 @@ WrapperFactory::Rewrap(JSContext *cx, JS
                     typedef XrayWrapper<CrossCompartmentWrapper> Xray;
                     usingXray = true;
                     wrapper = &Xray::singleton;
                 } else {
                     wrapper = &CrossCompartmentWrapper::singleton;
                 }
             }
         }
+    } else if (xpc::IsUniversalXPConnectEnabled(target)) {
+        wrapper = &CrossCompartmentWrapper::singleton;
     } else if (AccessCheck::isChrome(origin)) {
         JSFunction *fun = JS_GetObjectFunction(obj);
         if (fun) {
             if (JS_IsBuiltinEvalFunction(fun) || JS_IsBuiltinFunctionConstructor(fun)) {
                 JS_ReportError(cx, "Not allowed to access chrome eval or Function from content");
                 return nullptr;
             }
         }
--- a/js/xpconnect/wrappers/WrapperFactory.h
+++ b/js/xpconnect/wrappers/WrapperFactory.h
@@ -13,18 +13,17 @@
 
 namespace xpc {
 
 class WrapperFactory {
   public:
     enum { WAIVE_XRAY_WRAPPER_FLAG = js::Wrapper::LAST_USED_FLAG << 1,
            IS_XRAY_WRAPPER_FLAG    = WAIVE_XRAY_WRAPPER_FLAG << 1,
            SCRIPT_ACCESS_ONLY_FLAG = IS_XRAY_WRAPPER_FLAG << 1,
-           PARTIALLY_TRANSPARENT   = SCRIPT_ACCESS_ONLY_FLAG << 1,
-           SOW_FLAG                = PARTIALLY_TRANSPARENT << 1,
+           SOW_FLAG                = SCRIPT_ACCESS_ONLY_FLAG << 1,
 
            // Prevent scripts from shadowing native properties.
            // NB: Applies only to Xray wrappers.
            // NB: This will prevent scriptable helpers from defining special
            //     handlers for properties defined in IDL. Use with caution.
            SHADOWING_FORBIDDEN     = SOW_FLAG << 1 };
 
     // Return true if any of any of the nested wrappers have the flag set.
@@ -33,20 +32,16 @@ class WrapperFactory {
         js::UnwrapObject(wrapper, true, &flags);
         return !!(flags & flag);
     }
 
     static bool IsXrayWrapper(JSObject *wrapper) {
         return HasWrapperFlag(wrapper, IS_XRAY_WRAPPER_FLAG);
     }
 
-    static bool IsPartiallyTransparent(JSObject *wrapper) {
-        return HasWrapperFlag(wrapper, PARTIALLY_TRANSPARENT);
-    }
-
     static bool HasWaiveXrayFlag(JSObject *wrapper) {
         return HasWrapperFlag(wrapper, WAIVE_XRAY_WRAPPER_FLAG);
     }
 
     static bool IsShadowingForbidden(JSObject *wrapper) {
         return HasWrapperFlag(wrapper, SHADOWING_FORBIDDEN);
     }
 
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -905,49 +905,31 @@ nodePrincipal_getter(JSContext *cx, JSHa
                                                            vp.address(), nullptr);
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
         return false;
     }
     return true;
 }
 
-static bool
-ContentScriptHasUniversalXPConnect()
-{
-    nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
-    if (ssm) {
-        // Double-check that the subject principal according to CAPS is a content
-        // principal rather than the system principal. If it is, this check is
-        // meaningless.
-        NS_ASSERTION(!AccessCheck::callerIsChrome(), "About to do a meaningless security check!");
-
-        bool privileged;
-        if (NS_SUCCEEDED(ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged)) && privileged)
-            return true;
-    }
-    return false;
-}
-
 bool
 XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, js::Wrapper &jsWrapper,
                                                JSObject *wrapper, JSObject *holder, jsid id,
                                                bool set, PropertyDescriptor *desc)
 {
     // Xray wrappers don't use the regular wrapper hierarchy, so we should be
     // in the wrapper's compartment here, not the wrappee.
     MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
-    if (!WrapperFactory::IsPartiallyTransparent(wrapper) &&
+    if (AccessCheck::isChrome(wrapper) &&
         (((id == rt->GetStringID(XPCJSRuntime::IDX_BASEURIOBJECT) ||
            id == rt->GetStringID(XPCJSRuntime::IDX_NODEPRINCIPAL)) &&
           Is<nsINode>(wrapper)) ||
           (id == rt->GetStringID(XPCJSRuntime::IDX_DOCUMENTURIOBJECT) &&
-          Is<nsIDocument>(wrapper))) &&
-        (AccessCheck::callerIsChrome() || ContentScriptHasUniversalXPConnect())) {
+          Is<nsIDocument>(wrapper)))) {
         bool status;
         Wrapper::Action action = set ? Wrapper::SET : Wrapper::GET;
         desc->obj = NULL; // default value
         if (!jsWrapper.enter(cx, wrapper, id, action, &status))
             return status;
 
         desc->obj = wrapper;
         desc->attrs = JSPROP_ENUMERATE|JSPROP_SHARED;
@@ -1293,26 +1275,17 @@ XrayWrapper<Base, Traits>::~XrayWrapper(
 {
 }
 
 namespace XrayUtils {
 
 bool
 IsTransparent(JSContext *cx, JSObject *wrapper)
 {
-    if (WrapperFactory::HasWaiveXrayFlag(wrapper))
-        return true;
-
-    if (!WrapperFactory::IsPartiallyTransparent(wrapper))
-        return false;
-
-    // Redirect access straight to the wrapper if UniversalXPConnect is enabled.
-    // We don't need to check for system principal here, because only content
-    // scripts have Partially Transparent wrappers.
-    return ContentScriptHasUniversalXPConnect();
+    return WrapperFactory::HasWaiveXrayFlag(wrapper);
 }
 
 JSObject *
 GetNativePropertiesObject(JSContext *cx, JSObject *wrapper)
 {
     NS_ASSERTION(js::IsWrapper(wrapper) && WrapperFactory::IsXrayWrapper(wrapper),
                  "bad object passed in");
 
@@ -1409,20 +1382,21 @@ XrayWrapper<Base, Traits>::getPropertyDe
         if (desc->obj)
             desc->obj = wrapper;
         return JS_WrapPropertyDescriptor(cx, desc);
     }
 
     if (!holder)
         return false;
 
-    // Partially transparent wrappers (which used to be known as XOWs) don't
-    // have a .wrappedJSObject property.
+    // Only chrome wrappers and same-origin xrays (used by jetpack sandboxes)
+    // get .wrappedJSObject. We can check this by determining if the compartment
+    // of the wrapper subsumes that of the wrappee.
     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
-    if (!WrapperFactory::IsPartiallyTransparent(wrapper) &&
+    if (AccessCheck::wrapperSubsumes(wrapper) &&
         id == rt->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT)) {
         bool status;
         Wrapper::Action action = set ? Wrapper::SET : Wrapper::GET;
         desc->obj = NULL; // default value
         if (!this->enter(cx, wrapper, id, action, &status))
             return status;
 
         desc->obj = wrapper;
@@ -1603,17 +1577,17 @@ XrayWrapper<Base, Traits>::enumerate(JSC
 {
     // Redirect access straight to the wrapper if we should be transparent.
     if (XrayUtils::IsTransparent(cx, wrapper)) {
         JSObject *obj = Traits::getInnerObject(wrapper);
         JSAutoCompartment ac(cx, obj);
         return js::GetPropertyNames(cx, obj, flags, &props);
     }
 
-    if (WrapperFactory::IsPartiallyTransparent(wrapper)) {
+    if (!AccessCheck::wrapperSubsumes(wrapper)) {
         JS_ReportError(cx, "Not allowed to enumerate cross origin objects");
         return false;
     }
 
     return Traits::enumerateNames(cx, wrapper, flags, props);
 }
 
 template <typename Base, typename Traits>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -2,17 +2,17 @@ load 46043-1.html
 load 47843-1.html
 load 49122-1.html
 load 50257-1.html
 load 50395-1.html
 load 56746-1.html
 load 89101-1.html
 load 89358-1.html
 load 90205-1.html
-load 99776-1.html
+skip-if(isDebugBuild&&(OSX==10.7||OSX==10.8)) load 99776-1.html # 10.7 and 10.8 leaks are bug 705570
 load 118931-1.html
 load 121533-1.html
 load 123049-1.html
 load 123946-1.html
 load 128855-1.html
 load 133410-1.html
 load 143862-1a.html
 load 143862-1b.html
@@ -36,17 +36,17 @@ load 243519-1.html
 load 244490-1.html
 load 254367-1.html
 load 263359-1.html
 load 265027-1.html
 load 265736-1.html
 load 265736-2.html
 load 265899-1.html
 load 265973-1.html
-asserts(6-12) load 265986-1.html # Bug 512405
+asserts(6-12) skip-if(isDebugBuild&&(OSX==10.7||OSX==10.8)) load 265986-1.html # Bug 512405 for assertions, bug 705570 for 10.7 and 10.8 leaks
 load 265999-1.html
 load 266222-1.html
 asserts(3-7) load 266360-1.html # bug 575011 / bug 576358
 asserts(4) load 266445-1.html # Bug 575011
 load 268157-1.html
 load 269566-1.html
 load 272647-1.html
 load 275746-1.html
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1037,20 +1037,32 @@ nsLayoutUtils::GetEventCoordinatesRelati
   }
 
   const nsGUIEvent* GUIEvent = static_cast<const nsGUIEvent*>(aEvent);
   nsIWidget* widget = GUIEvent->widget;
   if (!widget) {
     return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
   }
 
+  return GetEventCoordinatesRelativeTo(widget, aPoint, aFrame);
+}
+
+nsPoint
+nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
+                                             const nsIntPoint aPoint,
+                                             nsIFrame* aFrame)
+{
+  if (!aFrame || !aWidget) {
+    return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
+  }
+
   nsIView* view = aFrame->GetView();
   if (view) {
     nsIWidget* frameWidget = view->GetWidget();
-    if (frameWidget && frameWidget == GUIEvent->widget) {
+    if (frameWidget && frameWidget == aWidget) {
       // Special case this cause it happens a lot.
       // This also fixes bug 664707, events in the extra-special case of select
       // dropdown popups that are transformed.
       nsPresContext* presContext = aFrame->PresContext();
       nsPoint pt(presContext->DevPixelsToAppUnits(aPoint.x),
                  presContext->DevPixelsToAppUnits(aPoint.y));
       return pt - view->ViewToWidgetOffset();
     }
@@ -1071,17 +1083,17 @@ nsLayoutUtils::GetEventCoordinatesRelati
   }
 
   nsIView* rootView = rootFrame->GetView();
   if (!rootView) {
     return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
   }
 
   nsPoint widgetToView = TranslateWidgetToView(rootFrame->PresContext(),
-                               widget, aPoint, rootView);
+                                               aWidget, aPoint, rootView);
 
   if (widgetToView == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) {
     return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
   }
 
   // Convert from root document app units to app units of the document aFrame
   // is in.
   int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -412,16 +412,30 @@ public:
    * for some reason the coordinates for the mouse are not known (e.g.,
    * the event is not a GUI event).
    */
   static nsPoint GetEventCoordinatesRelativeTo(const nsEvent* aEvent,
                                                const nsIntPoint aPoint,
                                                nsIFrame* aFrame);
 
   /**
+   * Get the coordinates of a given point relative to a widget and a
+   * given frame.
+   * @param aWidget the event src widget
+   * @param aPoint the point to get the coordinates relative to
+   * @param aFrame the frame to make coordinates relative to
+   * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
+   * for some reason the coordinates for the mouse are not known (e.g.,
+   * the event is not a GUI event).
+   */
+  static nsPoint GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
+                                               const nsIntPoint aPoint,
+                                               nsIFrame* aFrame);
+
+  /**
    * Get the popup frame of a given native mouse event.
    * @param aPresContext only check popups within aPresContext or a descendant
    * @param aEvent  the event.
    * @return        Null, if there is no popup frame at the point, otherwise,
    *                returns top-most popup frame at the point.
    */
   static nsIFrame* GetPopupFrameForEventCoordinates(nsPresContext* aPresContext,
                                                     const nsEvent* aEvent);
--- a/layout/base/tests/bug585922-ref.html
+++ b/layout/base/tests/bug585922-ref.html
@@ -2,23 +2,20 @@
 <html class="reftest-wait">
   <head>
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body onload="doTest()">
     <input type=text>
     <script>
       function doTest() {
-        netscape.security.PrivilegeManager.enablePrivilege(
-          "UniversalXPConnect");
-
         var d = document.querySelector("input");
         d.value = "b";
         d.focus();
-        var editor = d.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
+        var editor = SpecialPowers.wrap(d).QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
         var sel = editor.selection;
         var t = editor.rootElement.firstChild;
         sel.collapse(t, 1); // put the caret at the end of the textbox
         document.documentElement.removeAttribute("class");
       }
     </script>
   </body>
 </html>
--- a/layout/base/tests/bug585922.html
+++ b/layout/base/tests/bug585922.html
@@ -2,33 +2,29 @@
 <html class="reftest-wait">
   <head>
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body onload="doTest()">
     <input type=text>
     <script>
       function doTest() {
-        netscape.security.PrivilegeManager.enablePrivilege(
-          "UniversalXPConnect");
         function enableCaret(aEnable) {
           var selCon = editor.selectionController;
           selCon.setCaretEnabled(aEnable);
         }
 
         var d = document.querySelector("input");
         d.value = "a";
         d.focus();
-        var editor = d.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
+        var editor = SpecialPowers.wrap(d).QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
         var sel = editor.selection;
         var t = editor.rootElement.firstChild;
         sel.collapse(t, 1); // put the caret at the end of the div
         setTimeout(function() {
-          netscape.security.PrivilegeManager.enablePrivilege(
-            "UniversalXPConnect");
           enableCaret(false);enableCaret(true);// force a caret display
           enableCaret(false); // hide the caret
           t.replaceData(0, 1, "b"); // replace the text node data
           // at this point, the selection is collapsed to offset 0
           synthesizeQuerySelectedText(); // call nsCaret::GetGeometry
           sel.collapse(t, 1); // put the caret at the end again
           enableCaret(true); // show the caret again
           document.documentElement.removeAttribute("class");
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -60,17 +60,16 @@
 #include "nsXPathEvaluator.h"
 #include "txMozillaXSLTProcessor.h"
 #include "txNodeSetAdaptor.h"
 
 #include "nsDOMParser.h"
 #include "nsDOMSerializer.h"
 #include "nsXMLHttpRequest.h"
 #include "nsChannelPolicy.h"
-#include "nsWebSocket.h"
 #include "nsEventSource.h"
 
 // view stuff
 #include "nsViewsCID.h"
 #include "nsViewManager.h"
 #include "nsContentCreatorFunctions.h"
 
 // DOM includes
@@ -258,17 +257,16 @@ using mozilla::dom::alarm::AlarmHalServi
 
 // Factory Constructor
 NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor)
 NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(nsXPathEvaluator, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsEventSource)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebSocket)
 NS_GENERIC_FACTORY_CONSTRUCTOR(Activity)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDOMFileReader, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(ArchiveReader)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormData)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlobProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlobURI)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMParser)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDOMStorageManager,
@@ -748,17 +746,16 @@ NS_DEFINE_NAMED_CID(TRANSFORMIIX_NODESET
 NS_DEFINE_NAMED_CID(NS_XMLSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_FILEREADER_CID);
 NS_DEFINE_NAMED_CID(NS_ARCHIVEREADER_CID);
 NS_DEFINE_NAMED_CID(NS_FORMDATA_CID);
 NS_DEFINE_NAMED_CID(NS_BLOBPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_BLOBURI_CID);
 NS_DEFINE_NAMED_CID(NS_XMLHTTPREQUEST_CID);
 NS_DEFINE_NAMED_CID(NS_EVENTSOURCE_CID);
-NS_DEFINE_NAMED_CID(NS_WEBSOCKET_CID);
 NS_DEFINE_NAMED_CID(NS_DOMACTIVITY_CID);
 NS_DEFINE_NAMED_CID(NS_DOMPARSER_CID);
 NS_DEFINE_NAMED_CID(NS_DOMSTORAGE2_CID);
 NS_DEFINE_NAMED_CID(NS_DOMSTORAGEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_DOMJSON_CID);
 NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID);
 NS_DEFINE_NAMED_CID(INDEXEDDB_MANAGER_CID);
 NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID);
@@ -1024,17 +1021,16 @@ static const mozilla::Module::CIDEntry k
   { &kNS_XMLSERIALIZER_CID, false, NULL, nsDOMSerializerConstructor },
   { &kNS_FILEREADER_CID, false, NULL, nsDOMFileReaderConstructor },
   { &kNS_ARCHIVEREADER_CID, false, NULL, ArchiveReaderConstructor },
   { &kNS_FORMDATA_CID, false, NULL, nsFormDataConstructor },
   { &kNS_BLOBPROTOCOLHANDLER_CID, false, NULL, nsBlobProtocolHandlerConstructor },
   { &kNS_BLOBURI_CID, false, NULL, nsBlobURIConstructor },
   { &kNS_XMLHTTPREQUEST_CID, false, NULL, nsXMLHttpRequestConstructor },
   { &kNS_EVENTSOURCE_CID, false, NULL, nsEventSourceConstructor },
-  { &kNS_WEBSOCKET_CID, false, NULL, nsWebSocketConstructor },
   { &kNS_DOMACTIVITY_CID, false, NULL, ActivityConstructor },
   { &kNS_DOMPARSER_CID, false, NULL, nsDOMParserConstructor },
   { &kNS_DOMSTORAGE2_CID, false, NULL, NS_NewDOMStorage2 },
   { &kNS_DOMSTORAGEMANAGER_CID, false, NULL, nsDOMStorageManagerConstructor },
   { &kNS_DOMJSON_CID, false, NULL, NS_NewJSON },
   { &kNS_TEXTEDITOR_CID, false, NULL, nsPlaintextEditorConstructor },
   { &kINDEXEDDB_MANAGER_CID, false, NULL, IndexedDatabaseManagerConstructor },
   { &kDOMREQUEST_SERVICE_CID, false, NULL, DOMRequestServiceConstructor },
@@ -1165,17 +1161,16 @@ static const mozilla::Module::ContractID
   { TRANSFORMIIX_NODESET_CONTRACTID, &kTRANSFORMIIX_NODESET_CID },
   { NS_XMLSERIALIZER_CONTRACTID, &kNS_XMLSERIALIZER_CID },
   { NS_FILEREADER_CONTRACTID, &kNS_FILEREADER_CID },
   { NS_ARCHIVEREADER_CONTRACTID, &kNS_ARCHIVEREADER_CID },
   { NS_FORMDATA_CONTRACTID, &kNS_FORMDATA_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX BLOBURI_SCHEME, &kNS_BLOBPROTOCOLHANDLER_CID },
   { NS_XMLHTTPREQUEST_CONTRACTID, &kNS_XMLHTTPREQUEST_CID },
   { NS_EVENTSOURCE_CONTRACTID, &kNS_EVENTSOURCE_CID },
-  { NS_WEBSOCKET_CONTRACTID, &kNS_WEBSOCKET_CID },
   { NS_DOMACTIVITY_CONTRACTID, &kNS_DOMACTIVITY_CID },
   { NS_DOMPARSER_CONTRACTID, &kNS_DOMPARSER_CID },
   { "@mozilla.org/dom/storage;2", &kNS_DOMSTORAGE2_CID },
   { "@mozilla.org/dom/storagemanager;1", &kNS_DOMSTORAGEMANAGER_CID },
   { "@mozilla.org/dom/json;1", &kNS_DOMJSON_CID },
   { "@mozilla.org/editor/texteditor;1", &kNS_TEXTEDITOR_CID },
   { INDEXEDDB_MANAGER_CONTRACTID, &kINDEXEDDB_MANAGER_CID },
   { DOMREQUEST_SERVICE_CONTRACTID, &kDOMREQUEST_SERVICE_CID },
--- a/layout/forms/test/test_bug348236.html
+++ b/layout/forms/test/test_bug348236.html
@@ -33,27 +33,24 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   /** Test for Bug 348236 **/
 
 SimpleTest.waitForExplicitFinish()
 addLoadEvent(function test() {
 
     var
         CI = Components.interfaces,
-        WinUtils = window
-                   .QueryInterface(CI.nsIInterfaceRequestor)
-                   .getInterface(CI.nsIDOMWindowUtils),
+        WinUtils = SpecialPowers.getDOMWindowUtils(window),
         sec = netscape.security,
         eSelect = $("eSelect"),
         IDOMEvent = CI.nsIDOMEvent,
         IDOMKeyEvent = CI.nsIDOMKeyEvent,
         timeout = 0 // Choose a larger value like 500 ms if you want to see what's happening.
 
     function keypressOnSelect(key, modifiers) {
-        sec.PrivilegeManager.enablePrivilege("UniversalXPConnect")
         WinUtils.focus(eSelect)
         WinUtils.sendKeyEvent("keyup", key, 0, modifiers, WinUtils.KEY_FLAG_PREVENT_DEFAULT)
         WinUtils.sendKeyEvent("keypress", key, 0, modifiers, WinUtils.KEY_FLAG_PREVENT_DEFAULT)
         WinUtils.sendKeyEvent("keydown", key, 0, modifiers, WinUtils.KEY_FLAG_PREVENT_DEFAULT)
     }
 
     function testKey(key, modifiers, keyString, functionToContinue) {
         var selectGotClick
@@ -61,28 +58,26 @@ addLoadEvent(function test() {
         eSelect.selectedIndex = 0
         eSelect.onchangeCount = 0
 
         // Drop the SELECT down.
         keypressOnSelect(key, modifiers)
         // This timeout and the following are necessary to let the sent events take effect.
         setTimeout(cont1, timeout)
         function cont1() {
-            sec.PrivilegeManager.enablePrivilege("UniversalXPConnect")
             // Move the mouse over option 3 (90 = 3 (rows) * 24 (row height) + 18).
             WinUtils.sendMouseEvent(