Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 15 Aug 2012 21:37:36 -0400
changeset 102468 50e4ff05741e6485aa0248e20f2ebffb4e81f2d8
parent 102406 996a68d8420ee36b459933a3e27853d4810e6b39 (current diff)
parent 102467 dfcc0507902cf689c7369acd54c9bde50cb4b2a1 (diff)
child 102518 3940df6f9356f5681b7ebf99b31f65577f2567bf
push id23287
push userryanvm@gmail.com
push dateThu, 16 Aug 2012 01:37:50 +0000
treeherdermozilla-central@50e4ff05741e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.0a1
first release with
nightly linux32
50e4ff05741e / 17.0a1 / 20120816030539 / files
nightly linux64
50e4ff05741e / 17.0a1 / 20120816030539 / files
nightly mac
50e4ff05741e / 17.0a1 / 20120816030539 / files
nightly win32
50e4ff05741e / 17.0a1 / 20120816030539 / files
nightly win64
50e4ff05741e / 17.0a1 / 20120816030539 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge the last PGO-green inbound changeset to m-c.
content/canvas/test/webgl/resources/js-test-post.js
webapprt/test/chrome/install.html
webapprt/test/content/helpers.js
webapprt/test/content/sample.html
webapprt/test/content/sample.webapp
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -39,16 +39,21 @@ XPCOMUtils.defineLazyServiceGetter(Servi
                                    '@mozilla.org/focus-manager;1',
                                    'nsIFocusManager');
 
 XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
   Cu.import('resource://gre/modules/devtools/dbg-server.jsm');
   return DebuggerServer;
 });
 
+XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
+  return Cc["@mozilla.org/parentprocessmessagemanager;1"]
+         .getService(Ci.nsIFrameMessageManager);
+});
+
 function getContentWindow() {
   return shell.contentBrowser.contentWindow;
 }
 
 var shell = {
 
   get CrashSubmit() {
     delete this.CrashSubmit;
@@ -144,26 +149,29 @@ var shell = {
     SettingsListener.observe("debug.fps.enabled", false, function(value) {
       Services.prefs.setBoolPref("layers.acceleration.draw-fps", value);
     });
     SettingsListener.observe("debug.paint-flashing.enabled", false, function(value) {
       Services.prefs.setBoolPref("nglayout.debug.paint_flashing", value);
     });
 
     this.contentBrowser.src = homeURL;
+
+    ppmm.addMessageListener("content-handler", this);
   },
 
   stop: function shell_stop() {
     window.removeEventListener('keydown', this, true);
     window.removeEventListener('keypress', this, true);
     window.removeEventListener('keyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('mozfullscreenchange', this);
     window.removeEventListener('sizemodechange', this);
     this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
+    ppmm.removeMessageListener("content-handler", this);
 
 #ifndef MOZ_WIDGET_GONK
     delete Services.audioManager;
 #endif
   },
 
   // If this key event actually represents a hardware button, filter it here
   // and send a mozChromeEvent with detail.type set to xxx-button-press or
@@ -293,23 +301,39 @@ var shell = {
                               .getService(Ci.nsIOfflineCacheUpdateService);
           updateService.scheduleUpdate(manifestURI, documentURI, window);
         } catch (e) {
           dump('Error while creating offline cache: ' + e + '\n');
         }
         break;
     }
   },
+
   sendEvent: function shell_sendEvent(content, type, details) {
     let event = content.document.createEvent('CustomEvent');
     event.initCustomEvent(type, true, true, details ? details : {});
     content.dispatchEvent(event);
   },
+
   sendChromeEvent: function shell_sendChromeEvent(details) {
     this.sendEvent(getContentWindow(), "mozChromeEvent", details);
+  },
+
+  receiveMessage: function shell_receiveMessage(message) {
+    if (message.name != 'content-handler') {
+      return;
+    }
+    let handler = message.json;
+    new MozActivity({
+      name: 'view',
+      data: {
+        type: handler.type,
+        url: handler.url
+      }
+    });
   }
 };
 
 function nsBrowserAccess() {
 }
 
 nsBrowserAccess.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow]),
@@ -342,17 +366,18 @@ nsBrowserAccess.prototype = {
 // Listen for system messages and relay them to Gaia.
 Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
   let msg = JSON.parse(data);
   let origin = Services.io.newURI(msg.manifest, null, null).prePath;
   shell.sendChromeEvent({
     type: 'open-app',
     url: msg.uri,
     origin: origin,
-    manifest: msg.manifest
+    manifest: msg.manifest,
+    target: msg.target
   });
 }, 'system-messages-open-app', false);
 
 Services.obs.addObserver(function(aSubject, aTopic, aData) {
   shell.sendEvent(shell.contentBrowser.contentWindow,
                   "mozChromeEvent", { type: "fullscreenoriginchange",
                                       fullscreenorigin: aData } );
 }, "fullscreen-origin-change", false);
@@ -596,27 +621,16 @@ window.addEventListener('ContentStart', 
       shell.sendChromeEvent({
         type: 'take-screenshot-error',
         error: String(e)
       });
     }
   });
 });
 
-Services.obs.addObserver(function ContentHandler(subject, topic, data) {
-  let handler = JSON.parse(data);
-  new MozActivity({
-    name: 'view',
-    data: {
-      type: handler.type,
-      url: handler.url
-    }
-  });
-}, 'content-handler', false);
-
 (function geolocationStatusTracker() {
   let gGeolocationActiveCount = 0;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldCount = gGeolocationActiveCount;
     if (aData == "starting") {
       gGeolocationActiveCount += 1;
     } else if (aData == "shutdown") {
--- a/b2g/components/ContentHandler.js
+++ b/b2g/components/ContentHandler.js
@@ -8,16 +8,20 @@ const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 const PDF_CONTENT_TYPE = "application/pdf";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
+  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+});
+
 function log(aMsg) {
   let msg = "ContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg);
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
                                      .logStringMessage(msg);
   dump(msg + "\n");
 }
 
 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
@@ -31,17 +35,17 @@ ContentHandler.prototype = {
 
     if (!(aRequest instanceof Ci.nsIChannel))
       throw NS_ERROR_WONT_HANDLE_CONTENT;
 
     let detail = {
       "type": aMimetype,
       "url": aRequest.URI.spec
     };
-    Services.obs.notifyObservers(this, "content-handler", JSON.stringify(detail)); 
+    cpmm.sendAsyncMessage("content-handler", detail);
 
     aRequest.cancel(Cr.NS_BINDING_ABORTED);
   },
 
   classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler])
 };
 
--- a/b2g/config/mozconfigs/win32_gecko/nightly
+++ b/b2g/config/mozconfigs/win32_gecko/nightly
@@ -17,19 +17,13 @@ export MOZ_TELEMETRY_REPORTING=1
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
-# For known full-clobber builds on Windows (like nightlies/try), 
-# this speeds things up. IS_NIGHTLY is set by the build automation.
-if test "$IS_NIGHTLY" != ""; then 
-  ac_add_options --disable-auto-deps
-fi
-
 # B2G Options
 ac_add_options --enable-application=b2g
 ac_add_options --enable-marionette
 
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -83,33 +83,36 @@ var FullZoom = {
       case "DOMMouseScroll":
         this._handleMouseScrolled(event);
         break;
     }
   },
 
   _handleMouseScrolled: function FullZoom__handleMouseScrolled(event) {
     // Construct the "mousewheel action" pref key corresponding to this event.
-    // Based on nsEventStateManager::GetBasePrefKeyForMouseWheel.
-    var pref = "mousewheel";
-    if (event.axis == event.HORIZONTAL_AXIS)
-      pref += ".horizscroll";
+    // Based on nsEventStateManager::WheelPrefs::GetBasePrefName().
+    var pref = "mousewheel.";
 
-    if (event.shiftKey)
-      pref += ".withshiftkey";
-    else if (event.ctrlKey)
-      pref += ".withcontrolkey";
-    else if (event.altKey)
-      pref += ".withaltkey";
-    else if (event.metaKey)
-      pref += ".withmetakey";
-    else
-      pref += ".withnokey";
+    var pressedModifierCount = event.shiftKey + event.ctrlKey + event.altKey +
+                                 event.metaKey + event.getModifierState("OS");
+    if (pressedModifierCount != 1) {
+      pref += "default.";
+    } else if (event.shiftKey) {
+      pref += "with_shift.";
+    } else if (event.ctrlKey) {
+      pref += "with_control.";
+    } else if (event.altKey) {
+      pref += "with_alt.";
+    } else if (event.metaKey) {
+      pref += "with_meta.";
+    } else {
+      pref += "with_win.";
+    }
 
-    pref += ".action";
+    pref += "action";
 
     // Don't do anything if this isn't a "zoom" scroll event.
     var isZoomEvent = false;
     try {
       isZoomEvent = (gPrefService.getIntPref(pref) == MOUSE_SCROLL_ZOOM);
     } catch (e) {}
     if (!isZoomEvent)
       return;
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -20,14 +20,8 @@ mk_add_options MOZ_MAKE_FLAGS=-j1
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
-
-# For known full-clobber builds on Windows (like nightlies/try), 
-# this speeds things up. IS_NIGHTLY is set by the build automation.
-if test "$IS_NIGHTLY" != ""; then 
-  ac_add_options --disable-auto-deps
-fi
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -18,15 +18,9 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
-# For known full-clobber builds on Windows (like nightlies/try), 
-# this speeds things up. IS_NIGHTLY is set by the build automation.
-if test "$IS_NIGHTLY" != ""; then 
-  ac_add_options --disable-auto-deps
-fi
-
 . $topsrcdir/build/win64/mozconfig.vs2010
--- a/build/autoconf/mozconfig2client-mk
+++ b/build/autoconf/mozconfig2client-mk
@@ -5,21 +5,20 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # mozconfig2client-mk - Translates .mozconfig into options for client.mk.
 #    Prints defines to stdout.
 #
 # See mozconfig2configure for more details
 
 print_header() {
-  _mozconfig=${MOZCONFIG:-$HOME/.mozconfig}
   cat <<EOF
 # gmake
 # This file is automatically generated for client.mk.
-# Do not edit. Edit $_mozconfig instead.
+# Do not edit. Edit $FOUND_MOZCONFIG instead.
 
 EOF
 }
 
 ac_add_options() {
   echo "# $* is used by configure (not client.mk)"
 }
 
@@ -48,18 +47,16 @@ mk_echo_options() {
 
 # Main
 #--------------------------------------------------
 
 scriptdir=`dirname $0`
 topsrcdir=$1
 opts=""
 
-print_header
-
 # If the path changes, configure should be rerun
 echo "# PATH=$PATH"
 
 # If FOUND_MOZCONFIG isn't set, look for it and make sure the script doesn't error out
 isfoundset=${FOUND_MOZCONFIG+yes}
 if [ -z $isfoundset ]; then
   FOUND_MOZCONFIG=`$scriptdir/mozconfig-find $topsrcdir`
   if [ $? -ne 0 ]; then
@@ -67,16 +64,17 @@ if [ -z $isfoundset ]; then
   else
     isfoundset=yes
   fi
 fi
 
 if [ -n $isfoundset ]; then
   if [ "$FOUND_MOZCONFIG" ]
   then
+    print_header
     . "$FOUND_MOZCONFIG"
   fi
   echo "export FOUND_MOZCONFIG := $FOUND_MOZCONFIG"
 
   if [ "$opts" ]; then
     mk_echo_options
   fi
 fi
--- a/build/mobile/devicemanager.py
+++ b/build/mobile/devicemanager.py
@@ -33,19 +33,22 @@ def abstractmethod(method):
     raise NotImplementedError('Abstract method %s at File "%s", line %s '
                               'should be implemented by a concrete class' %
                               (repr(method), filename,line))
   return not_implemented
 
 class DeviceManager:
 
   @abstractmethod
-  def shell(self, cmd, outputfile, env=None, cwd=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
     """
     executes shell command on device
+
+    timeout is specified in seconds, and if no timeout is given, 
+    we will run until the script returns
     returns:
     success: Return code from command
     failure: None
     """
 
   @abstractmethod
   def pushFile(self, localname, destname):
     """
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -85,21 +85,23 @@ class DeviceManagerADB(DeviceManager):
       self.verifyZip()
     except DMError:
       pass
 
   def __del__(self):
     if self.host:
       self.disconnectRemoteADB()
 
-  # external function: executes shell command on device
+  # external function: executes shell command on device.
+  # timeout is specified in seconds, and if no timeout is given, 
+  # we will run until the script returns
   # returns:
   # success: <return code>
   # failure: None
-  def shell(self, cmd, outputfile, env=None, cwd=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
     # FIXME: this function buffers all output of the command into memory,
     # always. :(
 
     # Getting the return code is more complex than you'd think because adb
     # doesn't actually return the return code from a process, so we have to
     # capture the output to get it
     cmdline = "%s; echo $?" % self._escapedCommandLine(cmd)
 
@@ -112,16 +114,26 @@ class DeviceManagerADB(DeviceManager):
 
     # all output should be in stdout
     args=[self.adbPath]
     if self.deviceSerial:
         args.extend(['-s', self.deviceSerial])
     args.extend(["shell", cmdline])
     proc = subprocess.Popen(args,
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    if timeout:
+        timeout = int(timeout)
+        start_time = time.time()
+        ret_code = proc.poll()
+        while ((time.time() - start_time) <= timeout) and ret_code == None:
+            time.sleep(1)
+            ret_code = proc.poll()
+        if ret_code == None:
+            proc.kill()
+            raise DMError("Timeout exceeded for shell call")
     (stdout, stderr) = proc.communicate()
     outputfile.write(stdout.rstrip('\n'))
 
     lastline = _pop_last_line(outputfile)
     if lastline:
       m = re.search('([0-9]+)', lastline)
       if m:
         return_code = m.group(1)
@@ -707,33 +719,47 @@ class DeviceManagerADB(DeviceManager):
     return subprocess.Popen(finalArgs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
   def runCmdAs(self, args):
     if self.useRunAs:
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     return self.runCmd(args)
 
-  def checkCmd(self, args):
+  # timeout is specified in seconds, and if no timeout is given, 
+  # we will run until the script returns
+  def checkCmd(self, args, timeout=None):
     # If we are not root but have run-as, and we're trying to execute
     # a shell command then using run-as is the best we can do
     finalArgs = [self.adbPath]
     if self.deviceSerial:
       finalArgs.extend(['-s', self.deviceSerial])
     if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     finalArgs.extend(args)
+    if timeout:
+        timeout = int(timeout)
+        proc = subprocess.Popen(finalArgs)
+        start_time = time.time()
+        ret_code = proc.poll()
+        while ((time.time() - start_time) <= timeout) and ret_code == None:
+            time.sleep(1)
+            ret_code = proc.poll()
+        if ret_code == None:
+            proc.kill()
+            raise DMError("Timeout exceeded for checkCmd call")
+        return ret_code
     return subprocess.check_call(finalArgs)
 
-  def checkCmdAs(self, args):
+  def checkCmdAs(self, args, timeout=None):
     if (self.useRunAs):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
-    return self.checkCmd(args)
+    return self.checkCmd(args, timeout)
 
   # external function
   # returns:
   #  success: True
   #  failure: False
   def chmodDir(self, remoteDir):
     if (self.isDir(remoteDir)):
       files = self.listFiles(remoteDir.strip())
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -118,16 +118,18 @@ class DeviceManagerSUT(DeviceManager):
     '''
     a wrapper for _doCmds that loops up to self.retrylimit iterations.
     this allows us to move the retry logic outside of the _doCmds() to make it
     easier for debugging in the future.
     note that since cmdlist is a list of commands, they will all be retried if
     one fails.  this is necessary in particular for pushFile(), where we don't want
     to accidentally send extra data if a failure occurs during data transmission.
     '''
+    if timeout:
+      raise NotImplementedError("'timeout' parameter is not yet supported")
     while self.retries < self.retrylimit:
       try:
         self._doCmds(cmdlist, outputfile, timeout)
         return
       except AgentError, err:
         # re-raise error if it's fatal (i.e. the device got the command but
         # couldn't execute it). retry otherwise
         if err.fatal:
@@ -256,26 +258,26 @@ class DeviceManagerSUT(DeviceManager):
       except:
         self._sock = None
         raise AgentError("Error closing socket")
 
   # external function: executes shell command on device
   # returns:
   # success: <return code>
   # failure: None
-  def shell(self, cmd, outputfile, env=None, cwd=None):
+  def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None):
     cmdline = self._escapedCommandLine(cmd)
     if env:
       cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
 
     try:
       if cwd:
-        self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile)
+        self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile, timeout)
       else:
-        self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile)
+        self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile, timeout)
     except AgentError:
       return None
 
     # dig through the output to get the return code
     lastline = _pop_last_line(outputfile)
     if lastline:
       m = re.search('return code \[([0-9]+)\]', lastline)
       if m:
--- a/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
+++ b/caps/tests/mochitest/test_principal_extendedorigin_appid_appstatus.html
@@ -359,16 +359,17 @@ function checkIFrame(aFrame, data) {
             "childPrincipal and parent principal should have different appId");
     }
   }
 
   eoList.push(principal.extendedOrigin);
 
   checkedCount++;
   if (checkedCount == checksTodo) {
+    SpecialPowers.removePermission("browser", "http://example.org");
     SimpleTest.finish();
   } else {
     gTestRunner.next();
   }
 }
 
 is('appStatus' in document.nodePrincipal, true,
    'appStatus should be present in nsIPrincipal');
@@ -423,16 +424,16 @@ function runTest() {
     content.appendChild(iframe);
 
     yield;
   }
 }
 
 var gTestRunner = runTest();
 
-SpecialPowers.pushPrefEnv({'set': [["dom.mozBrowserFramesEnabled", true],
-                                   ["dom.mozBrowserFramesWhitelist", "http://example.org"]]},
+SpecialPowers.addPermission("browser", true, "http://example.org");
+SpecialPowers.pushPrefEnv({'set':[["dom.mozBrowserFramesEnabled", true]]},
                            function() { gTestRunner.next(); });
 
 </script>
 </pre>
 </body>
 </html>
--- a/client.mk
+++ b/client.mk
@@ -65,17 +65,17 @@ AUTOCONF=$(error Could not find autoconf
 endif
 
 SH := /bin/sh
 PERL ?= perl
 PYTHON ?= python
 
 CONFIG_GUESS_SCRIPT := $(wildcard $(TOPSRCDIR)/build/autoconf/config.guess)
 ifdef CONFIG_GUESS_SCRIPT
-  CONFIG_GUESS = $(shell $(CONFIG_GUESS_SCRIPT))
+  CONFIG_GUESS := $(shell $(CONFIG_GUESS_SCRIPT))
 endif
 
 
 ####################################
 # Sanity checks
 
 ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
 # check for CRLF line endings
@@ -87,18 +87,16 @@ endif
 endif
 
 ####################################
 # Load mozconfig Options
 
 # See build pages, http://www.mozilla.org/build/ for how to set up mozconfig.
 
 MOZCONFIG_LOADER := build/autoconf/mozconfig2client-mk
-MOZCONFIG_FINDER := build/autoconf/mozconfig-find 
-MOZCONFIG_MODULES := build/unix/uniq.pl
 
 define CR
 
 
 endef
 
 # As $(shell) doesn't preserve newlines, use sed to replace them with an
 # unlikely sequence (||), which is then replaced back to newlines by make
--- a/configure.in
+++ b/configure.in
@@ -8636,20 +8636,18 @@ if test "$MOZ_GL_DEFAULT_PROVIDER" = "GL
 fi # MOZ_GL_DEFAULT_PROVIDER=GLX
 fi # COMPILE_ENVIRONMENT
 
 dnl Set various defines and substitutions
 dnl ========================================================
 
 if test "$OS_ARCH" = "Darwin"; then
   AC_DEFINE(XP_UNIX)
-  AC_DEFINE(UNIX_ASYNC_DNS)
 elif test "$OS_ARCH" != "WINNT" -a "$OS_ARCH" != "OS2"; then
   AC_DEFINE(XP_UNIX)
-  AC_DEFINE(UNIX_ASYNC_DNS)
 fi
 
 if test "$MOZ_DEBUG"; then
     AC_DEFINE(MOZ_REFLOW_PERF)
     AC_DEFINE(MOZ_REFLOW_PERF_DSP)
 fi
 
 if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK2" ; then
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -1305,17 +1305,17 @@ nsAttrValue::ParseEnumValue(const nsAStr
   return false;
 }
 
 bool
 nsAttrValue::ParseSpecialIntValue(const nsAString& aString)
 {
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   bool isPercent = false;
   nsAutoString tmp(aString);
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec, true, &isPercent);
 
   if (NS_FAILED(ec)) {
     return false;
   }
@@ -1338,17 +1338,17 @@ nsAttrValue::ParseSpecialIntValue(const 
 bool
 nsAttrValue::ParseIntWithBounds(const nsAString& aString,
                                 PRInt32 aMin, PRInt32 aMax)
 {
   NS_PRECONDITION(aMin < aMax, "bad boundaries");
 
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec);
   if (NS_FAILED(ec)) {
     return false;
   }
 
   PRInt32 val = NS_MAX(originalVal, aMin);
   val = NS_MIN(val, aMax);
@@ -1358,34 +1358,34 @@ nsAttrValue::ParseIntWithBounds(const ns
   return true;
 }
 
 bool
 nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
 {
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec);
   if (NS_FAILED(ec) || originalVal < 0) {
     return false;
   }
 
   SetIntValueAndType(originalVal, eInteger, strict ? nullptr : &aString);
 
   return true;
 }
 
 bool
 nsAttrValue::ParsePositiveIntValue(const nsAString& aString)
 {
   ResetIfSet();
 
-  PRInt32 ec;
+  nsresult ec;
   bool strict;
   PRInt32 originalVal = StringToInteger(aString, &strict, &ec);
   if (NS_FAILED(ec) || originalVal <= 0) {
     return false;
   }
 
   SetIntValueAndType(originalVal, eInteger, strict ? nullptr : &aString);
 
@@ -1656,17 +1656,17 @@ nsAttrValue::GetStringBuffer(const nsASt
   PRUnichar *data = static_cast<PRUnichar*>(buf->Data());
   CopyUnicodeTo(aValue, 0, data, len);
   data[len] = PRUnichar(0);
   return buf;
 }
 
 PRInt32
 nsAttrValue::StringToInteger(const nsAString& aValue, bool* aStrict,
-                             PRInt32* aErrorCode,
+                             nsresult* aErrorCode,
                              bool aCanBePercent,
                              bool* aIsPercent) const
 {
   *aStrict = true;
   *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
   if (aCanBePercent) {
     *aIsPercent = false;
   }
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -413,17 +413,17 @@ private:
 
   bool EnsureEmptyMiscContainer();
   bool EnsureEmptyAtomArray();
   nsStringBuffer* GetStringBuffer(const nsAString& aValue) const;
   // aStrict is set true if stringifying the return value equals with
   // aValue.
   PRInt32 StringToInteger(const nsAString& aValue,
                           bool* aStrict,
-                          PRInt32* aErrorCode,
+                          nsresult* aErrorCode,
                           bool aCanBePercent = false,
                           bool* aIsPercent = nullptr) const;
   // Given an enum table and a particular entry in that table, return
   // the actual integer value we should store.
   PRInt32 EnumTableEntryToValue(const EnumTable* aEnumTable,
                                 const EnumTable* aTableEntry);  
 
   static nsTArray<const EnumTable*, nsTArrayDefaultAllocator>* sEnumTableArray;
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -1415,17 +1415,17 @@ nsHTMLCopyEncoder::SetSelection(nsISelec
   nsCOMPtr<nsIEnumerator> enumerator;
   rv = privSelection->GetEnumerator(getter_AddRefs(enumerator));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
 
   // loop thru the ranges in the selection
   enumerator->First(); 
   nsCOMPtr<nsISupports> currentItem;
-  while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
+  while (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == enumerator->IsDone())
   {
     rv = enumerator->CurrentItem(getter_AddRefs(currentItem));
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
     
     range = do_QueryInterface(currentItem);
     NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
     nsCOMPtr<nsIDOMRange> myRange;
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1514,17 +1514,19 @@ nsObjectLoadingContent::LoadObject(bool 
   }
 
   // Save these for NotifyStateChanged();
   nsEventStates oldState = ObjectState();
   ObjectType oldType = mType;
 
   ParameterUpdateFlags stateChange = UpdateObjectParameters();
 
-  if (!stateChange && !aForceLoad) {
+  // If nothing changed and we are not force-loading, or we're in state loading
+  // but continuing to wait on a channel, we're done
+  if ((!stateChange && !aForceLoad) || (mType == eType_Loading && mChannel)) {
     return NS_OK;
   }
 
   ///
   /// State has changed, unload existing content and attempt to load new type
   ///
   LOG(("OBJLC [%p]: LoadObject - plugin state changed (%u)",
        this, stateChange));
@@ -1712,31 +1714,25 @@ nsObjectLoadingContent::LoadObject(bool 
     {
       if (!mChannel) {
         // We could mFrameLoader->LoadURI(mURI), but UpdateObjectParameters
         // requires documents have a channel, so this is not a valid state.
         NS_NOTREACHED("Attempting to load a document without a channel");
         mType = eType_Null;
         break;
       }
+      
+      mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
+                                           mNetworkCreated);
       if (!mFrameLoader) {
-        // Force a sync state change, we need the frame created
-        NotifyStateChanged(oldType, oldState, true, aNotify);
-        oldType = mType;
-        oldState = ObjectState();
-
-        mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
-                                             mNetworkCreated);
-        if (!mFrameLoader) {
-          NS_NOTREACHED("nsFrameLoader::Create failed");
-          mType = eType_Null;
-          break;
-        }
+        NS_NOTREACHED("nsFrameLoader::Create failed");
+        mType = eType_Null;
+        break;
       }
-
+      
       rv = mFrameLoader->CheckForRecursiveLoad(mURI);
       if (NS_FAILED(rv)) {
         mType = eType_Null;
         break;
       }
 
       // We're loading a document, so we have to set LOAD_DOCUMENT_URI
       // (especially important for firing onload)
@@ -1807,20 +1803,21 @@ nsObjectLoadingContent::LoadObject(bool 
     // Don't notify or send events - we'll handle those ourselves
     // (so really this is just setting mFallbackType)
     LoadFallback(fallbackType, false);
   }
 
   // Notify of our final state if we haven't already
   NotifyStateChanged(oldType, oldState, false, aNotify);
 
-  if (mType == eType_Null && mFallbackType != eFallbackAlternate) {
-    // if we're not showing alternate content, fire a pluginerror to trigger
-    // (we stopped LoadFallback from doing so above, it doesn't know of our old
-    //  state)
+  if (mType == eType_Null && !mContentType.IsEmpty() &&
+      mFallbackType != eFallbackAlternate) {
+    // if we have a content type and are not showing alternate
+    // content, fire a pluginerror to trigger (we stopped LoadFallback
+    // from doing so above, it doesn't know of our old state)
     FirePluginError(mFallbackType);
   }
 
   return NS_OK;
 }
 
 nsresult
 nsObjectLoadingContent::CloseChannel()
--- a/content/base/test/test_ipc_messagemanager_blob.html
+++ b/content/base/test/test_ipc_messagemanager_blob.html
@@ -68,16 +68,17 @@
         let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
         mm.addMessageListener("test:ipcClonedMessage", function(message) {
           // We need to wrap to access message.json, and unwrap to do the
           // identity check.
           is(SpecialPowers.unwrap(SpecialPowers.wrap(message).json),
              messages[receivedMessageIndex++],
              "Got correct round-tripped response");
           if (receivedMessageIndex == messages.length) {
+            SpecialPowers.removePermission("browser", document);
             SimpleTest.finish();
           }
         });
         mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
                            false);
 
         for each (let message in messages) {
           mm.sendAsyncMessage("test:ipcClonedMessage", message);
@@ -85,30 +86,20 @@
       });
 
       document.body.appendChild(iframe);
     }
 
     addEventListener("load", function() {
       info("Got load event.");
 
-      let whitelist;
-      try {
-        whitelist =
-          SpecialPowers.getCharPref("dom.mozBrowserFramesWhitelist") + ", ";
-      } catch (e) {
-        whitelist = "";
-      }
-
-      whitelist += window.location.protocol + "//" + window.location.host;
-
+      SpecialPowers.addPermission("browser", true, document);
       SpecialPowers.pushPrefEnv({
         "set": [
           ["dom.ipc.browser_frames.oop_by_default", true],
           ["dom.mozBrowserFramesEnabled", true],
-          ["dom.mozBrowserFramesWhitelist", whitelist],
           ["browser.pageThumbs.enabled", false]
         ]
       }, runTests);
     });
   </script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/attribs/gl-enable-vertex-attrib.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-enable-vertex-attrib.html
@@ -45,13 +45,13 @@ gl.vertexAttribPointer(0, 3, gl.FLOAT, f
 gl.enableVertexAttribArray(3);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 gl.drawArrays(gl.TRIANGLES, 0, 3);
 glErrorShouldBe(gl, gl.INVALID_OPERATION);
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib-zero-issues.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib-zero-issues.html
@@ -79,13 +79,13 @@ for (var ii = 0; ii < 5; ++ii) {
       gl, gl.NO_ERROR,
       "drawing using attrib 3 with 60000 verts");
 }
 
 wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be 0, 0, 0, 0");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib.html
@@ -83,12 +83,12 @@ if (!gl) {
   }
   glErrorShouldBe(gl, gl.NO_ERROR);
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer-offsets.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer-offsets.html
@@ -182,12 +182,12 @@ There is supposed to be an example drawi
                 }
               }
             }
        }
 
        init();
        successfullyParsed = true;
     </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertexattribpointer.html
@@ -122,12 +122,12 @@ if (!gl) {
     }
   }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/buffer-bind-test.html
+++ b/content/canvas/test/webgl/conformance/buffers/buffer-bind-test.html
@@ -51,13 +51,13 @@ if (!gl) {
   gl.bindBuffer(gl.ARRAY_BUFFER, buf);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
             "should get INVALID_OPERATION if attempting to bind buffer to different target");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/buffers/buffer-data-array-buffer.html
+++ b/content/canvas/test/webgl/conformance/buffers/buffer-data-array-buffer.html
@@ -57,11 +57,11 @@ gl.bufferSubData(gl.ARRAY_BUFFER, 10, ar
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 gl.bufferSubData(gl.ARRAY_BUFFER, 10, null);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-copies-indices.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-copies-indices.html
@@ -66,11 +66,11 @@ indices[5] = 1;
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 2)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 4)");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-crash-with-buffer-sub-data.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-crash-with-buffer-sub-data.html
@@ -25,11 +25,11 @@ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, e
 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 256, gl.STATIC_DRAW);
 var data = new Uint8Array(127);
 gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 63, data);
 testPassed("bufferSubData, when buffer object was initialized with null, did not crash");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-verifies-too-many-indices.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-verifies-too-many-indices.html
@@ -37,11 +37,11 @@ context.bufferData(context.ELEMENT_ARRAY
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 2)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLE_STRIP, 4, context.UNSIGNED_SHORT, 4)");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation-with-resized-buffer.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation-with-resized-buffer.html
@@ -94,11 +94,11 @@ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, i
 glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
 gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_BYTE, 0);
 glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/buffers/index-validation.html
+++ b/content/canvas/test/webgl/conformance/buffers/index-validation.html
@@ -131,11 +131,11 @@ shouldBeUndefined('gl.drawElements(gl.TR
 debug("Pass large negative index to vertexAttribPointer");
 gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
 glErrorShouldBe(gl, gl.INVALID_VALUE);
 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/canvas-zero-size.html
+++ b/content/canvas/test/webgl/conformance/canvas/canvas-zero-size.html
@@ -31,12 +31,12 @@ gl.bindTexture(gl.TEXTURE_2D, tex);
 var pixel = new Uint8Array([0, 255, 0, 255]);
 gl.texImage2D(
   gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
 wtu.drawQuad(gl);
 
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/drawingbuffer-static-canvas-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/drawingbuffer-static-canvas-test.html
@@ -138,11 +138,11 @@ if (!gl) {
   shouldBeTrue('gl.drawingBufferHeight == 50');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
   drawTriangleTest(gl);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 }
 debug("")
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/drawingbuffer-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/drawingbuffer-test.html
@@ -137,11 +137,11 @@ if (!gl) {
   shouldBeTrue('gl.drawingBufferHeight == 50');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
   drawTriangleTest(gl);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 }
 debug("")
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/canvas/viewport-unchanged-upon-resize.html
+++ b/content/canvas/test/webgl/conformance/canvas/viewport-unchanged-upon-resize.html
@@ -101,12 +101,12 @@ if (passed) {
     if (passed) {
       testPassed("Viewport correctly did not change size during canvas resize");
     }
   }
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/context/constants.html
+++ b/content/canvas/test/webgl/conformance/context/constants.html
@@ -474,12 +474,12 @@ for (var i in gl) {
     }
     debug(i);
   }
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/context-type-test.html
+++ b/content/canvas/test/webgl/conformance/context/context-type-test.html
@@ -38,12 +38,12 @@ if (!gl) {
 
   debug("Checking context type");
   assertMsg(gl instanceof WebGLRenderingContext,
             "context type should be WebGLRenderingContext");
 }
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/incorrect-context-object-behaviour.html
+++ b/content/canvas/test/webgl/conformance/context/incorrect-context-object-behaviour.html
@@ -73,11 +73,11 @@ shouldGenerateGLError(contextA, contextA
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderInfoLog(shaderB, 0)");
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getShaderSource(shaderB)");
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniform(programB, locationA)");
 shouldGenerateGLError(contextA, contextA.INVALID_OPERATION, "contextA.getUniformLocation(programB, 'u_modelViewProjMatrix')");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/methods.html
+++ b/content/canvas/test/webgl/conformance/context/methods.html
@@ -189,12 +189,12 @@ for (var i in gl) {
     }
     debug(i);
   }
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/context/resource-sharing-test.html
+++ b/content/canvas/test/webgl/conformance/context/resource-sharing-test.html
@@ -30,12 +30,12 @@ assertMsg(gl1 && gl2,
 var vertexObject = gl1.createBuffer();
 gl2.bindBuffer(gl2.ARRAY_BUFFER, vertexObject);
 assertMsg(
   gl2.getError() == gl2.INVALID_OPERATION,
   "attempt to use a resource from the wrong context should fail with INVALID_OPERATION");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
+++ b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
@@ -166,12 +166,12 @@ function runHintTestEnabled() {
     }
 
     gl.deleteTexture(texture);
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
@@ -363,12 +363,12 @@ function runReferenceCycleTest()
 
     // create a self-cycle on the extension object
     ext.ext = ext;
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
@@ -204,12 +204,12 @@ function runReferenceCycleTest()
 
     // create a self-cycle on the extension object
     ext.ext = ext;
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/oes-vertex-array-object.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-vertex-array-object.html
@@ -399,12 +399,12 @@ function runDrawTests() {
     ext.bindVertexArrayOES(null);
     ext.deleteVertexArrayOES(vao0);
     ext.deleteVertexArrayOES(vao1);
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/webgl-compressed-texture-s3tc.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-compressed-texture-s3tc.html
@@ -603,12 +603,12 @@ function compareRect(
 
 function testPVRTCTextures() {
     testFailed("PVRTC test not yet implemented");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/webgl-debug-renderer-info.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-debug-renderer-info.html
@@ -93,12 +93,12 @@ function runTestEnabled() {
     shouldBe("ext.UNMASKED_RENDERER_WEBGL", "0x9246");
     gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
     glErrorShouldBe(gl, gl.NO_ERROR, "UNMASKED_RENDERER_WEBGL query should succeed if extension is enable");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/webgl-debug-shaders.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-debug-shaders.html
@@ -86,12 +86,12 @@ function runTestEnabled() {
         testPassed("Successfully called getTranslatedShaderSource()");
     else
         testFailed("Calling getTranslatedShaderSource() failed");
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/misc/attrib-location-length-limits.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/attrib-location-length-limits.html
@@ -72,11 +72,11 @@ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE
 
 debug("Attempt to fetch too-long attrib location should produce error");
 program = wtu.loadStandardProgram(gl);
 shouldBe('gl.getAttribLocation(program, "vPosition01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567")', '-1');
 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
 
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-2types-of-textures-on-same-unit.html
@@ -125,13 +125,13 @@ function init()
     glErrorShouldBe(gl, gl.INVALID_OPERATION,
               "drawing with 2 different targets on the same texture unit should generate INVALID_VALUE");
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
@@ -128,12 +128,12 @@ function init()
         else
             testPassed("Rendering results are the same");
     }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-long-variable-names.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-long-variable-names.html
@@ -239,11 +239,11 @@
                     return;
                 }
 
             pass();
         }
 
         successfullyParsed = true;
     </script>
-    <script src="../../../resources/js-test-post.js"></script>
+    <script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-vertex-branch.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-vertex-branch.html
@@ -119,12 +119,12 @@ function init()
         else
             testPassed("Rendering results are the same");
     }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/re-compile-re-link.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/re-compile-re-link.html
@@ -138,14 +138,14 @@ for (var i = 0; i < 10; ++i) {
   gl.linkProgram(program);
   checkProgramStatus(program)
 }
 
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
 
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/misc/uniform-location-length-limits.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/uniform-location-length-limits.html
@@ -75,11 +75,11 @@ program = wtu.loadProgramFromScript(gl, 
 wtu.glErrorShouldBe(gl, gl.NONE);
 shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true');
 var uniformLoc = gl.getUniformLocation(program, "identifier128CharactersLong_0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.identifier64CharactersLong_0123456789012345678901234567890123456.identifier63CharactersLong_012345678901234567890123456789012345");
 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
 shouldBeNull('uniformLoc');
 
 successfullyParsed = true;
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2d-bias.html
+++ b/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2d-bias.html
@@ -89,14 +89,14 @@ for (var ii = 0; ii < colors.length; ++i
       "256x256 texture drawn to 256x256 dest with bias = " + ii +
       " should be " + color.name);
 }
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dlod.html
+++ b/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dlod.html
@@ -89,14 +89,14 @@ for (var ii = 0; ii < colors.length; ++i
       "256x256 texture drawn to 256x256 dest with lod = " + ii +
       " should be " + color.name);
 }
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dproj.html
+++ b/content/canvas/test/webgl/conformance/glsl/samplers/glsl-function-texture2dproj.html
@@ -104,14 +104,14 @@ for (var ss = 0; ss < 2; ++ss) {
 	}
   }
 }
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/glsl/variables/gl-fragcoord.html
+++ b/content/canvas/test/webgl/conformance/glsl/variables/gl-fragcoord.html
@@ -76,12 +76,12 @@ found in the LICENSE file.
               gl, xx, yy, 1, 1, color, msg, 4);
         }
       }
     }
 
     init();
     successfullyParsed = true;
   </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/variables/gl-frontfacing.html
+++ b/content/canvas/test/webgl/conformance/glsl/variables/gl-frontfacing.html
@@ -77,12 +77,12 @@ found in the LICENSE file.
           }
         }
       }
     }
 
     init();
     successfullyParsed = true;
   </script>
-<script src="../../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/glsl/variables/gl-pointcoord.html
+++ b/content/canvas/test/webgl/conformance/glsl/variables/gl-pointcoord.html
@@ -130,12 +130,12 @@ found in the LICENSE file.
             wtu.checkCanvasRect(gl, xf, yf, 1, 1, color, msg, 4);
           }
         }
       }
     }
 
     successfullyParsed = true;
   </script>
-  <script src="../../../resources/js-test-post.js"></script>
+  <script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/limits/gl-max-texture-dimensions.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-max-texture-dimensions.html
@@ -84,14 +84,14 @@ var program = wtu.setupProgram(
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 
 // NOTE: We can't easily test cube maps because they require width == height
 // and we might not have enough memory for maxSize by maxSize texture.
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/limits/gl-min-attribs.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-min-attribs.html
@@ -72,14 +72,14 @@ for (var ii = 0; ii < 7; ++ii) {
 wtu.drawQuad(gl);
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [255, 127, 64, 32], "Should render 255,127,64,32 (+/-1)", 1);
 
 successfullyParsed = true;
 
 </script>
 </body>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/limits/gl-min-textures.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-min-textures.html
@@ -59,14 +59,14 @@ for (var ii = 0; ii < 8; ++ii) {
 wtu.drawQuad(gl);
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.checkCanvas(gl, [255, 128, 64, 252],
                 "Should render using all texture units", 1);
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/limits/gl-min-uniforms.html
+++ b/content/canvas/test/webgl/conformance/limits/gl-min-uniforms.html
@@ -91,14 +91,14 @@ for (var ii = 0; ii < 16; ++ii) {
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.drawQuad(gl);
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 wtu.checkCanvasRect(gl, 0, 0, gl.canvas.width, gl.canvas.height, [32, 64, 127, 255], "Should render 32,64,127,255 (+/-1)", 1);
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/misc/bad-arguments-test.html
+++ b/content/canvas/test/webgl/conformance/misc/bad-arguments-test.html
@@ -107,11 +107,11 @@ for (var i = 0; i < arguments.length; ++
   func3("context.getProgramInfoLog(argument)");
   func3("context.getShaderInfoLog(argument)");
   func3("context.getShaderSource(argument)");
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/error-reporting.html
+++ b/content/canvas/test/webgl/conformance/misc/error-reporting.html
@@ -90,11 +90,11 @@ shouldBeUndefined("context.framebufferTe
 // Synthetic OpenGL error
 glErrorShouldBe(context, context.INVALID_OPERATION);
 // Error state should be clear by this point
 glErrorShouldBe(context, context.NO_ERROR);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/functions-returning-strings.html
+++ b/content/canvas/test/webgl/conformance/misc/functions-returning-strings.html
@@ -92,12 +92,12 @@ if (!gl) {
   shouldReturnString("gl.getParameter(gl.VERSION)");
   shouldReturnString("gl.getParameter(gl.SHADING_LANGUAGE_VERSION)");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/instanceof-test.html
+++ b/content/canvas/test/webgl/conformance/misc/instanceof-test.html
@@ -76,14 +76,14 @@ shouldThrowWithNew(window.WebGLProgram, 
 shouldThrowWithNew(window.WebGLRenderbuffer, 'WebGLRenderbuffer');
 shouldThrowWithNew(window.WebGLShader, 'WebGLShader');
 shouldThrowWithNew(window.WebGLTexture, 'WebGLTexture');
 shouldThrowWithNew(window.WebGLUniformLocation, 'WebGLUniformLocation');
 shouldThrowWithNew(window.WebGLShaderPrecisionFormat, 'WebGLShaderPrecisionFormat');
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/misc/invalid-passed-params.html
+++ b/content/canvas/test/webgl/conformance/misc/invalid-passed-params.html
@@ -183,11 +183,11 @@ for (var i = 0; i < invalidSet.length; +
   context.getUniformLocation(program, invalidName);
   shouldBe("context.getError()", "context.INVALID_VALUE");
 }
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/is-object.html
+++ b/content/canvas/test/webgl/conformance/misc/is-object.html
@@ -63,11 +63,11 @@ debug("");
 shouldGenerateGLError(gl, gl.NO_ERROR, "shader = gl.createShader(gl.VERTEX_SHADER)");
 shouldBeTrue("gl.isShader(shader)");
 shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteShader(shader)");
 shouldBeFalse("gl.isShader(shader)");
 debug("");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/null-object-behaviour.html
+++ b/content/canvas/test/webgl/conformance/misc/null-object-behaviour.html
@@ -97,11 +97,11 @@ shouldGenerateGLError(context, context.I
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, 1, 1, 0, context.RGBA, context.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]))");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.getTexParameter(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER)");
 
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/object-deletion-behaviour.html
+++ b/content/canvas/test/webgl/conformance/misc/object-deletion-behaviour.html
@@ -418,11 +418,11 @@ if (gl.checkFramebufferStatus(gl.FRAMEBU
   shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
   // check again because many buggy implementations will have bound to the true backbuffer on deleteFramebuffer.
   shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/misc/type-conversion-test.html
+++ b/content/canvas/test/webgl/conformance/misc/type-conversion-test.html
@@ -159,12 +159,12 @@ for (var i = 0; i < args.length; ++i) {
   func1("context.uniform4f(loc, 0, argument, 0, 0)");
   func1("context.uniform4f(loc, 0, 0, argument, 0)");
   func1("context.uniform4f(loc, 0, 0, 0, argument)");
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/misc/uninitialized-test.html
+++ b/content/canvas/test/webgl/conformance/misc/uninitialized-test.html
@@ -159,12 +159,12 @@ glErrorShouldBe(gl, gl.NO_ERROR);
 //TODO: uninitialized vertex elements buffer
 //TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?)
 //TODO: uninitialized renderbuffer? (implementations would need to do a GL clear at first binding?)
 //TODO: uninitialized uniform arrays?
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/misc/webgl-specific.html
+++ b/content/canvas/test/webgl/conformance/misc/webgl-specific.html
@@ -94,11 +94,11 @@ glErrorShouldBe(gl, gl.NO_ERROR, "set/ge
 
 debug("");
 debug("Verify that drawingBufferWidth and drawingBufferHeights are implemented");
 shouldBeTrue("gl.drawingBufferWidth >= 0 && gl.drawingBufferHeight >= 0");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/get-active-test.html
+++ b/content/canvas/test/webgl/conformance/programs/get-active-test.html
@@ -125,11 +125,11 @@ context.deleteProgram(program);
 shouldBeNull("context.getActiveUniform(program, 0)");
 glErrorShouldBe(context, context.INVALID_VALUE);
 shouldBeNull("context.getActiveAttrib(program, 0)");
 glErrorShouldBe(context, context.INVALID_VALUE);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/gl-bind-attrib-location-test.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-bind-attrib-location-test.html
@@ -190,12 +190,12 @@ gl.vertexAttrib4f(0, 1, 0, 0, 1);
 checkDraw(0, 3, 255, 0, 0, 255);
 
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/gl-get-active-attribute.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-get-active-attribute.html
@@ -71,14 +71,14 @@ for (var tt = 0; tt < tests.length; ++tt
   }
   if (!found) {
     testFailed("attrib 'attr0' not found");
   }
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/programs/gl-get-active-uniform.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-get-active-uniform.html
@@ -130,14 +130,14 @@ gl.useProgram(p2);
 gl.uniform1f(l2, 1);
 glErrorShouldBe(gl, gl.NO_ERROR, "no errors setting uniform 0");
 gl.uniform1f(l1, 2);
 glErrorShouldBe(gl, gl.INVALID_OPERATION,
                 "setting a uniform using a location from another program");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/programs/gl-getshadersource.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-getshadersource.html
@@ -25,14 +25,14 @@ var gl = wtu.create3DContext("example");
 var original = document.getElementById("vshader").text;
 var shader = gl.createShader(gl.VERTEX_SHADER);
 gl.shaderSource(shader, original);
 var source = gl.getShaderSource(shader);
 shouldBe("source", "original");
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/programs/gl-shader-test.html
+++ b/content/canvas/test/webgl/conformance/programs/gl-shader-test.html
@@ -37,12 +37,12 @@ if (!gl) {
   assertMsg(shader == null,
             "should not be able to create GEOMETRY shader");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/invalid-UTF-16.html
+++ b/content/canvas/test/webgl/conformance/programs/invalid-UTF-16.html
@@ -40,11 +40,11 @@ var string = array.join('');
 
 var gl = create3DContext();
 var program = gl.createProgram();
 gl.bindAttribLocation(program, 0, string);
 testPassed("bindAttribLocation with invalid UTF-16 did not crash");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/programs/program-test.html
+++ b/content/canvas/test/webgl/conformance/programs/program-test.html
@@ -316,12 +316,12 @@ function go() {
     glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked shader should be deleted once all its attachments are removed");
 }
 
 debug("");
 go();
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/reading/read-pixels-pack-alignment.html
+++ b/content/canvas/test/webgl/conformance/reading/read-pixels-pack-alignment.html
@@ -230,11 +230,11 @@ for (var i = 0; i < formats.length; ++i)
     runTestIteration(format, gl.UNSIGNED_BYTE, 1, -1, 1);
     runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, -1);
     runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, -1);
     runTestIteration(format, gl.UNSIGNED_BYTE, 8, -1, -1);
 }
     
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html
+++ b/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html
@@ -413,11 +413,11 @@ function testFramebufferIncompleteDimens
     checkFramebuffer(gl.FRAMEBUFFER_COMPLETE);
 
     glErrorShouldBe(gl, gl.NO_ERROR);
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-test.html
+++ b/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-test.html
@@ -162,12 +162,12 @@ if (!gl) {
   glErrorShouldBe(gl, gl.NO_ERROR,
             "binding default (null) framebuffer should succeed.");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/renderbuffers/renderbuffer-initialization.html
+++ b/content/canvas/test/webgl/conformance/renderbuffers/renderbuffer-initialization.html
@@ -88,11 +88,11 @@ function runTest(gl, width, height, orde
     gl.canvas.width += 1;
     gl.canvas.height += 1;
 
     debug('');
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/draw-arrays-out-of-bounds.html
+++ b/content/canvas/test/webgl/conformance/rendering/draw-arrays-out-of-bounds.html
@@ -123,11 +123,11 @@ shouldGenerateGLError(context, context.I
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0, 0x7fffffff)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0x7fffffff, 1)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawArrays(context.TRIANGLES, 0x7fffffff, 0x7fffffff)");
 
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/draw-elements-out-of-bounds.html
+++ b/content/canvas/test/webgl/conformance/rendering/draw-elements-out-of-bounds.html
@@ -167,11 +167,11 @@ context.vertexAttribPointer(0, 3, contex
 context.disableVertexAttribArray(0);
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
 context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, null);
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
 debug("")
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/gl-clear.html
+++ b/content/canvas/test/webgl/conformance/rendering/gl-clear.html
@@ -55,12 +55,12 @@ gl.clearColor(1,1,1,1);
 gl.clear(gl.COLOR_BUFFER_BIT);
 wtu.checkCanvas(gl, [128,128,128,255], "should be 128,128,128,255");
 
 // TODO: Test depth and stencil clearing.
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/rendering/gl-drawelements.html
+++ b/content/canvas/test/webgl/conformance/rendering/gl-drawelements.html
@@ -87,12 +87,12 @@ found in the LICENSE file.
                 gl.TRIANGLES, 3, gl.UNSIGNED_INT,
                 gl.INVALID_ENUM, "gl.DrawElements should return INVALID_ENUM with UNSIGNED_INT");
 
        }
 
        init();
        successfullyParsed = true;
     </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/gl-scissor-test.html
+++ b/content/canvas/test/webgl/conformance/rendering/gl-scissor-test.html
@@ -62,12 +62,12 @@ if (!gl) {
   checkPixel(b, 0, 1, [0, 0, 0, 0]);
   checkPixel(b, 1, 1, [0, 0, 0, 0]);
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/line-loop-tri-fan.html
+++ b/content/canvas/test/webgl/conformance/rendering/line-loop-tri-fan.html
@@ -232,11 +232,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
         <canvas id="testbed" width="10px" height="10px" style="width:50px; height:50px"></canvas>
         <div id="description"></div>
         <div id="console"></div>
         <script>
             description('Verify that LINE_LOOP and TRIANGLE_FAN works correctly.');
             runTest();
             successfullyParsed = true;
         </script>
-        <script src="../../resources/js-test-post.js"></script>
+        <script>finishTest();</script>
     </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/more-than-65536-indices.html
+++ b/content/canvas/test/webgl/conformance/rendering/more-than-65536-indices.html
@@ -81,14 +81,14 @@ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, i
 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
 gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_BYTE, 0);
 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
 wtu.checkCanvas(gl, [0, 255, 0, 255], "Should be green.");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
 
--- a/content/canvas/test/webgl/conformance/rendering/point-size.html
+++ b/content/canvas/test/webgl/conformance/rendering/point-size.html
@@ -114,12 +114,12 @@ found in the LICENSE file.
                 index += 4;
             }
         }
     }
 
     successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/rendering/triangle.html
+++ b/content/canvas/test/webgl/conformance/rendering/triangle.html
@@ -112,12 +112,12 @@ There is supposed to be an example drawi
                 }
 
             pass();
        }
 
        init();
        successfullyParsed = true;
     </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-enable-enum-test.html
+++ b/content/canvas/test/webgl/conformance/state/gl-enable-enum-test.html
@@ -122,12 +122,12 @@ if (!gl) {
   }
 
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-enum-tests.html
+++ b/content/canvas/test/webgl/conformance/state/gl-enum-tests.html
@@ -75,13 +75,13 @@ if (!gl) {
               tests[ii] + " should return INVALID_ENUM.");
   }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/state/gl-get-calls.html
+++ b/content/canvas/test/webgl/conformance/state/gl-get-calls.html
@@ -145,12 +145,12 @@ else {
     shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[0] >= window.screen.width');
     shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[1] >= window.screen.height');
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-geterror.html
+++ b/content/canvas/test/webgl/conformance/state/gl-geterror.html
@@ -65,12 +65,12 @@ if (err2 == gl.NO_ERROR) {
                'err5 == gl.INVALID_VALUE || ' +
                'err6 == gl.INVALID_VALUE');
   shouldBeTrue('gl.getError() == gl.NO_ERROR');
 }
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/state/gl-getstring.html
+++ b/content/canvas/test/webgl/conformance/state/gl-getstring.html
@@ -47,12 +47,12 @@ function checkPrefix(expected, enum_val)
     testFailed("getParameter(gl." + enum_val + ") did not start with " + expected);
   }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/state/gl-object-get-calls.html
+++ b/content/canvas/test/webgl/conformance/state/gl-object-get-calls.html
@@ -266,11 +266,11 @@ gl.deleteRenderbuffer(renderbuffer);
 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE');
 gl.deleteBuffer(buffer);
 shouldBeNull('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)');
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/compressed-tex-image.html
+++ b/content/canvas/test/webgl/conformance/textures/compressed-tex-image.html
@@ -50,11 +50,11 @@ if (!gl) {
 
   shouldGenerateGLError(gl, gl.NO_ERROR, "formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)");
   shouldBeNonNull("formats");
   shouldBe("formats.length", "0");
 }
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/gl-pixelstorei.html
+++ b/content/canvas/test/webgl/conformance/textures/gl-pixelstorei.html
@@ -113,12 +113,12 @@ function init() {
     assertMsg(gl.getParameter(gl.PACK_ALIGNMENT) == table[ii],
         "PACK_ALIGNMENT is " + table[ii]);
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html
@@ -183,11 +183,11 @@ gl.clearColor(0,0,0,1);
 gl.clearDepth(1);
 
 textureLoc = gl.getUniformLocation(program, "tex");
 
 runTest();
 glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-image-and-uniform-binding-bugs.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-image-and-uniform-binding-bugs.html
@@ -55,12 +55,12 @@ tmpcanvas.width = 2;
 tmpcanvas.height = 2;
 var texture = gl.createTexture();
 shouldBeUndefined("gl.bindTexture(gl.TEXTURE_2D, texture)");
 shouldBeUndefined("gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tmpcanvas)");
 
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-image-with-invalid-data.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-image-with-invalid-data.html
@@ -89,13 +89,13 @@ test("Passing texSubImage2D parameter da
      function () {
       gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, "not a buffer");
      },
      "exception");
 
 debug("");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/tex-input-validation.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-input-validation.html
@@ -351,11 +351,11 @@ testCases =
      expectedError: gl.INVALID_OPERATION} ];
 
 for (var ii = 0; ii < testCases.length; ++ii)
     testCopyFromInternalFBO(testCases[ii]);
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d-bad-args.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d-bad-args.html
@@ -56,11 +56,11 @@ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 
 glErrorShouldBe(gl, gl.NO_ERROR, "format same as original RGBA 4_4_4_4");
 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGB, gl.UNSIGNED_BYTE, c);
 glErrorShouldBe(gl, gl.INVALID_OPERATION, "format not same as original RGBA 4_4_4_4");
 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, gl.RGBA, gl.UNSIGNED_BYTE, c);
 glErrorShouldBe(gl, gl.INVALID_OPERATION, "type not same as original RGBA 4_4_4_4");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-sub-image-2d.html
@@ -90,11 +90,11 @@ for (var i = 0; i < textureWidth; i++) {
     }
 }
 
 if (passed)
     testPassed("");
 
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/texparameter-test.html
+++ b/content/canvas/test/webgl/conformance/textures/texparameter-test.html
@@ -176,13 +176,13 @@ function init()
   if (passed) {
     testPassed("rendered as expected");
    }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-active-bind-2.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-active-bind-2.html
@@ -177,13 +177,13 @@ function init()
 
     testPassed(msg);
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-active-bind.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-active-bind.html
@@ -126,13 +126,13 @@ function init()
       testPassed(msg);
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-clear.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-clear.html
@@ -30,13 +30,13 @@ gl.bindTexture(gl.TEXTURE_2D, tex);
 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0,255,0,255]));
 wtu.drawQuad(gl);
 wtu.checkCanvas(
     gl, [0, 255, 0, 255], "should be green");
 glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-complete.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-complete.html
@@ -55,13 +55,13 @@ function init()
       "texture that is not -texture-complete- when " +
       "TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255");
 }
 
 init();
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-formats-test.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-formats-test.html
@@ -240,12 +240,12 @@ if (!gl) {
   }
   checkTypes();
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/textures/texture-mips.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-mips.html
@@ -245,12 +245,12 @@ function init()
     return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] +')';
   }
 }
 
 init();
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/textures/texture-npot.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-npot.html
@@ -213,13 +213,13 @@ function fillCubeTexture(gl, tex, width,
     gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
   for (var tt = 0; tt < targets.length; ++tt) {
     gl.texImage2D(
         targets[tt], opt_level, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
   }
 };
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
 
--- a/content/canvas/test/webgl/conformance/typedarrays/array-buffer-crash.html
+++ b/content/canvas/test/webgl/conformance/typedarrays/array-buffer-crash.html
@@ -28,11 +28,11 @@ try {
   new ArrayBuffer().byteLength;
 } catch (e) {
 }
 
 testPassed("new ArrayBuffer().byteLength did not crash");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/typedarrays/array-buffer-view-crash.html
+++ b/content/canvas/test/webgl/conformance/typedarrays/array-buffer-view-crash.html
@@ -54,12 +54,12 @@ try {
   new Uint32Array().length;
 } catch (e) {
 }
 
 testPassed("new Uint32Array().length did not crash");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/typedarrays/array-unit-tests.html
+++ b/content/canvas/test/webgl/conformance/typedarrays/array-unit-tests.html
@@ -1061,12 +1061,12 @@ function runTests() {
 
   printSummary();
 }
 
 runTests();
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-uniform-arrays.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-uniform-arrays.html
@@ -291,12 +291,12 @@ for (var tt = 0; tt < typeInfos.length; 
   gl.useProgram(null);
   glErrorShouldBe(gl, gl.NO_ERROR,
                   "can call gl.useProgram(null)");
 }
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-uniform-bool.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-uniform-bool.html
@@ -45,12 +45,12 @@ var loc = gl.getUniformLocation(gl.progr
 gl.uniform1f(loc, 1);
 glErrorShouldBe(gl, gl.NO_ERROR,
                 "should be able to set bool with gl.uniform1f");
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-uniformmatrix4fv.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-uniformmatrix4fv.html
@@ -68,12 +68,12 @@ for (var ii = 2; ii <= 4; ++ii) {
   gl[name](loc, true, mat);
   glErrorShouldBe(gl, gl.INVALID_VALUE, name + " should return INVALID_VALUE with transpose = true");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/gl-unknown-uniform.html
+++ b/content/canvas/test/webgl/conformance/uniforms/gl-unknown-uniform.html
@@ -54,12 +54,12 @@ if (!gl) {
   glErrorShouldBe(gl, gl.NO_ERROR,
             "there should be no error from trying to set an unknown uniform");
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/null-uniform-location.html
+++ b/content/canvas/test/webgl/conformance/uniforms/null-uniform-location.html
@@ -66,11 +66,11 @@ for (var i = 0; i < funcs.length; i++) {
   callString = "callUniformFunction('" + funcs[i] + "')";
   shouldBeUndefined(callString);
   glErrorShouldBe(gl, gl.NO_ERROR);
 }
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/uniform-location.html
+++ b/content/canvas/test/webgl/conformance/uniforms/uniform-location.html
@@ -102,11 +102,11 @@ locationSx2 = contextA.getUniformLocatio
 shouldBeFalse("locationSx === locationSx2");
 locationSx.foo  = {};
 locationSx2.foo = {};
 shouldBeFalse("locationSx.foo === locationSx2.foo");
 
 successfullyParsed = true;
 </script>
 
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/uniforms/uniform-samplers-test.html
+++ b/content/canvas/test/webgl/conformance/uniforms/uniform-samplers-test.html
@@ -49,12 +49,12 @@ function init()
   gl.uniform1fv(textureLoc, [1]);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
             "uniform1fv returns INVALID_OPERATION if attempting to set a sampler uniform");
 }
 
 init();
 successfullyParsed = true;
 </script>
-<script src="../../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 </body>
 </html>
 
--- a/content/canvas/test/webgl/ext-texture-filter-anisotropic.patch
+++ b/content/canvas/test/webgl/ext-texture-filter-anisotropic.patch
@@ -186,12 +186,12 @@ new file mode 100644
 +    }
 +
 +    gl.deleteTexture(texture);
 +}
 +
 +debug("");
 +successfullyParsed = true;
 +</script>
-+<script src="../../resources/js-test-post.js"></script>
++<script>finishTest();</script>
 +
 +</body>
 +</html>
--- a/content/canvas/test/webgl/extra/canvas-compositing-test.html
+++ b/content/canvas/test/webgl/extra/canvas-compositing-test.html
@@ -111,15 +111,15 @@ img tag<br/>
             gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
             gl.drawArrays(gl.TRIANGLES, 0, 3);
        }
 
        init();
        successfullyParsed = true;
     </script>
 </body>
-<script src="../resources/js-test-post.js"></script>
+<script>finishTest();</script>
 
 <script>
 </script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/extra/out-of-memory.html
+++ b/content/canvas/test/webgl/extra/out-of-memory.html
@@ -78,15 +78,15 @@ if (!gl) {
 }
 
 function finish() {
   debug("");
   successfullyParsed = true;
 }
 
 </script>
-<!-- <script src="../resources/js-test-post.js"></script> -->
+<!-- <script>finishTest();</script> -->
 
 <script>
 </script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/failing_tests_android.txt
+++ b/content/canvas/test/webgl/failing_tests_android.txt
@@ -21,15 +21,14 @@ conformance/glsl/functions/glsl-function
 conformance/glsl/functions/glsl-function-mod-gentype.html
 conformance/glsl/functions/glsl-function-normalize.html
 conformance/glsl/functions/glsl-function-reflect.html
 conformance/glsl/functions/glsl-function-sign.html
 conformance/glsl/functions/glsl-function-smoothstep-float.html
 conformance/glsl/functions/glsl-function-smoothstep-gentype.html
 conformance/glsl/functions/glsl-function-step-float.html
 conformance/glsl/functions/glsl-function-step-gentype.html
-conformance/glsl/misc/glsl-function-nodes.html
 conformance/glsl/misc/shared.html
 conformance/misc/null-object-behaviour.html
 conformance/renderbuffers/framebuffer-object-attachment.html
 conformance/textures/texture-mips.html
 conformance/textures/texture-npot.html
 conformance/textures/texture-npot-video.html
--- a/content/canvas/test/webgl/reference-cycle-test.patch
+++ b/content/canvas/test/webgl/reference-cycle-test.patch
@@ -44,17 +44,17 @@ diff --git a/content/canvas/test/webgl/c
 +
 +    // create a self-cycle on the extension object
 +    ext.ext = ext;
 +}
  
  debug("");
  successfullyParsed = true;
  </script>
- <script src="../../resources/js-test-post.js"></script>
+ <script>finishTest();</script>
  
  </body>
  </html>
 diff --git a/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html b/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
 --- a/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
 +++ b/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
 @@ -81,16 +81,17 @@ if (!gl) {
  
@@ -96,12 +96,12 @@ diff --git a/content/canvas/test/webgl/c
 +
 +    // create a self-cycle on the extension object
 +    ext.ext = ext;
 +}
  
  debug("");
  successfullyParsed = true;
  </script>
- <script src="../../resources/js-test-post.js"></script>
+ <script>finishTest();</script>
  
  </body>
  </html>
deleted file mode 100644
--- a/content/canvas/test/webgl/resources/js-test-post.js
+++ /dev/null
@@ -1,3 +0,0 @@
-shouldBeTrue("successfullyParsed");
-debug('<br /><span class="pass">TEST COMPLETE</span>');
-notifyFinishedToHarness()
--- a/content/canvas/test/webgl/resources/js-test-pre.js
+++ b/content/canvas/test/webgl/resources/js-test-pre.js
@@ -464,35 +464,12 @@ function gc() {
         temp += "foo";
         gcRec(n-1);
     }
     for (var i = 0; i < 1000; i++)
         gcRec(10);
 }
 
 function finishTest() {
-  testPassed("beginning of finishTest: " + (new Date().getTime()));
-
-  successfullyParsed = true;
-  var epilogue = document.createElement("script");
-  epilogue.onload = function() {
-    testPassed("finishTest epilogue onload: " + (new Date().getTime()));
-    if (window.nonKhronosFrameworkNotifyDone) {
-      window.nonKhronosFrameworkNotifyDone();
-    }
-  };
-
-  var basePath = "";
-  var expectedBase = "js-test-pre.js";
-  var scripts = document.getElementsByTagName('script');
-  for (var script, i = 0; script = scripts[i]; i++) {
-    var src = script.src;
-    var l = src.length;
-    if (src.substr(l - expectedBase.length) == expectedBase) {
-      basePath = src.substr(0, l - expectedBase.length);
-      break;
-    }
-  }
-  epilogue.src = basePath + "js-test-post.js";
-  document.body.appendChild(epilogue);
-  testPassed("end of finishTest: " + (new Date().getTime()));
+    debug('<br /><span class="pass">TEST COMPLETE</span>');
+    notifyFinishedToHarness();
 }
 
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -137,18 +137,16 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aP
           ...
         }
      */
     mEvent = new nsEvent(false, 0);
     mEvent->time = PR_Now();
   }
 
   InitPresContextData(aPresContext);
-
-  NS_ASSERTION(mEvent->message != NS_PAINT, "Trying to create a DOM paint event!");
 }
 
 void
 nsDOMEvent::InitPresContextData(nsPresContext* aPresContext)
 {
   mPresContext = aPresContext;
   // Get the explicit original target (if it's anonymous make it null)
   {
@@ -596,44 +594,16 @@ nsDOMEvent::DuplicatePrivateData()
       break;
     }
     case NS_GUI_EVENT:
     {
       // Not copying widget, it is a weak reference.
       newEvent = new nsGUIEvent(false, msg, nullptr);
       break;
     }
-    case NS_SIZE_EVENT:
-    {
-      nsSizeEvent* sizeEvent = new nsSizeEvent(false, msg, nullptr);
-      NS_ENSURE_TRUE(sizeEvent, NS_ERROR_OUT_OF_MEMORY);
-      sizeEvent->mWinWidth = static_cast<nsSizeEvent*>(mEvent)->mWinWidth;
-      sizeEvent->mWinHeight = static_cast<nsSizeEvent*>(mEvent)->mWinHeight;
-      newEvent = sizeEvent;
-      break;
-    }
-    case NS_SIZEMODE_EVENT:
-    {
-      newEvent = new nsSizeModeEvent(false, msg, nullptr);
-      NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
-      static_cast<nsSizeModeEvent*>(newEvent)->mSizeMode =
-        static_cast<nsSizeModeEvent*>(mEvent)->mSizeMode;
-      break;
-    }
-    case NS_ZLEVEL_EVENT:
-    {
-      nsZLevelEvent* zLevelEvent = new nsZLevelEvent(false, msg, nullptr);
-      NS_ENSURE_TRUE(zLevelEvent, NS_ERROR_OUT_OF_MEMORY);
-      nsZLevelEvent* oldZLevelEvent = static_cast<nsZLevelEvent*>(mEvent);
-      zLevelEvent->mPlacement = oldZLevelEvent->mPlacement;
-      zLevelEvent->mImmediate = oldZLevelEvent->mImmediate;
-      zLevelEvent->mAdjusted = oldZLevelEvent->mAdjusted;
-      newEvent = zLevelEvent;
-      break;
-    }
     case NS_SCROLLBAR_EVENT:
     {
       newEvent = new nsScrollbarEvent(false, msg, nullptr);
       NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
       static_cast<nsScrollbarEvent*>(newEvent)->position =
         static_cast<nsScrollbarEvent*>(mEvent)->position;
       break;
     }
@@ -787,24 +757,16 @@ nsDOMEvent::DuplicatePrivateData()
       mutationEvent->mRelatedNode = oldMutationEvent->mRelatedNode;
       mutationEvent->mAttrName = oldMutationEvent->mAttrName;
       mutationEvent->mPrevAttrValue = oldMutationEvent->mPrevAttrValue;
       mutationEvent->mNewAttrValue = oldMutationEvent->mNewAttrValue;
       mutationEvent->mAttrChange = oldMutationEvent->mAttrChange;
       newEvent = mutationEvent;
       break;
     }
-#ifdef ACCESSIBILITY
-    case NS_ACCESSIBLE_EVENT:
-    {
-      newEvent = new nsAccessibleEvent(false, msg, nullptr);
-      isInputEvent = true;
-      break;
-    }
-#endif
     case NS_FORM_EVENT:
     {
       newEvent = new nsFormEvent(false, msg);
       break;
     }
     case NS_FOCUS_EVENT:
     {
       nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg);
--- a/content/events/test/test_bug422132.html
+++ b/content/events/test/test_bug422132.html
@@ -34,16 +34,17 @@ function hitEventLoop(aFunc, aTimes)
   } else {
     setTimeout(aFunc, 20);
   }
 }
 
 function runTests()
 {
   SpecialPowers.setIntPref("mousewheel.min_line_scroll_amount", 1);
+  SpecialPowers.setIntPref("mousewheel.transaction.timeout", 100000);
 
   var target = document.getElementById("target");
 
   var scrollLeft = target.scrollLeft;
   var scrollTop = target.scrollTop;
   synthesizeWheel(target, 10, 10,
     { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
       deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 });
@@ -74,16 +75,17 @@ function runTests()
           { deltaMode: WheelEvent.DOM_DELTA_LINE,
             deltaX: 0.5, deltaY: 0.5, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 });
         hitEventLoop(function () {
           ok(target.scrollLeft > scrollLeft,
              "not scrolled to right by 0.5 line delta value with pending 0.5 line delta");
           ok(target.scrollTop > scrollTop,
              "not scrolled to bottom by 0.5 line delta value with pending 0.5 line delta");
           SpecialPowers.clearUserPref("mousewheel.min_line_scroll_amount");
+          SpecialPowers.clearUserPref("mousewheel.transaction.timeout");
           SimpleTest.finish();
         }, 20);
       }, 20);
     }, 20);
   }, 20);
 }
 
 </script>
--- a/content/events/test/window_bug659071.html
+++ b/content/events/test/window_bug659071.html
@@ -29,30 +29,30 @@ function hitEventLoop(aFunc, aTimes)
   } else {
     setTimeout(aFunc, 20);
   }
 }
 
 function runTests()
 {
   SpecialPowers.setIntPref("mousewheel.with_control.action", 3);
-  SpecialPowers.setFullZoom(window, 1.0);
+  synthesizeKey("0", { accelKey: true });
 
   var video = document.getElementById("v");
   hitEventLoop(function () {
     is(SpecialPowers.getFullZoom(window), 1.0,
        "failed to reset zoom");
     synthesizeWheel(video, 10, 10,
       { deltaMode: WheelEvent.DOM_DELTA_LINE, ctrlKey: true,
         deltaX: 0, deltaY: 1.0, lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 });
     hitEventLoop(function () {
       isnot(SpecialPowers.getFullZoom(window), 1.0,
              "failed to zoom by ctrl+wheel");
 
-      SpecialPowers.setFullZoom(window, 1.0);
+      synthesizeKey("0", { accelKey: true });
       SpecialPowers.clearUserPref("mousewheel.with_control.action");
 
       hitEventLoop(window.opener.finish, 20);
     }, 20);
   }, 20);
 }
 
 </script>
--- a/content/events/test/window_wheel_default_action.html
+++ b/content/events/test/window_wheel_default_action.html
@@ -777,29 +777,29 @@ function doTestZoom(aSettings, aCallback
           ok(SpecialPowers.getFullZoom(window) > 1.0,
              description + "not zoomed in, got " + SpecialPowers.getFullZoom(window));
         } else {
           ok(SpecialPowers.getFullZoom(window) < 1.0,
              description + "not zoomed out, got " + SpecialPowers.getFullZoom(window));
         }
       }
 
-      SpecialPowers.setFullZoom(window, 1.0);
+      synthesizeKey("0", { accelKey: true });
       hitEventLoop(doNextTest, 20);
     }, 20);
   }
   doNextTest();
 }
 
 function doTestZoomedScroll()
 {
   function testZoomedPixelScroll()
   {
     // Reset zoom and store the scroll amount into the data.
-    SpecialPowers.setFullZoom(window, 1.0);
+    synthesizeKey("0", { accelKey: true });
     gScrollableElement.scrollTop = 1000;
     gScrollableElement.scrollLeft = 1000;
     // Ensure not to be in reflow.
     hitEventLoop(function () {
       function handler(aEvent)
       {
         if (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS) {
           is(aEvent.detail, 16,
@@ -838,28 +838,28 @@ function doTestZoomedScroll()
             ok(Math.abs(gScrollableElement.scrollLeft - (1000 + (scrolledX - 1000) / 2)) <= 1,
                "doTestZoomedScroll: zoomed horizontal scroll amount by pixel wheel event is different from normal, scrollLeft=" +
                  gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
             ok(Math.abs(gScrollableElement.scrollTop - (1000 + (scrolledY - 1000) / 2)) <= 1,
                "doTestZoomedScroll: zoomed vertical scroll amount by pixel wheel event is different from normal, scrollTop=" +
                  gScrollableElement.scrollTop + ", scrolledY=" + scrolledY);
             window.removeEventListener("MozMousePixelScroll", handler, true);
 
-            SpecialPowers.setFullZoom(window, 1.0);
+            synthesizeKey("0", { accelKey: true });
             testZoomedLineScroll();
           }, 20);
         }, 20);
       }, 20);
     }, 20);
   }
 
   function testZoomedLineScroll()
   {
     // Reset zoom and store the scroll amount into the data.
-    SpecialPowers.setFullZoom(window, 1.0);
+    synthesizeKey("0", { accelKey: true });
     gScrollableElement.scrollTop = 1000;
     gScrollableElement.scrollLeft = 1000;
     // Ensure not to be in reflow.
     hitEventLoop(function () {
       var lineHeightX, lineHeightY;
       function handler(aEvent)
       {
         if (aEvent.axis == MouseScrollEvent.HORIZONTAL_AXIS) {
@@ -910,17 +910,17 @@ function doTestZoomedScroll()
                "doTestZoomedScroll: zoomed horizontal scroll amount by line wheel event is different from normal, scrollLeft=" +
                  gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
             ok(Math.abs(gScrollableElement.scrollTop - scrolledY) <= 1,
                "doTestZoomedScroll: zoomed vertical scroll amount by line wheel event is different from normal, scrollTop=" +
                  gScrollableElement.scrollTop + ", scrolledY=" + scrolledY);
 
             window.removeEventListener("MozMousePixelScroll", handler, true);
 
-            SpecialPowers.setFullZoom(window, 1.0);
+            synthesizeKey("0", { accelKey: true });
           }, 20);
         }, 20);
       }, 20);
     }, 20);
   }
 
   // XXX It's too difficult to test page scroll because the page scroll amount
   //     is computed by complex logic.
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -7,16 +7,17 @@
 
 #include "nsGenericHTMLFrameElement.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "nsIAppsService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMApplicationRegistry.h"
+#include "nsIPermissionManager.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFrameLoader, nsIFrameLoader)
@@ -285,28 +286,25 @@ nsGenericHTMLFrameElement::GetReallyIsBr
   // Fail if this frame doesn't have the mozbrowser attribute.
   bool isBrowser = false;
   GetMozbrowser(&isBrowser);
   if (!isBrowser) {
     return NS_OK;
   }
 
   // Fail if the node principal isn't trusted.
-  // TODO: check properly for mozApps rights when mozApps will be less hacky.
   nsIPrincipal *principal = NodePrincipal();
-  nsCOMPtr<nsIURI> principalURI;
-  principal->GetURI(getter_AddRefs(principalURI));
-  if (!nsContentUtils::IsSystemPrincipal(principal) &&
-      !nsContentUtils::URIIsChromeOrInPref(principalURI,
-                                           "dom.mozBrowserFramesWhitelist")) {
-    return NS_OK;
-  }
+  nsCOMPtr<nsIPermissionManager> permMgr =
+    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+  NS_ENSURE_STATE(permMgr);
 
-  // Otherwise, succeed.
-  *aOut = true;
+  PRUint32 permission = nsIPermissionManager::DENY_ACTION;
+  nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission);
+  NS_ENSURE_SUCCESS(rv, NS_OK);
+  *aOut = permission == nsIPermissionManager::ALLOW_ACTION;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGenericHTMLFrameElement::GetReallyIsApp(bool *aOut)
 {
   nsAutoString manifestURL;
   GetAppManifestURL(manifestURL);
--- a/content/svg/content/src/SVGFragmentIdentifier.cpp
+++ b/content/svg/content/src/SVGFragmentIdentifier.cpp
@@ -27,67 +27,67 @@ GetViewElement(nsIDocument *aDocument, c
   dom::Element* element = aDocument->GetElementById(aId);
   return (element && element->IsSVG(nsGkAtoms::view)) ?
             static_cast<nsSVGViewElement*>(element) : nullptr;
 }
 
 void 
 SVGFragmentIdentifier::SaveOldPreserveAspectRatio(nsSVGSVGElement *root)
 {
-  const SVGPreserveAspectRatio *oldPARPtr = root->GetPreserveAspectRatioProperty();
-  if (!oldPARPtr) {
+  if (root->mPreserveAspectRatio.IsExplicitlySet()) {
     root->SetPreserveAspectRatioProperty(root->mPreserveAspectRatio.GetBaseValue());
   }
 }
 
 void 
 SVGFragmentIdentifier::RestoreOldPreserveAspectRatio(nsSVGSVGElement *root)
 {
   const SVGPreserveAspectRatio *oldPARPtr = root->GetPreserveAspectRatioProperty();
   if (oldPARPtr) {
     root->mPreserveAspectRatio.SetBaseValue(*oldPARPtr, root);
-    root->ClearPreserveAspectRatioProperty();
+  } else if (root->mPreserveAspectRatio.IsExplicitlySet()) {
+    root->RemoveAttribute(NS_LITERAL_STRING("preserveAspectRatio"));
   }
 }
 
 void 
 SVGFragmentIdentifier::SaveOldViewBox(nsSVGSVGElement *root)
 {
-  const nsSVGViewBoxRect *oldViewBoxPtr = root->GetViewBoxProperty();
-  if (!oldViewBoxPtr) {
+  if (root->mViewBox.IsExplicitlySet()) {
     root->SetViewBoxProperty(root->mViewBox.GetBaseValue());
   }
 }
 
 void 
 SVGFragmentIdentifier::RestoreOldViewBox(nsSVGSVGElement *root)
 {
   const nsSVGViewBoxRect *oldViewBoxPtr = root->GetViewBoxProperty();
   if (oldViewBoxPtr) {
     root->mViewBox.SetBaseValue(*oldViewBoxPtr, root);
-    root->ClearViewBoxProperty();
+  } else if (root->mViewBox.IsExplicitlySet()) {
+    root->RemoveAttribute(NS_LITERAL_STRING("viewBox"));
   }
 }
 
 void 
 SVGFragmentIdentifier::SaveOldZoomAndPan(nsSVGSVGElement *root)
 {
-  PRUint16 oldZoomAndPan = root->GetZoomAndPanProperty();
-  if (oldZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_UNKNOWN) {
+  if (root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].IsExplicitlySet()) {
     root->SetZoomAndPanProperty(root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].GetBaseValue());
   }
 }
 
 void 
 SVGFragmentIdentifier::RestoreOldZoomAndPan(nsSVGSVGElement *root)
 {
   PRUint16 oldZoomAndPan = root->GetZoomAndPanProperty();
   if (oldZoomAndPan != nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_UNKNOWN) {
     root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(oldZoomAndPan, root);
-    root->ClearZoomAndPanProperty();
+  } else if (root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].IsExplicitlySet()) {
+    root->RemoveAttribute(NS_LITERAL_STRING("zoomAndPan"));
   }
 }
 
 bool
 SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
                                           nsSVGSVGElement *root)
 {
   if (!IsMatchingParameter(aViewSpec, NS_LITERAL_STRING("svgView"))) {
@@ -141,31 +141,28 @@ SVGFragmentIdentifier::ProcessSVGViewSpe
       zoomAndPanParams = &params;
     } else {
       // We don't support transform or viewTarget currently
       return false;
     }
   } while (tokenizer.hasMoreTokens());
 
   if (viewBoxParams) {
-    SaveOldViewBox(root);
     root->mViewBox.SetBaseValueString(*viewBoxParams, root);
   } else {
     RestoreOldViewBox(root);
   }
 
   if (preserveAspectRatioParams) {
-    SaveOldPreserveAspectRatio(root);
     root->mPreserveAspectRatio.SetBaseValueString(*preserveAspectRatioParams, root);
   } else {
     RestoreOldPreserveAspectRatio(root);
   }
 
   if (zoomAndPanParams) {
-    SaveOldZoomAndPan(root);
     nsCOMPtr<nsIAtom> valAtom = do_GetAtom(*zoomAndPanParams);
     const nsSVGEnumMapping *mapping = root->sZoomAndPanMap;
     while (mapping->mKey) {
       if (valAtom == *(mapping->mKey)) {
         root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(mapping->mVal, root);
         break;
       }
       mapping++;
@@ -182,45 +179,51 @@ SVGFragmentIdentifier::ProcessFragmentId
                                                  const nsAString &aAnchorName)
 {
   NS_ABORT_IF_FALSE(aDocument->GetRootElement()->IsSVG(nsGkAtoms::svg),
                     "expecting an SVG root element");
 
   nsSVGSVGElement *rootElement =
     static_cast<nsSVGSVGElement*>(aDocument->GetRootElement());
 
+  if (!rootElement->mUseCurrentView) {
+    SaveOldViewBox(rootElement);
+    SaveOldPreserveAspectRatio(rootElement);
+    SaveOldZoomAndPan(rootElement);
+  }
+
   const nsSVGViewElement *viewElement = GetViewElement(aDocument, aAnchorName);
 
   if (viewElement) {
     if (viewElement->mViewBox.IsExplicitlySet()) {
-      SaveOldViewBox(rootElement);
       rootElement->mViewBox.SetBaseValue(
         viewElement->mViewBox.GetBaseValue(), rootElement);
     } else {
       RestoreOldViewBox(rootElement);
     }
     if (viewElement->mPreserveAspectRatio.IsExplicitlySet()) {
-      SaveOldPreserveAspectRatio(rootElement);
       rootElement->mPreserveAspectRatio.SetBaseValue(
         viewElement->mPreserveAspectRatio.GetBaseValue(), rootElement);
     } else {
       RestoreOldPreserveAspectRatio(rootElement);
     }
     if (viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].IsExplicitlySet()) {
-      SaveOldZoomAndPan(rootElement);
       rootElement->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(
         viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].GetBaseValue(), rootElement);
     } else {
       RestoreOldZoomAndPan(rootElement);
     }
     rootElement->mUseCurrentView = true;
     return true;
   }
 
   rootElement->mUseCurrentView = ProcessSVGViewSpec(aAnchorName, rootElement);
   if (rootElement->mUseCurrentView) {
     return true;
   }
   RestoreOldViewBox(rootElement);
+  rootElement->ClearViewBoxProperty();
   RestoreOldPreserveAspectRatio(rootElement);
+  rootElement->ClearPreserveAspectRatioProperty();
   RestoreOldZoomAndPan(rootElement);
+  rootElement->ClearZoomAndPanProperty();
   return false;
 }
--- a/content/xbl/src/nsXBLWindowKeyHandler.cpp
+++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp
@@ -454,17 +454,17 @@ nsXBLWindowKeyHandler::WalkHandlersAndEx
   nsresult rv;
 
   // Try all of the handlers until we find one that matches the event.
   for (nsXBLPrototypeHandler *currHandler = aHandler; currHandler;
        currHandler = currHandler->GetNextHandler()) {
     bool stopped = aKeyEvent->IsDispatchStopped();
     if (stopped) {
       // The event is finished, don't execute any more handlers
-      return NS_OK;
+      return false;
     }
 
     if (!EventMatched(currHandler, aEventType, aKeyEvent,
                       aCharCode, aIgnoreShiftKey))
       continue;  // try the next one
 
     // Before executing this handler, check that it's not disabled,
     // and that it has something to do (oncommand of the <key> or its
--- a/dom/activities/src/ActivitiesService.jsm
+++ b/dom/activities/src/ActivitiesService.jsm
@@ -218,19 +218,22 @@ let Activities = {
         if (!sysmm) {
           // System message is not present, what should we do?
           return;
         }
 
         debug("Sending system message...");
         let result = aResults.options[aChoice];
         sysmm.sendMessage("activity", {
-          "id": aMsg.id,
-          "payload": aMsg.options
-        }, Services.io.newURI(result.manifest, null, null));
+            "id": aMsg.id,
+            "payload": aMsg.options,
+            "target": result.description
+          },
+          Services.io.newURI(result.description.href, null, null),
+          Services.io.newURI(result.manifest, null, null));
 
         if (!result.description.returnValue) {
           ppmm.sendAsyncMessage("Activity:FireSuccess", {
             "id": aMsg.id,
             "result": null
           });
         }
       };
--- a/dom/alarm/AlarmDB.jsm
+++ b/dom/alarm/AlarmDB.jsm
@@ -41,16 +41,17 @@ AlarmDB.prototype = {
     debug("upgradeSchema()");
 
     let objectStore = aDb.createObjectStore(ALARMSTORE_NAME, { keyPath: "id", autoIncrement: true });
 
     objectStore.createIndex("date",           "date",           { unique: false });
     objectStore.createIndex("ignoreTimezone", "ignoreTimezone", { unique: false });
     objectStore.createIndex("timezoneOffset", "timezoneOffset", { unique: false });
     objectStore.createIndex("data",           "data",           { unique: false });
+    objectStore.createIndex("pageURL",        "pageURL",        { unique: false });
     objectStore.createIndex("manifestURL",    "manifestURL",    { unique: false });
 
     debug("Created object stores and indexes");
   },
 
   /**
    * @param aAlarm
    *        The record to be added.
--- a/dom/alarm/AlarmService.jsm
+++ b/dom/alarm/AlarmService.jsm
@@ -93,16 +93,17 @@ let AlarmService = {
 
       case "AlarmsManager:Add":
         // prepare a record for the new alarm to be added
         let newAlarm = {
           date: json.date, 
           ignoreTimezone: json.ignoreTimezone, 
           timezoneOffset: this._currentTimezoneOffset, 
           data: json.data,
+          pageURL: json.pageURL,
           manifestURL: json.manifestURL
         };
 
         let newAlarmTime = this._getAlarmTime(newAlarm);
         if (newAlarmTime <= Date.now()) {
           debug("Adding a alarm that has past time. Return DOMError.");
           this._debugCurrentAlarm();
           this._sendAsyncMessage(mm, "Add", false, json.requestId, "InvalidStateError");
@@ -248,17 +249,18 @@ let AlarmService = {
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
       }
     );
   },
 
   _fireSystemMessage: function _fireSystemMessage(aAlarm) {
     debug("Fire system message: " + JSON.stringify(aAlarm));
     let manifestURI = Services.io.newURI(aAlarm.manifestURL, null, null);
-    messenger.sendMessage("alarm", aAlarm, manifestURI);
+    let pageURI = Services.io.newURI(aAlarm.pageURL, null, null);
+    messenger.sendMessage("alarm", aAlarm, pageURI, manifestURI);
   },
 
   _onAlarmFired: function _onAlarmFired() {
     debug("_onAlarmFired()");
 
     if (this._currentAlarm) {
       this._fireSystemMessage(this._currentAlarm);
       this._removeAlarmFromDb(this._currentAlarm.id, null);
--- a/dom/alarm/AlarmsManager.js
+++ b/dom/alarm/AlarmsManager.js
@@ -63,17 +63,22 @@ AlarmsManager.prototype = {
       default:
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
         break;
     }
 
     let request = this.createRequest();
     this._cpmm.sendAsyncMessage(
       "AlarmsManager:Add", 
-      { requestId: this.getRequestId(request), date: aDate, ignoreTimezone: isIgnoreTimezone, data: aData, manifestURL: this._manifestURL }
+      { requestId: this.getRequestId(request),
+        date: aDate,
+        ignoreTimezone: isIgnoreTimezone,
+        data: aData,
+        pageURL: this._pageURL,
+        manifestURL: this._manifestURL }
     );
     return request;
   },
 
   remove: function remove(aId) {
     debug("remove()");
 
     return this._cpmm.sendSyncMessage(
@@ -151,16 +156,17 @@ AlarmsManager.prototype = {
 
     // Add the valid messages to be listened.
     this.initHelper(aWindow, ["AlarmsManager:Add:Return:OK", "AlarmsManager:Add:Return:KO", 
                               "AlarmsManager:GetAll:Return:OK", "AlarmsManager:GetAll:Return:KO"]);
 
     // Get the manifest URL if this is an installed app
     let appsService = Cc["@mozilla.org/AppsService;1"]
                         .getService(Ci.nsIAppsService);
+    this._pageURL = principal.URI.spec;
     this._manifestURL = appsService.getManifestURLByLocalId(principal.appId);
   },
 
   // Called from DOMRequestIpcHelper.
   uninit: function uninit() {
     debug("uninit()");
   },
 }
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -109,16 +109,20 @@ let DOMApplicationRegistry = {
   _registerActivities: function(aManifest, aApp) {
     if (!aManifest.activities) {
       return;
     }
 
     let manifest = new DOMApplicationManifest(aManifest, aApp.origin);
     for (let activity in aManifest.activities) {
       let description = aManifest.activities[activity];
+      if (!description.href) {
+        description.href = manifest.launch_path;
+      }
+      description.href = manifest.resolveFromOrigin(description.href);
       let json = {
         "manifest": aApp.manifestURL,
         "name": activity,
         "title": manifest.name,
         "icon": manifest.iconURLForSize(128),
         "description": description
       }
       cpmm.sendAsyncMessage("Activities:Register", json);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -65,16 +65,17 @@
 #include "mozilla/dom/workers/Workers.h"
 #include "nsJSPrincipals.h"
 #include "mozilla/Attributes.h"
 
 // Interfaces Needed
 #include "nsIFrame.h"
 #include "nsCanvasFrame.h"
 #include "nsIWidget.h"
+#include "nsIWidgetListener.h"
 #include "nsIBaseWindow.h"
 #include "nsDeviceSensors.h"
 #include "nsIContent.h"
 #include "nsIContentViewerEdit.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
@@ -7703,20 +7704,21 @@ nsGlobalWindow::ActivateOrDeactivate(boo
   nsCOMPtr<nsIDOMWindow> topLevelWindow;
   if (topLevelWidget == mainWidget) {
     topLevelWindow = static_cast<nsIDOMWindow*>(this);
   } else {
     // This is a workaround for the following problem:
     // When a window with an open sheet loses focus, only the sheet window
     // receives the NS_DEACTIVATE event. However, it's not the sheet that
     // should lose the active styling, but the containing top level window.
-    void* clientData;
-    topLevelWidget->GetClientData(clientData); // clientData is nsXULWindow
-    nsISupports* data = static_cast<nsISupports*>(clientData);
-    nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(data));
+
+    // widgetListener should be a nsXULWindow
+    nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
+    nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
+    nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
     topLevelWindow = do_GetInterface(req);
   }
   if (topLevelWindow) {
     nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
     piWin->SetActive(aActivate);
   }
 }
 
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -216,17 +216,19 @@ nsScriptNameSpaceManager::FillHashWithDO
     return NS_OK;
   }
 
   bool found_old;
   nsCOMPtr<nsIInterfaceInfo> if_info;
   const char *if_name = nullptr;
   const nsIID *iid;
 
-  for ( ; domInterfaces->IsDone() == NS_ENUMERATOR_FALSE; domInterfaces->Next()) {
+  for ( ;
+       domInterfaces->IsDone() == static_cast<nsresult>(NS_ENUMERATOR_FALSE);
+       domInterfaces->Next()) {
     rv = domInterfaces->CurrentItem(getter_AddRefs(entry));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIInterfaceInfo> if_info(do_QueryInterface(entry));
     if_info->GetNameShared(&if_name);
     if_info->GetIIDShared(&iid);
     rv = RegisterInterface(if_name + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
                            iid, &found_old);
--- a/dom/browser-element/mochitest/browserElementTestHelpers.js
+++ b/dom/browser-element/mochitest/browserElementTestHelpers.js
@@ -44,24 +44,16 @@ const browserElementTestHelpers = {
   getEnabledPref: function() {
     return this._getBoolPref('dom.mozBrowserFramesEnabled');
   },
 
   setEnabledPref: function(value) {
     this._setBoolPref('dom.mozBrowserFramesEnabled', value);
   },
 
-  getWhitelistPref: function() {
-    return this._getCharPref('dom.mozBrowserFramesWhitelist');
-  },
-
-  setWhitelistPref: function(whitelist) {
-    this._setCharPref('dom.mozBrowserFramesWhitelist', whitelist);
-  },
-
   getOOPDisabledPref: function() {
     return this._getBoolPref('dom.ipc.tabs.disabled');
   },
 
   setOOPDisabledPref: function(value) {
     this._setBoolPref('dom.ipc.tabs.disabled', value);
   },
 
@@ -76,35 +68,45 @@ const browserElementTestHelpers = {
   getPageThumbsEnabledPref: function() {
     return this._getBoolPref('browser.pageThumbs.enabled');
   },
 
   setPageThumbsEnabledPref: function(value) {
     this._setBoolPref('browser.pageThumbs.enabled', value);
   },
 
-  addToWhitelist: function() {
-    var whitelist = this.getWhitelistPref();
-    whitelist += ',  http://' + window.location.host + ',  ';
-    this.setWhitelistPref(whitelist);
+  addPermission: function() {
+    SpecialPowers.addPermission("browser", true, document);
+    this.tempPermissions.push(location.href)
+  },
+
+  removeAllTempPermissions: function() {
+    for(var i = 0; i < this.tempPermissions.length; i++) {
+      SpecialPowers.removePermission("browser", this.tempPermissions[i]);
+    }
+  },
+
+  addPermissionForUrl: function(url) {
+    SpecialPowers.addPermission("browser", true, url);
+    this.tempPermissions.push(url);
   },
 
   restoreOriginalPrefs: function() {
     this.setEnabledPref(this.origEnabledPref);
-    this.setWhitelistPref(this.origWhitelistPref);
     this.setOOPDisabledPref(this.origOOPDisabledPref);
     this.setOOPByDefaultPref(this.origOOPByDefaultPref);
     this.setPageThumbsEnabledPref(this.origPageThumbsEnabledPref);
+    this.removeAllTempPermissions();
   },
 
   'origEnabledPref': null,
-  'origWhitelistPref': null,
   'origOOPDisabledPref': null,
   'origOOPByDefaultPref': null,
   'origPageThumbsEnabledPref': null,
+  'tempPermissions': [],
 
   // Some basically-empty pages from different domains you can load.
   'emptyPage1': 'http://example.com' +
                 window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
                 '/file_empty.html',
   'emptyPage2': 'http://example.org' +
                 window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
                 '/file_empty.html',
@@ -112,17 +114,16 @@ const browserElementTestHelpers = {
                 window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
                 '/file_empty.html',
   'focusPage': 'http://example.org' +
                 window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
                 '/file_focus.html',
 };
 
 browserElementTestHelpers.origEnabledPref = browserElementTestHelpers.getEnabledPref();
-browserElementTestHelpers.origWhitelistPref = browserElementTestHelpers.getWhitelistPref();
 browserElementTestHelpers.origOOPDisabledPref = browserElementTestHelpers.getOOPDisabledPref();
 browserElementTestHelpers.origOOPByDefaultPref = browserElementTestHelpers.getOOPByDefaultPref();
 browserElementTestHelpers.origPageThumbsEnabledPref = browserElementTestHelpers.getPageThumbsEnabledPref();
 
 // Disable tab view; it seriously messes us up.
 browserElementTestHelpers.setPageThumbsEnabledPref(false);
 
 // Enable or disable OOP-by-default depending on the test's filename.  You can
--- a/dom/browser-element/mochitest/browserElement_Alert.js
+++ b/dom/browser-element/mochitest/browserElement_Alert.js
@@ -7,17 +7,17 @@
 SimpleTest.waitForExplicitFinish();
 
 var numPendingChildTests = 0;
 var iframe;
 var mm;
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
   document.body.appendChild(iframe);
 
   mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
   mm.addMessageListener('test-success', function(msg) {
     numPendingChildTests--;
--- a/dom/browser-element/mochitest/browserElement_AlertInFrame.js
+++ b/dom/browser-element/mochitest/browserElement_AlertInFrame.js
@@ -3,17 +3,17 @@
 
 // Test that alert works from inside an <iframe> inside an <iframe mozbrowser>.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
     is(e.detail.message, 'Hello');
     SimpleTest.finish();
   });
--- a/dom/browser-element/mochitest/browserElement_AppWindowNamespace.js
+++ b/dom/browser-element/mochitest/browserElement_AppWindowNamespace.js
@@ -3,17 +3,17 @@
 
 // Bug 780351 - Test that mozapp divides the window name namespace.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
   iframe1.setAttribute('mozapp', 'http://example.org/manifest.webapp');
 
   // Two mozapp frames for different apps with the same code both do the same
   // window.open("foo", "bar") call.  We should get two mozbrowseropenwindow
   // events.
--- a/dom/browser-element/mochitest/browserElement_BackForward.js
+++ b/dom/browser-element/mochitest/browserElement_BackForward.js
@@ -14,17 +14,17 @@ function addOneShotIframeEventListener(e
     fn(e);
   };
 
   iframe.addEventListener(event, wrapper);
 }
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   addOneShotIframeEventListener('mozbrowserloadend', function() {
     SimpleTest.executeSoon(test2);
   });
 
--- a/dom/browser-element/mochitest/browserElement_BrowserWindowNamespace.js
+++ b/dom/browser-element/mochitest/browserElement_BrowserWindowNamespace.js
@@ -6,17 +6,17 @@
 // they share a window name namespace.
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
 
   // Two mozbrowser frames with the same code both do the same
   // window.open("foo", "bar") call.  We should only get one
   // mozbrowseropenwindow event.
 
--- a/dom/browser-element/mochitest/browserElement_Close.js
+++ b/dom/browser-element/mochitest/browserElement_Close.js
@@ -3,17 +3,17 @@
 
 // Test that window.close() works.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
   document.body.appendChild(iframe);
 
   iframe.addEventListener("mozbrowserclose", function(e) {
     ok(true, "got mozbrowserclose event.");
     SimpleTest.finish();
--- a/dom/browser-element/mochitest/browserElement_CloseFromOpener.js
+++ b/dom/browser-element/mochitest/browserElement_CloseFromOpener.js
@@ -3,17 +3,17 @@
 
 // Bug 764718 - Test that window.close() works from the opener window.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     ok(true, "got openwindow event.");
     document.body.appendChild(e.detail.frameElement);
 
--- a/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
+++ b/dom/browser-element/mochitest/browserElement_ContextmenuEvents.js
@@ -26,17 +26,17 @@ var iframeScript = function() {
 
 var trigger1 = function() {
   content.fireContextMenu(content.document.getElementById('menu1-trigger'));
 };
 
 function runTest() {
 
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
   document.body.appendChild(iframe1);
   iframe1.src = 'data:text/html,<html>' +
     '<body>' +
     '<menu type="context" id="menu1" label="firstmenu">' +
       '<menuitem label="foo" onclick="window.ctxCallbackFired(\'foo\')"></menuitem>' +
--- a/dom/browser-element/mochitest/browserElement_DataURI.js
+++ b/dom/browser-element/mochitest/browserElement_DataURI.js
@@ -3,17 +3,17 @@
 
 // Test that data: URIs work with mozbrowserlocationchange events.
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
   iframe1.id = 'iframe1';
   iframe1.addEventListener('mozbrowserloadend', function if1_loadend() {
     iframe1.removeEventListener('mozbrowserloadend', if1_loadend);
     ok(true, 'Got first loadend event.');
     SimpleTest.executeSoon(runTest2);
--- a/dom/browser-element/mochitest/browserElement_ErrorSecurity.js
+++ b/dom/browser-element/mochitest/browserElement_ErrorSecurity.js
@@ -4,17 +4,17 @@
 // Bug 764718 - Test that mozbrowsererror works for a security error.
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener("mozbrowsererror", function(e) {
     ok(true, "Got mozbrowsererror event.");
     ok(e.detail.type, "Event's detail has a |type| param.");
     SimpleTest.finish();
--- a/dom/browser-element/mochitest/browserElement_ForwardName.js
+++ b/dom/browser-element/mochitest/browserElement_ForwardName.js
@@ -5,17 +5,17 @@
 // forwarded down to remote mozbrowsers.
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
   iframe.setAttribute('name', 'foo');
 
   iframe.addEventListener("mozbrowseropenwindow", function(e) {
     ok(false, 'Got mozbrowseropenwindow, but should not have.');
   });
--- a/dom/browser-element/mochitest/browserElement_GetScreenshot.js
+++ b/dom/browser-element/mochitest/browserElement_GetScreenshot.js
@@ -4,17 +4,17 @@
 // Test the getScreenshot property for mozbrowser
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
 
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
   document.body.appendChild(iframe1);
   iframe1.src = 'data:text/html,<html>' +
     '<body style="background:green">hello</body></html>';
 
   var screenshots = [];
--- a/dom/browser-element/mochitest/browserElement_Iconchange.js
+++ b/dom/browser-element/mochitest/browserElement_Iconchange.js
@@ -11,17 +11,17 @@ function createHtml(link) {
 }
 
 function createLink(name) {
   return '<link rel="icon" type="image/png" href="http://example.com/' + name + '.png">';
 }
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
   document.body.appendChild(iframe1);
 
   // iframe2 is a red herring; we modify its favicon but don't listen for
   // iconchanges; we want to make sure that its iconchange events aren't
   // picked up by the listener on iframe1.
--- a/dom/browser-element/mochitest/browserElement_KeyEvents.js
+++ b/dom/browser-element/mochitest/browserElement_KeyEvents.js
@@ -14,17 +14,17 @@ let whitelistedEvents = [
   Ci.nsIDOMKeyEvent.DOM_VK_F5,       // Search button.
   Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP,  // Volume up.
   Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN // Volume down.
 ];
 
 SimpleTest.waitForExplicitFinish();
 
 browserElementTestHelpers.setEnabledPref(true);
-browserElementTestHelpers.addToWhitelist();
+browserElementTestHelpers.addPermission();
 browserElementTestHelpers.setOOPDisabledPref(true); // this is breaking the autofocus.
 
 var iframe = document.createElement('iframe');
 iframe.mozbrowser = true;
 iframe.src = browserElementTestHelpers.focusPage;
 document.body.appendChild(iframe);
 
 // Number of expected events at which point we will consider the test as done.
--- a/dom/browser-element/mochitest/browserElement_LoadEvents.js
+++ b/dom/browser-element/mochitest/browserElement_LoadEvents.js
@@ -4,17 +4,17 @@
 // Test that an iframe with the |mozbrowser| attribute emits mozbrowserloadX
 // events when this page is in the whitelist.
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   // Load emptypage1 into the iframe, wait for that to finish loading, then
   // call runTest2.
   //
   // This should trigger loadstart, locationchange, and loadend events.
 
   var seenLoadEnd = false;
   var seenLoadStart = false;
--- a/dom/browser-element/mochitest/browserElement_OpenNamed.js
+++ b/dom/browser-element/mochitest/browserElement_OpenNamed.js
@@ -6,17 +6,17 @@
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 var iframe;
 var popupFrame;
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   var gotPopup = false;
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     is(gotPopup, false, 'Should get just one popup.');
     gotPopup = true;
--- a/dom/browser-element/mochitest/browserElement_OpenWindow.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindow.js
@@ -3,17 +3,17 @@
 
 // Bug 742944 - Test that window.open works with <iframe mozbrowser>.
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   var gotPopup = false;
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     is(gotPopup, false, 'Should get just one popup.');
     gotPopup = true;
--- a/dom/browser-element/mochitest/browserElement_OpenWindowDifferentOrigin.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowDifferentOrigin.js
@@ -3,17 +3,17 @@
 
 // Bug 769182 - window.open to a different origin should load the page.
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     ok(true, 'Got first window.open call');
 
     e.detail.frameElement.addEventListener('mozbrowseropenwindow', function(e) {
--- a/dom/browser-element/mochitest/browserElement_OpenWindowInFrame.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowInFrame.js
@@ -9,17 +9,17 @@
 // mozbrowser.  OpenWindowInFrame loads file_browserElement_Open1.html inside
 // an iframe.
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   var gotPopup = false;
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     is(gotPopup, false, 'Should get just one popup.');
     gotPopup = true;
--- a/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowRejected.js
@@ -4,17 +4,17 @@
 // Bug 742944 - Do window.open from inside <iframe mozbrowser>.  But then
 // reject the call.  This shouldn't cause problems (crashes, leaks).
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     ok(e.detail.url.indexOf('does_not_exist.html') != -1,
        'Opened URL; got ' + e.detail.url);
     is(e.detail.name, '');
--- a/dom/browser-element/mochitest/browserElement_OpenWindowRejected2.js
+++ b/dom/browser-element/mochitest/browserElement_OpenWindowRejected2.js
@@ -8,17 +8,17 @@
 // adding the iframe element to our DOM, instead of by not calling
 // preventDefault() on the event.
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     ok(e.detail.url.indexOf('does_not_exist.html') != -1,
        'Opened URL; got ' + e.detail.url);
     is(e.detail.name, '');
--- a/dom/browser-element/mochitest/browserElement_PromptCheck.js
+++ b/dom/browser-element/mochitest/browserElement_PromptCheck.js
@@ -7,17 +7,17 @@
 //
 // At the moment, we treat alertCheck/promptCheck/confirmCheck just like a
 // normal alert.  But it's different to nsIPrompt!
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 browserElementTestHelpers.setEnabledPref(true);
-browserElementTestHelpers.addToWhitelist();
+browserElementTestHelpers.addPermission();
 
 // Test harness sets dom.successive_dialog_time_limit to 0 for some bizarre
 // reason.  That's not normal usage, and it keeps us from testing alertCheck!
 const dialogTimeLimitPrefName = 'dom.successive_dialog_time_limit';
 var oldDialogTimeLimitPref;
 try {
   oldDialogTimeLimitPref = SpecialPowers.getIntPref(dialogTimeLimitPrefName);
 }
--- a/dom/browser-element/mochitest/browserElement_PromptConfirm.js
+++ b/dom/browser-element/mochitest/browserElement_PromptConfirm.js
@@ -7,17 +7,17 @@
 // We use alert() to communicate the return values of prompt/confirm back to
 // ourselves.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
   document.body.appendChild(iframe);
 
   var prompts = [
     {msg: 1, type: 'alert', rv: 42, expected: 'undefined'},
     {msg: 2, type: 'confirm', rv: true, expected: 'true'},
--- a/dom/browser-element/mochitest/browserElement_Reload.js
+++ b/dom/browser-element/mochitest/browserElement_Reload.js
@@ -14,17 +14,17 @@ var iframeScript = function() {
 
 var mm;
 var iframe;
 var loadedEvents = 0;
 var countAcc;
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowserloadend', mozbrowserLoaded);
 
   iframe.src = 'file_bug741717.sjs';
   document.body.appendChild(iframe);
--- a/dom/browser-element/mochitest/browserElement_ScrollEvent.js
+++ b/dom/browser-element/mochitest/browserElement_ScrollEvent.js
@@ -3,17 +3,17 @@
 
 // Test that scroll event bubbles up.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
   document.body.appendChild(iframe);
 
   iframe.addEventListener("mozbrowserscroll", function(e) {
     ok(true, "got mozbrowserscroll event.");
     ok(e.detail, "event.detail is not null.");
--- a/dom/browser-element/mochitest/browserElement_SecurityChange.js
+++ b/dom/browser-element/mochitest/browserElement_SecurityChange.js
@@ -4,17 +4,17 @@
 // Bug 763694 - Test that <iframe mozbrowser> delivers proper
 // mozbrowsersecuritychange events.
 
 "use strict";
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   var lastSecurityState;
   iframe.addEventListener('mozbrowsersecuritychange', function(e) {
     lastSecurityState = e.detail;
   });
--- a/dom/browser-element/mochitest/browserElement_SendEvent.js
+++ b/dom/browser-element/mochitest/browserElement_SendEvent.js
@@ -3,17 +3,17 @@
 
 // Test that sendMouseEvent dispatch events.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement("iframe");
   iframe.mozbrowser = true;
   document.body.appendChild(iframe);
 
   iframe.addEventListener("mozbrowserloadend", function onloadend(e) {
     iframe.sendMouseEvent("mousedown", 10, 10, 0, 1, 0);
   });
--- a/dom/browser-element/mochitest/browserElement_SetVisible.js
+++ b/dom/browser-element/mochitest/browserElement_SetVisible.js
@@ -12,17 +12,17 @@ var iframeScript = function() {
       hidden: content.document.mozHidden
     });
   }, false);
 }
 
 function runTest() {
 
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var mm;
   var numEvents = 0;
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
   iframe1.src = 'data:text/html,1';
 
   document.body.appendChild(iframe1);
--- a/dom/browser-element/mochitest/browserElement_SetVisibleFrames.js
+++ b/dom/browser-element/mochitest/browserElement_SetVisibleFrames.js
@@ -11,17 +11,17 @@
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 var iframe;
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   // Our test involves three <iframe mozbrowser>'s, parent, child1, and child2.
   // child1 and child2 are contained inside parent.  child1 is visibile, and
   // child2 is not.
   //
--- a/dom/browser-element/mochitest/browserElement_SetVisibleFrames2.js
+++ b/dom/browser-element/mochitest/browserElement_SetVisibleFrames2.js
@@ -5,17 +5,17 @@
 // inside an invisible <iframe mozbrowser> doesn't trigger any events.
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   // We need remote = false here until bug 761935 is fixed; see
   // SetVisibleFrames.js for an explanation.
   iframe.remote = false;
 
--- a/dom/browser-element/mochitest/browserElement_Stop.js
+++ b/dom/browser-element/mochitest/browserElement_Stop.js
@@ -12,17 +12,17 @@
 SimpleTest.waitForExplicitFinish();
 
 var iframe;
 var stopped = false;
 var imgSrc = 'http://test/tests/dom/browser-element/mochitest/file_bug709759.sjs';
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowserloadend', loadend);
   iframe.src = 'data:text/html,<html>' +
     '<body><img src="' + imgSrc + '" /></body></html>';
 
--- a/dom/browser-element/mochitest/browserElement_TargetBlank.js
+++ b/dom/browser-element/mochitest/browserElement_TargetBlank.js
@@ -4,17 +4,17 @@
 // Bug 764718 - Test that clicking a link with _target=blank works.
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     is(e.detail.url, 'http://example.com/');
     SimpleTest.finish();
   });
--- a/dom/browser-element/mochitest/browserElement_TargetTop.js
+++ b/dom/browser-element/mochitest/browserElement_TargetTop.js
@@ -4,17 +4,17 @@
 // Bug 771273 - Check that window.open(url, '_top') works properly with <iframe
 // mozbrowser>.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   iframe.addEventListener('mozbrowseropenwindow', function(e) {
     ok(false, 'Not expecting an openwindow event.');
   });
 
--- a/dom/browser-element/mochitest/browserElement_Titlechange.js
+++ b/dom/browser-element/mochitest/browserElement_Titlechange.js
@@ -3,17 +3,17 @@
 
 // Test that the onmozbrowsertitlechange event works.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe1 = document.createElement('iframe');
   iframe1.mozbrowser = true;
   document.body.appendChild(iframe1);
 
   // iframe2 is a red herring; we modify its title but don't listen for
   // titlechanges; we want to make sure that its titlechange events aren't
   // picked up by the listener on iframe1.
--- a/dom/browser-element/mochitest/browserElement_TopBarrier.js
+++ b/dom/browser-element/mochitest/browserElement_TopBarrier.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the public domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that an <iframe mozbrowser> is a window.{top,parent,frameElement} barrier.
 "use strict";
 
 browserElementTestHelpers.setEnabledPref(true);
-browserElementTestHelpers.addToWhitelist();
+browserElementTestHelpers.addPermission();
 
 var iframe;
 function runTest() {
   iframe = document.createElement('iframe');
   iframe.addEventListener('mozbrowserloadend', function() {
     try {
       outerIframeLoaded();
     } catch(e) {
--- a/dom/browser-element/mochitest/browserElement_XFrameOptions.js
+++ b/dom/browser-element/mochitest/browserElement_XFrameOptions.js
@@ -4,17 +4,17 @@
 // Bug 770239 - Test that we can load pages with X-Frame-Options: Deny inside
 // <iframe mozbrowser>.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   // The page we load will fire an alert when it successfully loads.
   iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
     ok(true, "Got alert");
     SimpleTest.finish();
--- a/dom/browser-element/mochitest/browserElement_XFrameOptionsDeny.js
+++ b/dom/browser-element/mochitest/browserElement_XFrameOptionsDeny.js
@@ -6,17 +6,17 @@
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 var initialScreenshot;
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   // Our child will create two iframes, so make sure this iframe is big enough
   // to show both of them without scrolling, so taking a screenshot gets both
   // frames.
   iframe.height = '1000px';
--- a/dom/browser-element/mochitest/browserElement_XFrameOptionsSameOrigin.js
+++ b/dom/browser-element/mochitest/browserElement_XFrameOptionsSameOrigin.js
@@ -6,17 +6,17 @@
 // this page will be of a different origin.  The load should succeed.
 
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.addToWhitelist();
+  browserElementTestHelpers.addPermission();
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
 
   // The innermost page we load will fire an alert when it successfully loads.
   iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
     ok(true, "Got alert");
     SimpleTest.finish();
--- a/dom/browser-element/mochitest/createNewTest.py
+++ b/dom/browser-element/mochitest/createNewTest.py
@@ -33,17 +33,17 @@ js_template = textwrap.dedent("""\
 
     // Bug {bug} - FILL IN TEST DESCRIPTION
     "use strict";
 
     SimpleTest.waitForExplicitFinish();
 
     function runTest() {{
       browserElementTestHelpers.setEnabledPref(true);
-      browserElementTestHelpers.addToWhitelist();
+      browserElementTestHelpers.addPermission();
 
       var iframe = document.createElement('iframe');
       iframe.mozbrowser = true;
 
       // FILL IN TEST
 
       document.body.appendChild(iframe);
     }}
--- a/dom/browser-element/mochitest/test_browserElement_NoWhitelist.html
+++ b/dom/browser-element/mochitest/test_browserElement_NoWhitelist.html
@@ -19,17 +19,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 <script type="application/javascript;version=1.7">
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 
 function runTest() {
   browserElementTestHelpers.setEnabledPref(true);
-  browserElementTestHelpers.setWhitelistPref(' http://foobar.com');
+  browserElementTestHelpers.addPermissionForUrl('http://foobar.com');
 
   var iframe = document.createElement('iframe');
   iframe.mozbrowser = true;
   document.body.appendChild(iframe);
 
   iframe.addEventListener('mozbrowserloadstart', function() {
     ok(false, 'Should not send mozbrowserloadstart event.');
   });
--- a/dom/devicestorage/ipc/test_ipc.html
+++ b/dom/devicestorage/ipc/test_ipc.html
@@ -125,36 +125,27 @@
       href = href.substring(0, href.lastIndexOf('/'));
       href = href.substring(0, href.lastIndexOf('/'));
       iframe.src = href + "/test?consoleLevel=INFO";
 
       document.body.appendChild(iframe);
     }
 
     addEventListener("load", function() {
-      let whitelist;
-      try {
-        whitelist =
-          SpecialPowers.getCharPref("dom.mozBrowserFramesWhitelist") + ", ";
-      } catch (e) {
-        whitelist = "";
-      }
 
-      whitelist += window.location.protocol + "//" + window.location.host;
-
+      SpecialPowers.addPermission("browser", true, document);
       SpecialPowers.pushPrefEnv({
         "set": [
 
           ["device.storage.enabled", true],
           ["device.storage.testing", true],
           ["device.storage.prompt.testing", true],
 
           ["dom.ipc.browser_frames.oop_by_default", true],
           ["dom.mozBrowserFramesEnabled", true],
-          ["browser.pageThumbs.enabled", false],
-          ["dom.mozBrowserFramesWhitelist", whitelist]
+          ["browser.pageThumbs.enabled", false]
         ]
       }, runTests);
     });
 
   </script>
 </body>
 </html>
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -681,17 +681,19 @@ ContentParent::RecvReadPermissions(Infal
     // Ask for future changes
     mSendPermissionUpdates = true;
 #endif
 
     return true;
 }
 
 bool
-ContentParent::RecvSetClipboardText(const nsString& text, const PRInt32& whichClipboard)
+ContentParent::RecvSetClipboardText(const nsString& text,
+                                       const bool& isPrivateData,
+                                       const PRInt32& whichClipboard)
 {
     nsresult rv;
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     NS_ENSURE_SUCCESS(rv, true);
 
     nsCOMPtr<nsISupportsString> dataWrapper =
         do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, true);
@@ -700,16 +702,17 @@ ContentParent::RecvSetClipboardText(cons
     NS_ENSURE_SUCCESS(rv, true);
     
     nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
     NS_ENSURE_SUCCESS(rv, true);
     trans->Init(nullptr);
     
     // If our data flavor has already been added, this will fail. But we don't care
     trans->AddDataFlavor(kUnicodeMime);
+    trans->SetIsPrivateData(isPrivateData);
     
     nsCOMPtr<nsISupports> nsisupportsDataWrapper =
         do_QueryInterface(dataWrapper);
     
     rv = trans->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
                                 text.Length() * sizeof(PRUnichar));
     NS_ENSURE_SUCCESS(rv, true);
     
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -196,17 +196,17 @@ private:
     virtual PStorageParent* AllocPStorage(const StorageConstructData& aData);
     virtual bool DeallocPStorage(PStorageParent* aActor);
 
     virtual bool RecvReadPrefsArray(InfallibleTArray<PrefTuple> *retValue);
     virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue);
 
     virtual bool RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions);
 
-    virtual bool RecvSetClipboardText(const nsString& text, const PRInt32& whichClipboard);
+    virtual bool RecvSetClipboardText(const nsString& text, const bool& isPrivateData, const PRInt32& whichClipboard);
     virtual bool RecvGetClipboardText(const PRInt32& whichClipboard, nsString* text);
     virtual bool RecvEmptyClipboard();
     virtual bool RecvClipboardHasText(bool* hasText);
 
     virtual bool RecvGetSystemColors(const PRUint32& colorsCount, InfallibleTArray<PRUint32>* colors);
     virtual bool RecvGetIconForExtension(const nsCString& aFileExt, const PRUint32& aIconSize, InfallibleTArray<PRUint8>* bits);
     virtual bool RecvGetShowPasswordSetting(bool* showPassword);
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -274,17 +274,17 @@ parent:
                 PRUint32 lineNumber, PRUint32 colNumber, PRUint32 flags,
                 nsCString category); 
 
     // nsIPermissionManager messages
     sync ReadPermissions() returns (Permission[] permissions);
 
     // These clipboard methods are only really used on Android since
     // the clipboard is not available in the content process.
-    SetClipboardText(nsString text, PRInt32 whichClipboard);
+    SetClipboardText(nsString text, bool isPrivateData, PRInt32 whichClipboard);
     sync GetClipboardText(PRInt32 whichClipboard)
         returns (nsString text);
     EmptyClipboard();
     sync ClipboardHasText()
         returns (bool hasText);
 
     sync GetSystemColors(PRUint32 colorsCount)
         returns (PRUint32[] colors);
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -21,49 +21,54 @@ let kMaxPendingMessages;
 try {
   kMaxPendingMessages = Services.prefs.getIntPref("dom.messages.maxPendingMessages");
 } catch(e) {
   // getIntPref throws when the pref is not set.
   kMaxPendingMessages = 5;
 }
 
 function debug(aMsg) { 
-  //dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n"); 
+  //dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
 }
 
 // Implementation of the component used by internal users.
 
 function SystemMessageInternal() {
   // The set of pages registered by installed apps. We keep the
   // list of pending messages for each page here also.
   this._pages = [];
   Services.obs.addObserver(this, "xpcom-shutdown", false);
   ppmm.addMessageListener("SystemMessageManager:GetPending", this);
 }
 
 SystemMessageInternal.prototype = {
-  sendMessage: function sendMessage(aType, aMessage, aManifestURI) {
+  sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
     debug("Broadcasting " + aType + " " + JSON.stringify(aMessage));
     ppmm.sendAsyncMessage("SystemMessageManager:Message" , { type: aType,
                                                              msg: aMessage,
                                                              manifest: aManifestURI.spec });
 
     // Queue the message for pages that registered an handler for this type.
     this._pages.forEach(function sendMess_openPage(aPage) {
-      if (aPage.type != aType || aPage.manifest != aManifestURI.spec) {
+      if (aPage.type != aType ||
+          aPage.manifest != aManifestURI.spec ||
+          aPage.uri != aPageURI.spec) {
         return;
       }
 
       aPage.pending.push(aMessage);
       if (aPage.pending.length > kMaxPendingMessages) {
         aPage.pending.splice(0, 1);
       }
 
       // We don't need to send the full object to observers.
-      let page = { uri: aPage.uri, manifest: aPage.manifest };
+      let page = { uri: aPage.uri,
+                   manifest: aPage.manifest,
+                   type: aPage.type,
+                   target: aMessage.target };
       debug("Asking to open  " + JSON.stringify(page));
       Services.obs.notifyObservers(this, "system-messages-open-app", JSON.stringify(page));
     }.bind(this))
   },
 
   registerPage: function registerPage(aType, aPageURI, aManifestURI) {
     if (!aPageURI || !aManifestURI) {
       throw Cr.NS_ERROR_INVALID_ARG;
--- a/dom/messages/interfaces/nsISystemMessagesInternal.idl
+++ b/dom/messages/interfaces/nsISystemMessagesInternal.idl
@@ -3,26 +3,27 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
 interface nsIURI;
 
 // Implemented by the contract id @mozilla.org/system-message-internal;1
 
-[scriptable, uuid(fdc1ba03-5d8f-4de9-894a-333c7a136c5f)]
+[scriptable, uuid(3a50fd6b-0263-45c1-b738-a002052ad31b)]
 interface nsISystemMessagesInternal : nsISupports
 {
   /*
    * Allow any internal user to broadcast a message of a given type.
    * @param type        The type of the message to be sent.
    * @param message     The message payload.
+   * @param pageURI     The URI of the page that will be opened.
    * @param manifestURI The webapp's manifest URI.
    */
-  void sendMessage(in DOMString type, in jsval message, in nsIURI manifestURI);
+  void sendMessage(in DOMString type, in jsval message, in nsIURI pageURI, in nsIURI manifestURI);
 
   /*
    * Registration of a page that wants to be notified of a message type.
    * @param type          The message type.
    * @param pageURI       The URI of the page that will be opened.
    * @param manifestURI   The webapp's manifest URI.
    */
   void registerPage(in DOMString type, in nsIURI pageURI, in nsIURI manifestURI);
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2525,17 +2525,17 @@ NPError NP_CALLBACK
 
   if (!streamlistener->mStreamListenerPeer)
     return NPERR_GENERIC_ERROR;
 
   nsresult rv = streamlistener->mStreamListenerPeer->RequestRead((NPByteRange *)rangeList);
   if (NS_FAILED(rv))
     return NPERR_GENERIC_ERROR;
 
-  return NS_OK;
+  return NPERR_NO_ERROR;
 }
 
 // Deprecated, only stubbed out
 void* NP_CALLBACK /* OJI type: JRIEnv* */
 _getJavaEnv()
 {
   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
   return NULL;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -3352,17 +3352,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
     }
 
     nsWidgetInitData initData;
     initData.mWindowType = eWindowType_plugin;
     initData.mUnicode = false;
     initData.clipChildren = true;
     initData.clipSiblings = true;
     rv = mWidget->Create(parentWidget.get(), nullptr, nsIntRect(0,0,0,0),
-                         nullptr, nullptr, &initData);
+                         nullptr, &initData);
     if (NS_FAILED(rv)) {
       mWidget->Destroy();
       mWidget = nullptr;
       return rv;
     }
 
     mWidget->EnableDragDrop(true);
     mWidget->Show(false);
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -44,22 +44,17 @@ const RIL_IPC_MSG_NAMES = [
   "RIL:GetAvailableNetworks",
   "RIL:NetworkSelectionModeChanged",
   "RIL:SelectNetwork",
   "RIL:SelectNetworkAuto",
   "RIL:CallStateChanged",
   "RIL:VoicemailNotification",
   "RIL:VoicemailNumberChanged",
   "RIL:CallError",
-  "RIL:GetCardLock:Return:OK",
-  "RIL:GetCardLock:Return:KO",
-  "RIL:SetCardLock:Return:OK",
-  "RIL:SetCardLock:Return:KO",
-  "RIL:UnlockCardLock:Return:OK",
-  "RIL:UnlockCardLock:Return:KO",
+  "RIL:CardLockResult",
   "RIL:UssdReceived",
   "RIL:SendUssd:Return:OK",
   "RIL:SendUssd:Return:KO",
   "RIL:CancelUssd:Return:OK",
   "RIL:CancelUssd:Return:KO"
 ];
 
 const kVoiceChangedTopic     = "mobile-connection-voice-changed";
@@ -565,25 +560,22 @@ RILContentHelper.prototype = {
         break;
       case "RIL:VoicemailNotification":
         this.handleVoicemailNotification(msg.json);
         break;
       case "RIL:VoicemailNumberChanged":
         this.voicemailNumber = msg.json.number;
         this.voicemailDisplayName = msg.json.alphaId;
         break;
-      case "RIL:GetCardLock:Return:OK":
-      case "RIL:SetCardLock:Return:OK":
-      case "RIL:UnlockCardLock:Return:OK":
-        this.fireRequestSuccess(msg.json.requestId, msg.json);
-        break;
-      case "RIL:GetCardLock:Return:KO":
-      case "RIL:SetCardLock:Return:KO":
-      case "RIL:UnlockCardLock:Return:KO":
-        this.fireRequestError(msg.json.requestId, msg.json.errorMsg);
+      case "RIL:CardLockResult":
+        if (msg.json.success) {
+          this.fireRequestSuccess(msg.json.requestId, msg.json);
+        } else {
+          this.fireRequestError(msg.json.requestId, msg.json);
+        }
         break;
       case "RIL:UssdReceived":
         Services.obs.notifyObservers(null, kUssdReceivedTopic,
                                      msg.json.message);
         break;
       case "RIL:SendUssd:Return:OK":
       case "RIL:CancelUssd:Return:OK":
         request = this.takeRequest(msg.json.requestId);
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -393,24 +393,20 @@ RadioInterfaceLayer.prototype = {
         debug("nitzTime networkTime=" + message.networkTimeInSeconds +
               " timezone=" + message.networkTimeZoneInMinutes +
               " dst=" + message.dstFlag +
               " timestamp=" + message.localTimeStampInMS);
         break;
       case "iccinfochange":
         this.rilContext.icc = message;
         break;
-      case "iccgetcardlock":
-        this.handleICCGetCardLock(message);
-        break;
-      case "iccsetcardlock":
-        this.handleICCSetCardLock(message);
-        break;
-      case "iccunlockcardlock":
-        this.handleICCUnlockCardLock(message);
+      case "iccGetCardLock":
+      case "iccSetCardLock":
+      case "iccUnlockCardLock":
+        this.handleICCCardLockResult(message);
         break;
       case "icccontacts":
         if (!this._contactsCallbacks) {
           return;
         }
         let callback = this._contactsCallbacks[message.requestId];
         if (callback) {
           delete this._contactsCallbacks[message.requestId];
@@ -941,26 +937,18 @@ RadioInterfaceLayer.prototype = {
   /**
    * Handle data call list.
    */
   handleDataCallList: function handleDataCallList(message) {
     this._deliverDataCallCallback("receiveDataCallList",
                                   [message.datacalls, message.datacalls.length]);
   },
 
-  handleICCGetCardLock: function handleICCGetCardLock(message) {
-    ppmm.sendAsyncMessage("RIL:GetCardLock:Return:OK", message);
-  },
-
-  handleICCSetCardLock: function handleICCSetCardLock(message) {
-    ppmm.sendAsyncMessage("RIL:SetCardLock:Return:OK", message);
-  },
-
-  handleICCUnlockCardLock: function handleICCUnlockCardLock(message) {
-    ppmm.sendAsyncMessage("RIL:UnlockCardLock:Return:OK", message);
+  handleICCCardLockResult: function handleICCCardLockResult(message) {
+    ppmm.sendAsyncMessage("RIL:CardLockResult", message);
   },
 
   handleUSSDReceived: function handleUSSDReceived(ussd) {
     debug("handleUSSDReceived " + JSON.stringify(ussd));
     ppmm.sendAsyncMessage("RIL:UssdReceived", ussd);
   },
 
   handleSendUSSD: function handleSendUSSD(message) {
@@ -1635,77 +1623,27 @@ RadioInterfaceLayer.prototype = {
                              reason: reason});
   },
 
   getDataCallList: function getDataCallList() {
     this.worker.postMessage({rilMessageType: "getDataCallList"});
   },
 
   getCardLock: function getCardLock(message) {
-    // Currently only support pin.
-    switch (message.lockType) {
-      case "pin" :
-        message.rilMessageType = "getICCPinLock";
-        break;
-      default:
-        ppmm.sendAsyncMessage("RIL:GetCardLock:Return:KO",
-                              {errorMsg: "Unsupported Card Lock.",
-                               requestId: message.requestId});
-        return;
-    }
+    message.rilMessageType = "iccGetCardLock";
     this.worker.postMessage(message);
   },
 
   unlockCardLock: function unlockCardLock(message) {
-    switch (message.lockType) {
-      case "pin":
-        message.rilMessageType = "enterICCPIN";
-        break;
-      case "pin2":
-        message.rilMessageType = "enterICCPIN2";
-        break;
-      case "puk":
-        message.rilMessageType = "enterICCPUK";
-        break;
-      case "puk2":
-        message.rilMessageType = "enterICCPUK2";
-        break;
-      default:
-        ppmm.sendAsyncMessage("RIL:UnlockCardLock:Return:KO",
-                              {errorMsg: "Unsupported Card Lock.",
-                               requestId: message.requestId});
-        return;
-    }
+    message.rilMessageType = "iccUnlockCardLock";
     this.worker.postMessage(message);
   },
 
   setCardLock: function setCardLock(message) {
-    // Change pin.
-    if (message.newPin !== undefined) {
-      switch (message.lockType) {
-        case "pin":
-          message.rilMessageType = "changeICCPIN";
-          break;
-        case "pin2":
-          message.rilMessageType = "changeICCPIN2";
-          break;
-        default:
-          ppmm.sendAsyncMessage("RIL:SetCardLock:Return:KO",
-                                {errorMsg: "Unsupported Card Lock.",
-                                 requestId: message.requestId});
-          return;
-      }
-    } else { // Enable/Disable pin lock.
-      if (message.lockType != "pin") {
-          ppmm.sendAsyncMessage("RIL:SetCardLock:Return:KO",
-                                {errorMsg: "Unsupported Card Lock.",
-                                 requestId: message.requestId});
-      }
-      message.rilMessageType = "setICCPinLock";
-    }
+    message.rilMessageType = "iccSetCardLock";
     this.worker.postMessage(message);
   },
 
   _contactsCallbacks: null,
   getICCContacts: function getICCContacts(type, callback) {
     if (!this._contactsCallbacks) {
       this._contactsCallbacks = {};
     } 
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -226,23 +226,25 @@ const ERROR_SS_MODIFIED_TO_USSD = 24;
 const ERROR_SS_MODIFIED_TO_SS = 25;
 const ERROR_SUBSCRIPTION_NOT_SUPPORTED = 26;
 
 const GECKO_ERROR_SUCCESS = null;
 const GECKO_ERROR_RADIO_NOT_AVAILABLE = "RadioNotAvailable";
 const GECKO_ERROR_GENERIC_FAILURE = "GenericFailure";
 const GECKO_ERROR_REQUEST_NOT_SUPPORTED = "RequestNotSupported";
 const GECKO_ERROR_ILLEGAL_SIM_OR_ME = "IllegalSIMorME";
+const GECKO_ERROR_PASSWORD_INCORRECT = "IncorrectPassword";
 
 const RIL_ERROR_TO_GECKO_ERROR = {};
 RIL_ERROR_TO_GECKO_ERROR[ERROR_SUCCESS] = GECKO_ERROR_SUCCESS;
 RIL_ERROR_TO_GECKO_ERROR[ERROR_RADIO_NOT_AVAILABLE] = GECKO_ERROR_RADIO_NOT_AVAILABLE;
 RIL_ERROR_TO_GECKO_ERROR[ERROR_GENERIC_FAILURE] = GECKO_ERROR_GENERIC_FAILURE;
 RIL_ERROR_TO_GECKO_ERROR[ERROR_REQUEST_NOT_SUPPORTED] = GECKO_ERROR_REQUEST_NOT_SUPPORTED;
 RIL_ERROR_TO_GECKO_ERROR[ERROR_ILLEGAL_SIM_OR_ME] = GECKO_ERROR_ILLEGAL_SIM_OR_ME;
+RIL_ERROR_TO_GECKO_ERROR[ERROR_PASSWORD_INCORRECT] = GECKO_ERROR_PASSWORD_INCORRECT;
 
 // 3GPP 23.040 clause 9.2.3.6 TP-Message-Reference(TP-MR):
 // The number of times the MS automatically repeats the SMS-SUBMIT shall be in
 // the range 1 to 3 but the precise number is an implementation matter.
 const SMS_RETRY_MAX = 3;
 
 const RADIO_STATE_OFF = 0;
 const RADIO_STATE_UNAVAILABLE = 1;
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -728,16 +728,40 @@ let RIL = {
 
   /**
    * Retrieve the ICC's status.
    */
   getICCStatus: function getICCStatus() {
     Buf.simpleRequest(REQUEST_GET_SIM_STATUS);
   },
 
+   /**
+   * Helper function for unlocking ICC locks.
+   */
+  iccUnlockCardLock: function iccUnlockCardLock(options) {
+    switch (options.lockType) {
+      case "pin":
+        this.enterICCPIN(options);
+        break;
+      case "pin2":
+        this.enterICCPIN2(options);
+        break;
+      case "puk":
+        this.enterICCPUK(options);
+        break;
+      case "puk2":
+        this.enterICCPUK2(options);
+        break;
+      default:
+        options.errorMsg = "Unsupported Card Lock.";
+        options.success = false;
+        this.sendDOMMessage(options);
+    }
+  },
+
   /**
    * Enter a PIN to unlock the ICC.
    *
    * @param pin
    *        String containing the PIN.
    * @param [optional] aid
    *        AID value.
    */
@@ -764,16 +788,44 @@ let RIL = {
     Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 1 : 2);
     Buf.writeString(options.pin);
     if (!RILQUIRKS_V5_LEGACY) {
       Buf.writeString(options.aid ? options.aid : this.aid);
     }
     Buf.sendParcel();
   },
 
+   /**
+   * Helper function for changing ICC locks.
+   */
+  iccSetCardLock: function iccSetCardLock(options) {
+    if (options.newPin !== undefined) {
+      switch (options.lockType) {
+        case "pin":
+          this.changeICCPIN(options);
+          break;
+        case "pin2":
+          this.changeICCPIN2(options);
+          break;
+        default:
+          options.errorMsg = "Unsupported Card Lock.";
+          options.success = false;
+          this.sendDOMMessage(options);
+      }
+    } else { // Enable/Disable pin lock.
+      if (options.lockType != "pin") {
+        options.errorMsg = "Unsupported Card Lock.";
+        options.success = false;
+        this.sendDOMMessage(options);
+        return;
+      }
+      this.setICCPinLock(options);
+    }
+  },
+
   /**
    * Change the current ICC PIN number.
    *
    * @param pin
    *        String containing the old PIN value
    * @param newPin
    *        String containing the new PIN value
    * @param [optional] aid
@@ -848,27 +900,42 @@ let RIL = {
      Buf.writeString(options.newPin);
      if (!RILQUIRKS_V5_LEGACY) {
        Buf.writeString(options.aid ? options.aid : this.aid);
      }
      Buf.sendParcel();
    },
 
   /**
+   * Helper function for fetching the state of ICC locks.
+   */
+  iccGetCardLock: function iccGetCardLock(options) {
+    switch (options.lockType) {
+      case "pin":
+        this.getICCPinLock(options);
+        break;
+      default:
+        options.errorMsg = "Unsupported Card Lock.";
+        options.success = false;
+        this.sendDOMMessage(options);
+    }
+  },
+
+  /**
    * Get ICC Pin lock. A wrapper call to queryICCFacilityLock.
    *
    * @param requestId
    *        Request Id from RadioInterfaceLayer.
    */
   getICCPinLock: function getICCPinLock(options) {
     options.facility = ICC_CB_FACILITY_SIM;
     options.password = ""; // For query no need to provide pin.
     options.serviceClass = ICC_SERVICE_CLASS_VOICE |
                            ICC_SERVICE_CLASS_DATA  |
-                           ICC_SERVICE_CLASS_FAX,
+                           ICC_SERVICE_CLASS_FAX;
     this.queryICCFacilityLock(options);
   },
 
   /**
    * Query ICC facility lock.
    *
    * @param facility
    *        One of ICC_CB_FACILITY_*.
@@ -902,17 +969,17 @@ let RIL = {
    *        Request Id from RadioInterfaceLayer.
    */
   setICCPinLock: function setICCPinLock(options) {
     options.facility = ICC_CB_FACILITY_SIM;
     options.enabled = options.enabled;
     options.password = options.pin;
     options.serviceClass = ICC_SERVICE_CLASS_VOICE |
                            ICC_SERVICE_CLASS_DATA  |
-                           ICC_SERVICE_CLASS_FAX,
+                           ICC_SERVICE_CLASS_FAX;
     this.setICCFacilityLock(options);
   },
 
   /**
    * Set ICC facility lock.
    *
    * @param facility
    *        One of ICC_CB_FACILITY_*.
@@ -1966,16 +2033,28 @@ let RIL = {
     this.getSignalStrength();
     this.fetchICCRecords();
 
     this.cardState = newCardState;
     this.sendDOMMessage({rilMessageType: "cardstatechange",
                          cardState: this.cardState});
   },
 
+   /**
+   * Helper for processing responses of functions such as enterICC* and changeICC*.
+   */
+  _processEnterAndChangeICCResponses: function _processEnterAndChangeICCResponses(length, options) {
+    options.success = options.rilRequestError == 0;
+    if (!options.success) {
+      options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+    }
+    options.retryCount = length ? Buf.readUint32List()[0] : -1;
+    this.sendDOMMessage(options);
+  },
+
   /**
    * Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
    */
   _processICCIOGetResponse: function _processICCIOGetResponse(options) {
     let length = Buf.readUint32();
 
     // The format is from TS 51.011, clause 9.2.1
 
@@ -2832,56 +2911,32 @@ RIL[REQUEST_GET_SIM_STATUS] = function R
       Buf.readUint32();
     }
   }
 
   if (DEBUG) debug("iccStatus: " + JSON.stringify(iccStatus));
   this._processICCStatus(iccStatus);
 };
 RIL[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) {
-  this.sendDOMMessage({rilMessageType: "iccunlockcardlock",
-                       lockType: "pin",
-                       result: options.rilRequestError == 0 ? true : false,
-                       retryCount: length ? Buf.readUint32List()[0] : -1,
-                       requestId: options.requestId});
+  this._processEnterAndChangeICCResponses(length, options);
 };
 RIL[REQUEST_ENTER_SIM_PUK] = function REQUEST_ENTER_SIM_PUK(length, options) {
-  this.sendDOMMessage({rilMessageType: "iccunlockcardlock",
-                       lockType: "puk",
-                       result: options.rilRequestError == 0 ? true : false,
-                       retryCount: length ? Buf.readUint32List()[0] : -1,
-                       requestId: options.requestId});
+  this._processEnterAndChangeICCResponses(length, options);
 };
 RIL[REQUEST_ENTER_SIM_PIN2] = function REQUEST_ENTER_SIM_PIN2(length, options) {
-  this.sendDOMMessage({rilMessageType: "iccunlockcardlock",
-                       lockType: "pin2",
-                       result: options.rilRequestError == 0 ? true : false,
-                       retryCount: length ? Buf.readUint32List()[0] : -1,
-                       requestId: options.requestId});
+  this._processEnterAndChangeICCResponses(length, options);
 };
 RIL[REQUEST_ENTER_SIM_PUK2] = function REQUEST_ENTER_SIM_PUK(length, options) {
-  this.sendDOMMessage({rilMessageType: "iccunlockcardlock",
-                       lockType: "puk2",
-                       result: options.rilRequestError == 0 ? true : false,
-                       retryCount: length ? Buf.readUint32List()[0] : -1,
-                       requestId: options.requestId});
+  this._processEnterAndChangeICCResponses(length, options);
 };
 RIL[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN(length, options) {
-  this.sendDOMMessage({rilMessageType: "iccsetcardlock",
-                       lockType: "pin",
-                       result: options.rilRequestError == 0 ? true : false,
-                       retryCount: length ? Buf.readUint32List()[0] : -1,
-                       requestId: options.requestId});
+  this._processEnterAndChangeICCResponses(length, options);
 };
 RIL[REQUEST_CHANGE_SIM_PIN2] = function REQUEST_CHANGE_SIM_PIN2(length, options) {
-  this.sendDOMMessage({rilMessageType: "iccsetcardlock",
-                       lockType: "pin2",
-                       result: options.rilRequestError == 0 ? true : false,
-                       retryCount: length ? Buf.readUint32List()[0] : -1,
-                       requestId: options.requestId});
+  this._processEnterAndChangeICCResponses(length, options);
 };
 RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION] = null;
 RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let calls_length = 0;
@@ -3268,32 +3323,33 @@ RIL[REQUEST_DEACTIVATE_DATA_CALL] = func
 
   let datacall = this.currentDataCalls[options.cid];
   delete this.currentDataCalls[options.cid];
   datacall.state = GECKO_NETWORK_STATE_DISCONNECTED;
   datacall.rilMessageType = "datacallstatechange";
   this.sendDOMMessage(datacall);
 };
 RIL[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
-  if (options.rilRequestError) {
-    return;
+  options.success = options.rilRequestError == 0;
+  if (!options.success) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
-  let response = Buf.readUint32List()[0];
-  this.sendDOMMessage({rilMessageType: "iccgetcardlock",
-                       lockType: "pin",
-                       enabled: response == 0 ? false : true,
-                       requestId: options.requestId});
+  if (length) {
+    options.enabled = Buf.readUint32List()[0] == 0 ? false : true;
+  }
+  this.sendDOMMessage(options);
 };
 RIL[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, options) {
-  this.sendDOMMessage({rilMessageType: "iccsetcardlock",
-                       lockType: "pin",
-                       result: options.rilRequestError == 0 ? true : false,
-                       retryCount: length ? Buf.readUint32List()[0] : -1,
-                       requestId: options.requestId});
+  options.success = options.rilRequestError == 0;
+  if (!options.success) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+  }
+  options.retryCount = length ? Buf.readUint32List()[0] : -1;
+  this.sendDOMMessage(options);
 };
 RIL[REQUEST_CHANGE_BARRING_PASSWORD] = null;
 RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_NETWORK_SELECTION_MODE);
 
   if (options.rilRequestError) {
     options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendDOMMessage(options);
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -4680,18 +4680,17 @@ nsHTMLEditor::SetCSSBackgroundColor(cons
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
 
     // loop thru the ranges in the selection
     enumerator->First(); 
     nsCOMPtr<nsISupports> currentItem;
     nsAutoString bgcolor; bgcolor.AssignLiteral("bgcolor");
     nsCOMPtr<nsIDOMNode> cachedBlockParent = nullptr;
-    while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
-    {
+    while (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == enumerator->IsDone()) {
       res = enumerator->CurrentItem(getter_AddRefs(currentItem));
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
       
       nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
       
       // check for easy case: both range endpoints in same text node
       nsCOMPtr<nsIDOMNode> startNode, endNode;
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -139,17 +139,18 @@ nsHTMLEditor::SetInlineProperty(nsIAtom 
     // get selection range enumerator
     nsCOMPtr<nsIEnumerator> enumerator;
     res = selection->GetEnumerator(getter_AddRefs(enumerator));
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
 
     // loop thru the ranges in the selection
     nsCOMPtr<nsISupports> currentItem;
-    for (enumerator->First(); NS_ENUMERATOR_FALSE == enumerator->IsDone();
+    for (enumerator->First();
+         static_cast<nsresult>(NS_ENUMERATOR_FALSE) == enumerator->IsDone();
          enumerator->Next()) {
       res = enumerator->CurrentItem(getter_AddRefs(currentItem));
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
 
       nsCOMPtr<nsIDOMRange> range(do_QueryInterface(currentItem));
 
       // adjust range to include any ancestors whose children are entirely
@@ -1386,18 +1387,17 @@ nsresult nsHTMLEditor::RemoveInlinePrope
     nsCOMPtr<nsIEnumerator> enumerator;
     res = selection->GetEnumerator(getter_AddRefs(enumerator));
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
 
     // loop thru the ranges in the selection
     enumerator->First(); 
     nsCOMPtr<nsISupports> currentItem;
-    while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
-    {
+    while (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == enumerator->IsDone()) {
       res = enumerator->CurrentItem(getter_AddRefs(currentItem));
       NS_ENSURE_SUCCESS(res, res);
       NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
       
       nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
 
       if (aProperty == nsEditProperty::name)
       {
@@ -1574,18 +1574,17 @@ nsHTMLEditor::RelativeFontChange( PRInt3
   nsCOMPtr<nsIEnumerator> enumerator;
   nsresult res = selection->GetEnumerator(getter_AddRefs(enumerator));
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
 
   // loop thru the ranges in the selection
   enumerator->First(); 
   nsCOMPtr<nsISupports> currentItem;
-  while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
-  {
+  while (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == enumerator->IsDone()) {
     res = enumerator->CurrentItem(getter_AddRefs(currentItem));
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
     
     nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
 
     // adjust range to include any ancestors who's children are entirely selected
     res = PromoteInlineRange(range);
--- a/editor/txmgr/tests/TestTXMgr.cpp
+++ b/editor/txmgr/tests/TestTXMgr.cpp
@@ -4586,39 +4586,38 @@ main (int argc, char *argv[])
 
   nsresult result;
 
   //
   // quick_test() part:
   //
 
   result = simple_test();
-  NS_ENSURE_SUCCESS(result, result);
+  NS_ENSURE_SUCCESS(result, 1);
 
   result = aggregation_test();
-  NS_ENSURE_SUCCESS(result, result);
+  NS_ENSURE_SUCCESS(result, 1);
 
   //
   // quick_batch_test() part:
   //
 
   result = simple_batch_test();
-  NS_ENSURE_SUCCESS(result, result);
+  NS_ENSURE_SUCCESS(result, 1);
 
   result = aggregation_batch_test();
-  NS_ENSURE_SUCCESS(result, result);
+  NS_ENSURE_SUCCESS(result, 1);
 
   //
   // stress_test() part:
   //
 
   result = simple_stress_test();
-  NS_ENSURE_SUCCESS(result, result);
+  NS_ENSURE_SUCCESS(result, 1);
 
   result = aggregation_stress_test();
-  NS_ENSURE_SUCCESS(result, result);
+  NS_ENSURE_SUCCESS(result, 1);
 
   result = aggregation_batch_stress_test();
-  NS_ENSURE_SUCCESS(result, result);
-
-
-  return NS_OK;
+  NS_ENSURE_SUCCESS(result, 1);
+
+  return 0;
 }
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -87,17 +87,17 @@ nsWebBrowser::~nsWebBrowser()
 {
    InternalDestroy();
 }
 
 NS_IMETHODIMP nsWebBrowser::InternalDestroy()
 {
 
    if (mInternalWidget) {
-     mInternalWidget->SetClientData(0);
+     mInternalWidget->SetWidgetListener(nullptr);
      mInternalWidget->Destroy();
      mInternalWidget = nullptr; // Force release here.
    }
 
    SetDocShell(nullptr);
 
    if(mDocShellTreeOwner)
       {
@@ -882,18 +882,18 @@ NS_IMETHODIMP nsWebBrowser::GetCurrentSt
     if (mPersist)
     {
         mPersist->GetCurrentState(&mPersistCurrentState);
     }
     *aCurrentState = mPersistCurrentState;
     return NS_OK;
 }
 
-/* readonly attribute unsigned long result; */
-NS_IMETHODIMP nsWebBrowser::GetResult(PRUint32 *aResult)
+/* readonly attribute nsresult result; */
+NS_IMETHODIMP nsWebBrowser::GetResult(nsresult *aResult)
 {
     NS_ENSURE_ARG_POINTER(aResult);
     if (mPersist)
     {
         mPersist->GetResult(&mPersistResult);
     }
     *aResult = mPersistResult;
     return NS_OK;
@@ -1113,19 +1113,18 @@ NS_IMETHODIMP nsWebBrowser::Create()
       docShellParentWidget = mInternalWidget;
       nsWidgetInitData  widgetInit;
 
       widgetInit.clipChildren = true;
 
       widgetInit.mWindowType = eWindowType_child;
       nsIntRect bounds(mInitInfo->x, mInitInfo->y, mInitInfo->cx, mInitInfo->cy);
       
-      mInternalWidget->SetClientData(static_cast<nsWebBrowser *>(this));
-      mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, nsWebBrowser::HandleEvent,
-                              nullptr, &widgetInit);  
+      mInternalWidget->SetWidgetListener(this);
+      mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, nullptr, &widgetInit);
       }
 
     nsCOMPtr<nsIDocShell> docShell(do_CreateInstance("@mozilla.org/docshell;1", &rv));
     NS_ENSURE_SUCCESS(rv, rv);
     rv = SetDocShell(docShell);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // get the system default window background colour
@@ -1654,79 +1653,55 @@ static void DrawThebesLayer(ThebesLayer*
   nscolor* color = static_cast<nscolor*>(aCallbackData);
   aContext->NewPath();
   aContext->SetColor(gfxRGBA(*color));
   nsIntRect dirtyRect = aRegionToDraw.GetBounds();
   aContext->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
   aContext->Fill();  
 }
 
-/* static */
-nsEventStatus nsWebBrowser::HandleEvent(nsGUIEvent *aEvent)
+void nsWebBrowser::WindowRaised(nsIWidget* aWidget)
 {
-  nsWebBrowser  *browser = nullptr;
-  void          *data = nullptr;
-  nsIWidget     *widget = aEvent->widget;
-
-  if (!widget)
-    return nsEventStatus_eIgnore;
-
-  widget->GetClientData(data);
-  if (!data)
-    return nsEventStatus_eIgnore;
-
-  browser = static_cast<nsWebBrowser *>(data);
-
-  switch(aEvent->message) {
-
-  case NS_PAINT: {
-      LayerManager* layerManager = widget->GetLayerManager();
-      NS_ASSERTION(layerManager, "Must be in paint event");
+#if defined(DEBUG_smaug)
+  nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(mDocShell);
+  nsAutoString documentURI;
+  domDocument->GetDocumentURI(documentURI);
+  printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)browser,
+         NS_ConvertUTF16toUTF8(documentURI).get());
+#endif
+  Activate();
+}
 
-      layerManager->BeginTransaction();
-      nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer();
-      nsPaintEvent* paintEvent = static_cast<nsPaintEvent*>(aEvent);
-      nsIntRect dirtyRect = paintEvent->region.GetBounds();
-      if (root) {
-          root->SetVisibleRegion(dirtyRect);
-          layerManager->SetRoot(root);
-      }
-      layerManager->EndTransaction(DrawThebesLayer, &browser->mBackgroundColor);
-      return nsEventStatus_eConsumeDoDefault;
-    }
+void nsWebBrowser::WindowLowered(nsIWidget* aWidget)
+{
+#if defined(DEBUG_smaug)
+  nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(mDocShell);
+  nsAutoString documentURI;
+  domDocument->GetDocumentURI(documentURI);
+  printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)browser,
+         NS_ConvertUTF16toUTF8(documentURI).get());
+#endif
+  Deactivate();
+}
 
-  case NS_ACTIVATE: {
-#if defined(DEBUG_smaug)
-    nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell);
-    nsAutoString documentURI;
-    domDocument->GetDocumentURI(documentURI);
-    printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)browser,
-           NS_ConvertUTF16toUTF8(documentURI).get());
-#endif
-    browser->Activate();
-    break;
+bool nsWebBrowser::PaintWindow(nsIWidget* aWidget, bool isRequest, nsIntRegion aRegion, bool aWillSendDidPaint)
+{
+  LayerManager* layerManager = aWidget->GetLayerManager();
+  NS_ASSERTION(layerManager, "Must be in paint event");
+
+  layerManager->BeginTransaction();
+  nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer();
+  if (root) {
+    nsIntRect dirtyRect = aRegion.GetBounds();
+    root->SetVisibleRegion(dirtyRect);
+    layerManager->SetRoot(root);
   }
 
-  case NS_DEACTIVATE: {
-#if defined(DEBUG_smaug)
-    nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell);
-    nsAutoString documentURI;
-    domDocument->GetDocumentURI(documentURI);
-    printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)browser,
-           NS_ConvertUTF16toUTF8(documentURI).get());
-#endif
-    browser->Deactivate();
-    break;
-  }
-
-  default:
-    break;
-  }
-
-  return nsEventStatus_eIgnore;
+  layerManager->EndTransaction(DrawThebesLayer, &mBackgroundColor);
+  return true;
 }
 
 NS_IMETHODIMP nsWebBrowser::GetPrimaryContentWindow(nsIDOMWindow** aDOMWindow)
 {
   *aDOMWindow = 0;
 
   nsCOMPtr<nsIDocShellTreeItem> item;
   NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_FAILURE);
--- a/embedding/browser/webBrowser/nsWebBrowser.h
+++ b/embedding/browser/webBrowser/nsWebBrowser.h
@@ -31,16 +31,17 @@
 #include "nsIWebNavigation.h"
 #include "nsIWebBrowserSetup.h"
 #include "nsIWebBrowserPersist.h"
 #include "nsIWebBrowserFocus.h"
 #include "nsIWebBrowserStream.h"
 #include "nsIWindowWatcher.h"
 #include "nsIPrintSettings.h"
 #include "nsEmbedStream.h"
+#include "nsIWidgetListener.h"
 
 #include "nsTArray.h"
 #include "nsWeakPtr.h"
 
 class nsIContentViewerFile;
 
 class nsWebBrowserInitInfo
 {
@@ -79,16 +80,17 @@ class nsWebBrowser : public nsIWebBrowse
                      public nsIBaseWindow,
                      public nsIScrollable, 
                      public nsITextScroll, 
                      public nsIInterfaceRequestor,
                      public nsIWebBrowserPersist,
                      public nsIWebBrowserFocus,
                      public nsIWebProgressListener,
                      public nsIWebBrowserStream,
+                     public nsIWidgetListener,
                      public nsSupportsWeakReference
 {
 friend class nsDocShellTreeOwner;
 public:
     nsWebBrowser();
 
     NS_DECL_ISUPPORTS
 
@@ -114,17 +116,20 @@ protected:
     // XXXbz why are these NS_IMETHOD?  They're not interface methods!
     NS_IMETHOD SetDocShell(nsIDocShell* aDocShell);
     NS_IMETHOD EnsureDocShellTreeOwner();
     NS_IMETHOD GetPrimaryContentWindow(nsIDOMWindow **aDomWindow);
     NS_IMETHOD BindListener(nsISupports *aListener, const nsIID& aIID);
     NS_IMETHOD UnBindListener(nsISupports *aListener, const nsIID& aIID);
     NS_IMETHOD EnableGlobalHistory(bool aEnable);
 
-    static nsEventStatus HandleEvent(nsGUIEvent *aEvent);
+    // nsIWidgetListener
+    virtual void WindowRaised(nsIWidget* aWidget);
+    virtual void WindowLowered(nsIWidget* aWidget);
+    virtual bool PaintWindow(nsIWidget* aWidget, bool isRequest, nsIntRegion aRegion, bool aWillSendDidPaint);
 
 protected:
    nsDocShellTreeOwner*       mDocShellTreeOwner;
    nsCOMPtr<nsIDocShell>      mDocShell;
    nsCOMPtr<nsIInterfaceRequestor> mDocShellAsReq;
    nsCOMPtr<nsIBaseWindow>    mDocShellAsWin;
    nsCOMPtr<nsIDocShellTreeItem> mDocShellAsItem;
    nsCOMPtr<nsIWebNavigation> mDocShellAsNav;
@@ -144,17 +149,17 @@ protected:
    nsCOMPtr<nsIPrintSettings> mPrintSettings;
 
    // cached background color
    nscolor                       mBackgroundColor;
 
    // persistence object
    nsCOMPtr<nsIWebBrowserPersist> mPersist;
    PRUint32                       mPersistCurrentState;
-   PRUint32                       mPersistResult;
+   nsresult                       mPersistResult;
    PRUint32                       mPersistFlags;
 
    // stream
    nsEmbedStream                 *mStream;
    nsCOMPtr<nsISupports>          mStreamGuard;
 
    //Weak Reference interfaces...
    nsIWidget*                            mParentWidget;
--- a/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl
+++ b/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl
@@ -93,17 +93,17 @@ interface nsIWebBrowserPersist : nsICanc
   /**
    * Value indicating the success or failure of the persist
    * operation.
    *
    * @return NS_OK Operation was successful or is still ongoing.
    * @return NS_BINDING_ABORTED Operation cancelled.
    * @return NS_ERROR_FAILURE Non-specific failure.
    */
-  readonly attribute unsigned long result;
+  readonly attribute nsresult result;
 
   /**
    * Callback listener for progress notifications. The object that the
    * embbedder supplies may also implement nsIInterfaceRequestor and be
    * prepared to return nsIAuthPrompt or other interfaces that may be required
    * to download data.
    *
    * @see nsIAuthPrompt
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
@@ -298,17 +298,17 @@ NS_IMETHODIMP nsWebBrowserPersist::GetCu
     else
     {
         *aCurrentState = PERSIST_STATE_READY;
     }
     return NS_OK;
 }
 
 /* readonly attribute unsigned long result; */
-NS_IMETHODIMP nsWebBrowserPersist::GetResult(PRUint32 *aResult)
+NS_IMETHODIMP nsWebBrowserPersist::GetResult(nsresult *aResult)
 {
     NS_ENSURE_ARG_POINTER(aResult);
     *aResult = mPersistResult;
     return NS_OK;
 }
 
 /* attribute nsIWebBrowserPersistProgress progressListener; */
 NS_IMETHODIMP nsWebBrowserPersist::GetProgressListener(
@@ -987,18 +987,18 @@ NS_IMETHODIMP nsWebBrowserPersist::OnSta
         case NS_NET_STATUS_RESOLVED_HOST:
         case NS_NET_STATUS_BEGIN_FTP_TRANSACTION:
         case NS_NET_STATUS_END_FTP_TRANSACTION:
         case NS_NET_STATUS_CONNECTING_TO:
         case NS_NET_STATUS_CONNECTED_TO:
         case NS_NET_STATUS_SENDING_TO:
         case NS_NET_STATUS_RECEIVING_FROM:
         case NS_NET_STATUS_WAITING_FOR:
-        case nsITransport::STATUS_READING:
-        case nsITransport::STATUS_WRITING:
+        case NS_NET_STATUS_READING:
+        case NS_NET_STATUS_WRITING:
             break;
 
         default:
             // Pass other notifications (for legitimate errors) along.
             mProgressListener->OnStatusChange(nullptr, request, status, statusArg);
             break;
         }
 
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
@@ -198,17 +198,17 @@ private:
     bool                      mFirstAndOnlyUse;
     bool                      mCancel;
     bool                      mJustStartedLoading;
     bool                      mCompleted;
     bool                      mStartSaving;
     bool                      mReplaceExisting;
     bool                      mSerializingOutput;
     PRUint32                  mPersistFlags;
-    PRUint32                  mPersistResult;
+    nsresult                  mPersistResult;
     PRInt64                   mTotalCurrentProgress;
     PRInt64                   mTotalMaxProgress;
     PRInt16                   mWrapColumn;
     PRUint32                  mEncodingFlags;
     nsString                  mContentType;
 };
 
 // Helper class does node fixup during persistence
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -1170,17 +1170,17 @@ nsPermissionManager::Import()
     // Split the line at tabs
     ParseString(buffer, '\t', lineArray);
     
     if (lineArray[0].EqualsLiteral(kMatchTypeHost) &&
         lineArray.Length() == 4) {
       
       nsresult error;
       PRUint32 permission = lineArray[2].ToInteger(&error);
-      if (error)
+      if (NS_FAILED(error))
         continue;
 
       // hosts might be encoded in UTF8; switch them to ACE to be consistent
       if (!IsASCII(lineArray[3])) {
         rv = NormalizeToACE(lineArray[3]);
         if (NS_FAILED(rv))
           continue;
       }
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -999,16 +999,17 @@ ShadowThebesLayerOGL::Swap(const ThebesB
                            nsIntRegion* aNewBackValidRegion,
                            OptionalThebesBuffer* aReadOnlyFront,
                            nsIntRegion* aFrontUpdatedRegion)
 {
   if (mDestroyed) {
     // Don't drop buffers on the floor.
     *aNewBack = aNewFront;
     *aNewBackValidRegion = aNewFront.rect();
+    *aReadOnlyFront = null_t();
     return;
   }
 
   if (IsSurfaceDescriptorValid(mBufferDescriptor)) {
     AutoOpenSurface currentFront(OPEN_READ_ONLY, mBufferDescriptor);
     AutoOpenSurface newFront(OPEN_READ_ONLY, aNewFront.buffer());
     if (currentFront.Size() != newFront.Size()) {
       // The buffer changed size making the current front buffer
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -184,19 +184,19 @@ nsJPEGDecoder::WriteInternal(const char 
 {
   mSegment = (const JOCTET *)aBuffer;
   mSegmentLen = aCount;
 
   NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
   /* Return here if there is a fatal error within libjpeg. */
   nsresult error_code;
-  // XXX: This cast to nsresult makes absolutely no sense and is thoroughly
-  // broken (bug 778103).  I hope this code path is never hit.
-  if ((error_code = (nsresult)setjmp(mErr.setjmp_buffer)) != 0) {
+  // This cast to nsresult makes sense because setjmp() returns whatever we
+  // passed to longjmp(), which was actually an nsresult.
+  if ((error_code = (nsresult)setjmp(mErr.setjmp_buffer)) != NS_OK) {
     if (error_code == NS_ERROR_FAILURE) {
       PostDataError();
       /* Error due to corrupt stream - return NS_OK and consume silently
          so that libpr0n doesn't throw away a partial image load */
       mState = JPEG_SINK_NON_JPEG_TRAILER;
       PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
              ("} (setjmp returned NS_ERROR_FAILURE)"));
       return;
@@ -652,18 +652,19 @@ my_error_exit (j_common_ptr cinfo)
   char buffer[JMSG_LENGTH_MAX];
 
   /* Create the message */
   (*err->pub.format_message) (cinfo, buffer);
 
   fprintf(stderr, "JPEG decoding error:\n%s\n", buffer);
 #endif
 
-  /* Return control to the setjmp point. */
-  longjmp(err->setjmp_buffer, error_code);
+  /* Return control to the setjmp point.  We pass an nsresult masquerading as
+   * an int, which works because the setjmp() caller casts it back. */
+  longjmp(err->setjmp_buffer, static_cast<int>(error_code));
 }
 
 /******************************************************************************/
 /*-----------------------------------------------------------------------------
  * This is the callback routine from the IJG JPEG library used to supply new
  * data to the decompressor when its input buffer is exhausted.  It juggles
  * multiple buffers in an attempt to avoid unnecessary copying of input data.
  *
--- a/image/encoders/jpeg/nsJPEGEncoder.cpp
+++ b/image/encoders/jpeg/nsJPEGEncoder.cpp
@@ -411,19 +411,21 @@ nsJPEGEncoder::emptyOutputBuffer(jpeg_co
                                          that->mImageBufferSize);
   if (! newBuf) {
     // can't resize, just zero (this will keep us from writing more)
     PR_Free(that->mImageBuffer);
     that->mImageBuffer = nullptr;
     that->mImageBufferSize = 0;
     that->mImageBufferUsed = 0;
 
-    // this seems to be the only way to do errors through the JPEG library
+    // This seems to be the only way to do errors through the JPEG library.  We
+    // pass an nsresult masquerading as an int, which works because the
+    // setjmp() caller casts it back.
     longjmp(((encoder_error_mgr*)(cinfo->err))->setjmp_buffer,
-            NS_ERROR_OUT_OF_MEMORY);
+            static_cast<int>(NS_ERROR_OUT_OF_MEMORY));
   }
   that->mImageBuffer = newBuf;
 
   cinfo->dest->next_output_byte = &that->mImageBuffer[that->mImageBufferUsed];
   cinfo->dest->free_in_buffer = that->mImageBufferSize - that->mImageBufferUsed;
   return 1;
 }
 
@@ -463,18 +465,19 @@ nsJPEGEncoder::errorExit(jpeg_common_str
   switch (cinfo->err->msg_code) {
     case JERR_OUT_OF_MEMORY:
       error_code = NS_ERROR_OUT_OF_MEMORY;
       break;
     default:
       error_code = NS_ERROR_FAILURE;
   }
 
-  // Return control to the setjmp point.
-  longjmp(err->setjmp_buffer, error_code);
+  // Return control to the setjmp point.  We pass an nsresult masquerading as
+  // an int, which works because the setjmp() caller casts it back.
+  longjmp(err->setjmp_buffer, static_cast<int>(error_code));
 }
 
 void
 nsJPEGEncoder::NotifyListener()
 {
   // We might call this function on multiple threads (any threads that call
   // AsyncWait and any that do encoding) so we lock to avoid notifying the
   // listener twice about the same data (which generally leads to a truncated
--- a/intl/strres/src/nsStringBundle.cpp
+++ b/intl/strres/src/nsStringBundle.cpp
@@ -755,17 +755,18 @@ nsStringBundleService::FormatWithBundle(
   if (NS_FAILED(rv)) {
     PRUint16 code = NS_ERROR_GET_CODE(aStatus);
     rv = bundle->FormatStringFromID(code, (const PRUnichar**)argArray, argCount, result);
   }
 
   // If the int key fails, try looking up the default error message. E.g. print:
   //   An unknown error has occurred (0x804B0003).
   if (NS_FAILED(rv)) {
-    nsAutoString statusStr; statusStr.AppendInt(aStatus, 16);
+    nsAutoString statusStr;
+    statusStr.AppendInt(static_cast<PRUint32>(aStatus), 16);
     const PRUnichar* otherArgArray[1];
     otherArgArray[0] = statusStr.get();
     PRUint16 code = NS_ERROR_GET_CODE(NS_ERROR_FAILURE);
     rv = bundle->FormatStringFromID(code, otherArgArray, 1, result);
   }
 
   return rv;
 }
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4393,20 +4393,18 @@ fi # MOZ_X11
 fi # COMPILE_ENVIRONMENT
 
 dnl Set various defines and substitutions
 dnl ========================================================
 
 if test "$OS_ARCH" = "Darwin"; then
   AC_DEFINE(XP_MACOSX)
   AC_DEFINE(XP_UNIX)
-  AC_DEFINE(UNIX_ASYNC_DNS)
 elif test "$OS_ARCH" != "WINNT" -a "$OS_ARCH" != "OS2"; then
   AC_DEFINE(XP_UNIX)
-  AC_DEFINE(UNIX_ASYNC_DNS)
 fi
 
 AC_ARG_ENABLE(threadsafe,
     [  --enable-threadsafe     Enable support for multiple threads.],
     [if test "x$enableval" = "xyes"; then
         AC_DEFINE(JS_THREADSAFE)
     fi],)
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug774859.js
@@ -0,0 +1,16 @@
+gczeal(4,1);
+function g()
+{
+    try {
+	return [];
+    } catch (e) {}
+}
+function f()
+{
+    for (var i=0; i<2; i++) {
+	var o = {a: g(),
+		 a: g()};
+	print(i);
+    }
+}
+f();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug781393.js
@@ -0,0 +1,14 @@
+gczeal(4,1);
+function check(o)
+{
+    print(o);
+    assertEq(o.b, 3);
+}
+function f()
+{
+    for (var i=0; i<3; i++) {
+	var o = {b: 3};
+	check(o);
+    }
+}
+f();
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -112,17 +112,17 @@ MSG_DEF(JSMSG_BAD_REGEXP_FLAG,         5
 MSG_DEF(JSMSG_NO_INPUT,                59, 5, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}{3}{4}")
 MSG_DEF(JSMSG_CANT_OPEN,               60, 2, JSEXN_ERR, "can't open {0}: {1}")
 MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 61, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
 MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN,   62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
 MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE,       63, 0, JSEXN_INTERNALERR, "data are to big to encode")
 MSG_DEF(JSMSG_ARG_INDEX_OUT_OF_RANGE,  64, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range")
 MSG_DEF(JSMSG_SPREAD_TOO_LARGE,        65, 0, JSEXN_RANGEERR, "array too large due to spread operand(s)")
 MSG_DEF(JSMSG_SOURCE_TOO_LONG,         66, 0, JSEXN_RANGEERR, "source is too long")
-MSG_DEF(JSMSG_BAD_WEAKMAP_KEY,         67, 0, JSEXN_TYPEERR, "cannot use the given object as a weak map key")
+MSG_DEF(JSMSG_UNUSED67,                67, 0, JSEXN_NONE,    "")
 MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC,        68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
 MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL,     69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
 MSG_DEF(JSMSG_MISSING_FORMAL,          70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
 MSG_DEF(JSMSG_PAREN_AFTER_FORMAL,      71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
 MSG_DEF(JSMSG_CURLY_BEFORE_BODY,       72, 0, JSEXN_SYNTAXERR, "missing { before function body")
 MSG_DEF(JSMSG_CURLY_AFTER_BODY,        73, 0, JSEXN_SYNTAXERR, "missing } after function body")
 MSG_DEF(JSMSG_PAREN_BEFORE_COND,       74, 0, JSEXN_SYNTAXERR, "missing ( before condition")
 MSG_DEF(JSMSG_PAREN_AFTER_COND,        75, 0, JSEXN_SYNTAXERR, "missing ) after condition")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -7102,27 +7102,35 @@ JS_SetGCZeal(JSContext *cx, uint8_t zeal
                    " 11: Verify post write barriers between instructions\n"
                    " 12: Verify post write barriers between paints\n");
         }
         const char *p = strchr(env, ',');
         zeal = atoi(env);
         frequency = p ? atoi(p + 1) : JS_DEFAULT_ZEAL_FREQ;
     }
 
+    JSRuntime *rt = cx->runtime;
+
     if (zeal == 0) {
-        if (cx->runtime->gcVerifyPreData)
-            VerifyBarriers(cx->runtime, PreBarrierVerifier);
-        if (cx->runtime->gcVerifyPostData)
-            VerifyBarriers(cx->runtime, PostBarrierVerifier);
+        if (rt->gcVerifyPreData)
+            VerifyBarriers(rt, PreBarrierVerifier);
+        if (rt->gcVerifyPostData)
+            VerifyBarriers(rt, PostBarrierVerifier);
     }
 
     bool schedule = zeal >= js::gc::ZealAllocValue;
-    cx->runtime->gcZeal_ = zeal;
-    cx->runtime->gcZealFrequency = frequency;
-    cx->runtime->gcNextScheduled = schedule ? frequency : 0;
+    rt->gcZeal_ = zeal;
+    rt->gcZealFrequency = frequency;
+    rt->gcNextScheduled = schedule ? frequency : 0;
+
+#ifdef JS_METHODJIT
+    /* In case JSCompartment::compileBarriers() changed... */
+    for (CompartmentsIter c(rt); !c.done(); c.next())
+        mjit::ClearAllFrames(c);
+#endif
 }
 
 JS_PUBLIC_API(void)
 JS_ScheduleGC(JSContext *cx, uint32_t count)
 {
     cx->runtime->gcNextScheduled = count;
 }
 #endif
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -107,17 +107,19 @@ JSCompartment::init(JSContext *cx)
 
     return debuggees.init();
 }
 
 void
 JSCompartment::setNeedsBarrier(bool needs)
 {
 #ifdef JS_METHODJIT
-    if (needsBarrier_ != needs)
+    /* ClearAllFrames calls compileBarriers() and needs the old value. */
+    bool old = compileBarriers();
+    if (compileBarriers(needs) != old)
         mjit::ClearAllFrames(this);
 #endif
     needsBarrier_ = needs;
 }
 
 static bool
 WrapForSameCompartment(JSContext *cx, HandleObject obj, Value *vp)
 {
@@ -481,16 +483,25 @@ JSCompartment::discardJitCode(FreeOp *fo
         }
 
         types.sweepCompilerOutputs(fop);
     }
 
 #endif /* JS_METHODJIT */
 }
 
+bool
+JSCompartment::isDiscardingJitCode(JSTracer *trc)
+{
+    if (!IS_GC_MARKING_TRACER(trc))
+        return false;
+
+    return !gcPreserveCode;
+}
+
 void
 JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
 {
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_DISCARD_CODE);
         discardJitCode(fop);
     }
 
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -150,16 +150,24 @@ struct JSCompartment
   private:
     bool                         needsBarrier_;
   public:
 
     bool needsBarrier() const {
         return needsBarrier_;
     }
 
+    bool compileBarriers(bool needsBarrier) const {
+        return needsBarrier || rt->gcZeal() == js::gc::ZealVerifierPreValue;
+    }
+
+    bool compileBarriers() const {
+        return compileBarriers(needsBarrier());
+    }
+
     void setNeedsBarrier(bool needs);
 
     js::GCMarker *barrierTracer() {
         JS_ASSERT(needsBarrier_);
         return &rt->gcMarker;
     }
 
   private:
@@ -320,16 +328,17 @@ struct JSCompartment
     bool wrapId(JSContext *cx, jsid *idp);
     bool wrap(JSContext *cx, js::PropertyOp *op);
     bool wrap(JSContext *cx, js::StrictPropertyOp *op);
     bool wrap(JSContext *cx, js::PropertyDescriptor *desc);
     bool wrap(JSContext *cx, js::AutoIdVector &props);
 
     void markTypes(JSTracer *trc);
     void discardJitCode(js::FreeOp *fop);
+    bool isDiscardingJitCode(JSTracer *trc);
     void sweep(js::FreeOp *fop, bool releaseTypes);
     void sweepCrossCompartmentWrappers();
     void purge();
 
     void setGCLastBytes(size_t lastBytes, size_t lastMallocBytes, js::JSGCInvocationKind gckind);
     void reduceGCTriggerBytes(size_t amount);
 
     void resetGCMallocBytes();
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2054,16 +2054,21 @@ GCMarker::markDelayedChildren(ArenaHeade
                 JS_TraceChildren(this, t, MapAllocToTraceKind(aheader->getAllocKind()));
             }
         }
     } else {
         JS_ASSERT(aheader->allocatedDuringIncremental);
         PushArena(this, aheader);
     }
     aheader->allocatedDuringIncremental = 0;
+    /*
+     * Note that during an incremental GC we may still be allocating into
+     * aheader. However, prepareForIncrementalGC sets the
+     * allocatedDuringIncremental flag if we continue marking.
+     */
 }
 
 bool
 GCMarker::markDelayedChildren(SliceBudget &budget)
 {
     gcstats::AutoPhase ap(runtime->gcStats, gcstats::PHASE_MARK_DELAYED);
 
     JS_ASSERT(unmarkedArenaStackTop);
@@ -4892,17 +4897,17 @@ StartVerifyPreBarriers(JSRuntime *rt)
         node = NextNode(node);
     }
 
     rt->gcVerifyPreData = trc;
     rt->gcIncrementalState = MARK;
     rt->gcMarker.start(rt);
     for (CompartmentsIter c(rt); !c.done(); c.next()) {
         c->setNeedsBarrier(true);
-        c->arenas.prepareForIncrementalGC(rt);
+        c->arenas.purge();
     }
 
     return;
 
 oom:
     rt->gcIncrementalState = NO_INCREMENTAL;
     trc->~VerifyPreTracer();
     js_free(trc);
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -294,17 +294,17 @@ struct AutoEnterCompilation
         JS_ASSERT(info.outputIndex == RecompileInfo::NoCompilerRunning);
     }
 
     bool init(JSScript *script, bool constructing, unsigned chunkIndex)
     {
         CompilerOutput co;
         co.script = script;
         co.constructing = constructing;
-        co.barriers = cx->compartment->needsBarrier();
+        co.barriers = cx->compartment->compileBarriers();
         co.chunkIndex = chunkIndex;
 
         // This flag is used to prevent adding the current compiled script in
         // the list of compiler output which should be invalided.  This is
         // necessary because we can run some analysis might discard the script
         // it-self, which can happen when the monitored value does not reflect
         // the types propagated by the type inference.
         co.pendingRecompilation = true;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1322,22 +1322,22 @@ js::Interpret(JSContext *cx, StackFrame 
      */
 
 #else /* !JS_THREADED_INTERP */
     for (;;) {
       advance_pc_by_one:
         JS_ASSERT(js_CodeSpec[op].length == 1);
         len = 1;
       advance_pc:
+        js::gc::MaybeVerifyBarriers(cx);
         regs.pc += len;
         op = (JSOp) *regs.pc;
 
       do_op:
         CHECK_PCCOUNT_INTERRUPTS();
-        js::gc::MaybeVerifyBarriers(cx);
         switchOp = int(op) | switchMask;
       do_switch:
         switch (switchOp) {
 #endif
 
 #if JS_THREADED_INTERP
   interrupt:
 #else /* !JS_THREADED_INTERP */
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -244,30 +244,29 @@ WeakMap_set_impl(JSContext *cx, CallArgs
         if (!map->init()) {
             cx->delete_(map);
             JS_ReportOutOfMemory(cx);
             return false;
         }
         thisObj->setPrivate(map);
     }
 
-    // Preserve wrapped native keys to prevent wrapper optimization.
-    if (key->getClass()->ext.isWrappedNative) {
-        MOZ_ASSERT(cx->runtime->preserveWrapperCallback, "wrapped native weak map key needs preserveWrapperCallback");
-        if (!cx->runtime->preserveWrapperCallback(cx, key)) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_WEAKMAP_KEY);
-            return false;
-        }
-    }
-
     if (!map->put(key, value)) {
         JS_ReportOutOfMemory(cx);
         return false;
     }
 
+    // Preserve wrapped native keys to prevent wrapper optimization.
+    if (key->getClass()->ext.isWrappedNative) {
+        if (!cx->runtime->preserveWrapperCallback ||
+            !cx->runtime->preserveWrapperCallback(cx, key)) {
+            JS_ReportWarning(cx, "Failed to preserve wrapper of wrapped native weak map key.");
+        }
+    }
+
     args.rval().setUndefined();
     return true;
 }
 
 static JSBool
 WeakMap_set(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -110,17 +110,17 @@ CompileStatus
 mjit::Compiler::compile()
 {
     JS_ASSERT(!outerChunkRef().chunk);
 
     CompileStatus status = performCompilation();
     if (status != Compile_Okay && status != Compile_Retry) {
         if (!outerScript->ensureHasMJITInfo(cx))
             return Compile_Error;
-        JSScript::JITScriptHandle *jith = outerScript->jitHandle(isConstructing, cx->compartment->needsBarrier());
+        JSScript::JITScriptHandle *jith = outerScript->jitHandle(isConstructing, cx->compartment->compileBarriers());
         JSScript::ReleaseCode(cx->runtime->defaultFreeOp(), jith);
         jith->setUnjittable();
 
         if (outerScript->function()) {
             outerScript->uninlineable = true;
             types::MarkTypeObjectFlags(cx, outerScript->function(),
                                        types::OBJECT_FLAG_UNINLINEABLE);
         }
@@ -937,17 +937,17 @@ mjit::CanMethodJIT(JSContext *cx, JSScri
      * turned off, then we can't enter the jit because the epilogue of a pop
      * will not be emitted. Otherwise, we're safe with respect to balancing the
      * push/pops to the SPS sampling stack.
      */
     if (frame->hasPushedSPSFrame() && !cx->runtime->spsProfiler.enabled())
         return Compile_Skipped;
 
     if (script->hasMJITInfo()) {
-        JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->needsBarrier());
+        JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->compileBarriers());
         if (jith->isUnjittable())
             return Compile_Abort;
     }
 
     if (!cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS) &&
         (cx->typeInferenceEnabled()
          ? script->incUseCount() <= INFER_USES_BEFORE_COMPILE
          : script->incUseCount() <= USES_BEFORE_COMPILE))
@@ -962,25 +962,25 @@ mjit::CanMethodJIT(JSContext *cx, JSScri
     if (construct && !script->nslots)
         script->nslots++;
 
     uint64_t gcNumber = cx->runtime->gcNumber;
 
     if (!script->ensureHasMJITInfo(cx))
         return Compile_Error;
 
-    JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->needsBarrier());
+    JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->compileBarriers());
 
     JITScript *jit;
     if (jith->isEmpty()) {
         jit = MakeJITScript(cx, script);
         if (!jit)
             return Compile_Error;
 
-        // Script analysis can trigger GC, watch in case needsBarrier() changed.
+        // Script analysis can trigger GC, watch in case compileBarriers() changed.
         if (gcNumber != cx->runtime->gcNumber) {
             FreeOp *fop = cx->runtime->defaultFreeOp();
             jit->destroy(fop);
             fop->free_(jit);
             goto restart;
         }
 
         jith->setValid(jit);
@@ -5439,17 +5439,17 @@ mjit::Compiler::jsop_setprop(PropertyNam
             uint32_t slot = propertyTypes->definiteSlot();
             RegisterID reg = frame.tempRegForData(lhs);
             frame.pinReg(reg);
             bool isObject = lhs->isTypeKnown();
             MaybeJump notObject;
             if (!isObject)
                 notObject = frame.testObject(Assembler::NotEqual, lhs);
 #ifdef JSGC_INCREMENTAL_MJ
-            if (cx->compartment->needsBarrier() && propertyTypes->needsBarrier(cx)) {
+            if (cx->compartment->compileBarriers() && propertyTypes->needsBarrier(cx)) {
                 /* Write barrier. */
                 Jump j = masm.testGCThing(Address(reg, JSObject::getFixedSlotOffset(slot)));
                 stubcc.linkExit(j, Uses(0));
                 stubcc.leave();
                 stubcc.masm.addPtr(Imm32(JSObject::getFixedSlotOffset(slot)),
                                    reg, Registers::ArgReg1);
                 OOL_STUBCALL(stubs::GCThingWriteBarrier, REJOIN_NONE);
                 stubcc.rejoin(Changes(0));
@@ -5472,17 +5472,17 @@ mjit::Compiler::jsop_setprop(PropertyNam
         }
     }
 
     if (script->hasScriptCounts)
         bumpPropCount(PC, PCCounts::PROP_OTHER);
 
 #ifdef JSGC_INCREMENTAL_MJ
     /* Write barrier. We don't have type information for JSOP_SETNAME. */
-    if (cx->compartment->needsBarrier() &&
+    if (cx->compartment->compileBarriers() &&
         (!types || JSOp(*PC) == JSOP_SETNAME || types->propertyNeedsBarrier(cx, id)))
     {
         jsop_setprop_slow(name);
         return true;
     }
 #endif
 
     PICGenInfo pic(ic::PICInfo::SET, PC);
@@ -5840,17 +5840,17 @@ mjit::Compiler::jsop_aliasedArg(unsigned
     int32_t argsOff = ArgumentsData::offsetOfArgs() + arg * sizeof(Value);
     masm.addPtr(Imm32(argsOff), reg, reg);
     if (get) {
         FrameEntry *fe = frame.getArg(arg);
         JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;
         frame.push(Address(reg), type, true /* = reuseBase */);
     } else {
 #ifdef JSGC_INCREMENTAL_MJ
-        if (cx->compartment->needsBarrier()) {
+        if (cx->compartment->compileBarriers()) {
             /* Write barrier. */
             stubcc.linkExit(masm.testGCThing(Address(reg)), Uses(0));
             stubcc.leave();
             stubcc.masm.move(reg, Registers::ArgReg1);
             OOL_STUBCALL(stubs::GCThingWriteBarrier, REJOIN_NONE);
             stubcc.rejoin(Changes(0));
         }
 #endif
@@ -5883,17 +5883,17 @@ mjit::Compiler::jsop_aliasedVar(ScopeCoo
         frame.pushRegs(typeReg, dataReg, type);
         BarrierState barrier = testBarrier(typeReg, dataReg,
                                            /* testUndefined = */ false,
                                            /* testReturn */ false,
                                            /* force */ true);
         finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
     } else {
 #ifdef JSGC_INCREMENTAL_MJ
-        if (cx->compartment->needsBarrier()) {
+        if (cx->compartment->compileBarriers()) {
             /* Write barrier. */
             stubcc.linkExit(masm.testGCThing(addr), Uses(0));
             stubcc.leave();
             stubcc.masm.addPtr(Imm32(addr.offset), addr.base, Registers::ArgReg1);
             OOL_STUBCALL(stubs::GCThingWriteBarrier, REJOIN_NONE);
             stubcc.rejoin(Changes(0));
         }
 #endif
@@ -6030,17 +6030,17 @@ mjit::Compiler::iter(unsigned flags)
     Jump overlongChain = masm.branchPtr(Assembler::NonZero, T1, T1);
     stubcc.linkExit(overlongChain, Uses(1));
 
 #ifdef JSGC_INCREMENTAL_MJ
     /*
      * Write barrier for stores to the iterator. We only need to take a write
      * barrier if NativeIterator::obj is actually going to change.
      */
-    if (cx->compartment->needsBarrier()) {
+    if (cx->compartment->compileBarriers()) {
         Jump j = masm.branchPtr(Assembler::NotEqual,
                                 Address(nireg, offsetof(NativeIterator, obj)), reg);
         stubcc.linkExit(j, Uses(1));
     }
 #endif
 
     /* Found a match with the most recent iterator. Hooray! */
 
@@ -6413,17 +6413,17 @@ mjit::Compiler::jsop_setgname(PropertyNa
         if (shape && shape->hasDefaultSetter() &&
             shape->writable() && shape->hasSlot() &&
             !types->isOwnProperty(cx, globalObj->getType(cx), true)) {
             watchGlobalReallocation();
             HeapSlot *value = &globalObj->getSlotRef(shape->slot());
             RegisterID reg = frame.allocReg();
 #ifdef JSGC_INCREMENTAL_MJ
             /* Write barrier. */
-            if (cx->compartment->needsBarrier() && types->needsBarrier(cx)) {
+            if (cx->compartment->compileBarriers() && types->needsBarrier(cx)) {
                 stubcc.linkExit(masm.jump(), Uses(0));
                 stubcc.leave();
                 stubcc.masm.move(ImmPtr(value), Registers::ArgReg1);
                 OOL_STUBCALL(stubs::WriteBarrier, REJOIN_NONE);
                 stubcc.rejoin(Changes(0));
             }
 #endif
             masm.move(ImmPtr(value), reg);
@@ -6431,17 +6431,17 @@ mjit::Compiler::jsop_setgname(PropertyNa
             frame.shimmy(1);
             frame.freeReg(reg);
             return true;
         }
     }
 
 #ifdef JSGC_INCREMENTAL_MJ
     /* Write barrier. */
-    if (cx->compartment->needsBarrier()) {
+    if (cx->compartment->compileBarriers()) {
         jsop_setgname_slow(name);
         return true;
     }
 #endif
 
 #if defined JS_MONOIC
     FrameEntry *objFe = frame.peek(-2);
     FrameEntry *fe = frame.peek(-1);
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -481,17 +481,17 @@ private:
             return PC;
         ActiveFrame *scan = a;
         while (scan && scan->parent != outer)
             scan = static_cast<ActiveFrame *>(scan->parent);
         return scan->parentPC;
     }
 
     JITScript *outerJIT() {
-        return outerScript->getJIT(isConstructing, cx->compartment->needsBarrier());
+        return outerScript->getJIT(isConstructing, cx->compartment->compileBarriers());
     }
 
     ChunkDescriptor &outerChunkRef() {
         return outerJIT()->chunkDescriptor(chunkIndex);
     }
 
     bool bytecodeInChunk(jsbytecode *pc) {
         return (unsigned(pc - outerScript->code) >= outerChunk.begin)
--- a/js/src/methodjit/FastBuiltins.cpp
+++ b/js/src/methodjit/FastBuiltins.cpp
@@ -468,17 +468,17 @@ CompileStatus
 mjit::Compiler::compileArrayPopShift(FrameEntry *thisValue, bool isPacked, bool isArrayPop)
 {
     /* Filter out silly cases. */
     if (thisValue->isConstant())
         return Compile_InlineAbort;
 
 #ifdef JSGC_INCREMENTAL_MJ
     /* Write barrier. */
-    if (cx->compartment->needsBarrier())
+    if (cx->compartment->compileBarriers())
         return Compile_InlineAbort;
 #endif
 
     RegisterID objReg = frame.tempRegForData(thisValue);
     frame.pinReg(objReg);
 
     RegisterID lengthReg = frame.allocReg();
     RegisterID slotsReg = frame.allocReg();
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -1165,17 +1165,17 @@ mjit::Compiler::jsop_setelem_dense()
 #ifdef JSGC_INCREMENTAL_MJ
     /*
      * Write barrier.
      * We skip over the barrier if we incremented initializedLength above,
      * because in that case the slot we're overwriting was previously
      * undefined.
      */
     types::TypeSet *types = frame.extra(obj).types;
-    if (cx->compartment->needsBarrier() && (!types || types->propertyNeedsBarrier(cx, JSID_VOID))) {
+    if (cx->compartment->compileBarriers() && (!types || types->propertyNeedsBarrier(cx, JSID_VOID))) {
         Label barrierStart = stubcc.masm.label();
         stubcc.linkExitDirect(masm.jump(), barrierStart);
 
         /*
          * The sync call below can potentially clobber key.reg() and slotsReg.
          * We pin key.reg() to avoid it being clobbered. If |hoisted| is true,
          * we can also pin slotsReg. If not, then slotsReg is owned by the
          * compiler and we save in manually to VMFrame::scratch.
@@ -1571,17 +1571,17 @@ mjit::Compiler::jsop_setelem(bool popGua
 
     if (id->isType(JSVAL_TYPE_DOUBLE) || !globalObj) {
         jsop_setelem_slow();
         return true;
     }
 
 #ifdef JSGC_INCREMENTAL_MJ
     // Write barrier.
-    if (cx->compartment->needsBarrier()) {
+    if (cx->compartment->compileBarriers()) {
         jsop_setelem_slow();
         return true;
     }
 #endif
 
     SetElementICInfo ic;
 
     // One by one, check if the most important stack entries have registers,
@@ -2680,17 +2680,17 @@ void
 mjit::Compiler::jsop_initprop()
 {
     FrameEntry *obj = frame.peek(-2);
     FrameEntry *fe = frame.peek(-1);
     PropertyName *name = script->getName(GET_UINT32_INDEX(PC));
 
     RootedObject baseobj(cx, frame.extra(obj).initObject);
 
-    if (!baseobj || monitored(PC)) {
+    if (!baseobj || monitored(PC) || cx->compartment->compileBarriers()) {
         prepareStubCall(Uses(2));
         masm.move(ImmPtr(name), Registers::ArgReg1);
         INLINE_STUBCALL(stubs::InitProp, REJOIN_FALLTHROUGH);
         return;
     }
 
     RootedObject holder(cx);
     RootedShape shape(cx);
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -294,17 +294,17 @@ UncachedInlineCall(VMFrame &f, InitialFr
     /* Finish the handoff to the new frame regs. */
     PreserveRegsGuard regsGuard(cx, regs);
 
     /*
      * If newscript was successfully compiled, run it. Skip for calls which
      * will be constructing a new type object for 'this'.
      */
     if (!newType) {
-        if (JITScript *jit = newscript->getJIT(regs.fp()->isConstructing(), cx->compartment->needsBarrier())) {
+        if (JITScript *jit = newscript->getJIT(regs.fp()->isConstructing(), cx->compartment->compileBarriers())) {
             if (jit->invokeEntry) {
                 *pret = jit->invokeEntry;
 
                 /* Restore the old fp around and let the JIT code repush the new fp. */
                 regs.popFrame((Value *) regs.fp());
                 return true;
             }
         }
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -1074,17 +1074,17 @@ CheckStackAndEnterMethodJIT(JSContext *c
     return EnterMethodJIT(cx, fp, code, stackLimit, partial);
 }
 
 JaegerStatus
 mjit::JaegerShot(JSContext *cx, bool partial)
 {
     StackFrame *fp = cx->fp();
     JSScript *script = fp->script();
-    JITScript *jit = script->getJIT(fp->isConstructing(), cx->compartment->needsBarrier());
+    JITScript *jit = script->getJIT(fp->isConstructing(), cx->compartment->compileBarriers());
 
     JS_ASSERT(cx->regs().pc == script->code);
 
     return CheckStackAndEnterMethodJIT(cx, cx->fp(), jit->invokeEntry, partial);
 }
 
 JaegerStatus
 js::mjit::JaegerShotAtSafePoint(JSContext *cx, void *safePoint, bool partial)
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -997,17 +997,17 @@ VMFrame::pc()
     return regs.pc;
 }
 
 } /* namespace js */
 
 inline void *
 JSScript::nativeCodeForPC(bool constructing, jsbytecode *pc)
 {
-    js::mjit::JITScript *jit = getJIT(constructing, compartment()->needsBarrier());
+    js::mjit::JITScript *jit = getJIT(constructing, compartment()->compileBarriers());
     if (!jit)
         return NULL;
     js::mjit::JITChunk *chunk = jit->chunk(pc);
     if (!chunk)
         return NULL;
     return bsearch_nmap(chunk->nmap(), chunk->nNmapPairs, (size_t)(pc - code));
 }
 
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -575,17 +575,17 @@ class CallCompiler : public BaseCompiler
 
         // Test that:
         // - script->mJITInfo is not NULL
         // - script->mJITInfo->jitHandle{Ctor,Normal}->value is neither NULL nor UNJITTABLE, and
         // - script->mJITInfo->jitHandle{Ctor,Normal}->value->arityCheckEntry is not NULL.
         masm.loadPtr(Address(t0, JSScript::offsetOfMJITInfo()), t0);
         Jump hasNoJitInfo = masm.branchPtr(Assembler::Equal, t0, ImmPtr(NULL));
         size_t offset = JSScript::JITScriptSet::jitHandleOffset(callingNew,
-                                                                f.cx->compartment->needsBarrier());
+                                                                f.cx->compartment->compileBarriers());
         masm.loadPtr(Address(t0, offset), t0);
         Jump hasNoJitCode = masm.branchPtr(Assembler::BelowOrEqual, t0,
                                            ImmPtr(JSScript::JITScriptHandle::UNJITTABLE));
 
         masm.loadPtr(Address(t0, offsetof(JITScript, arityCheckEntry)), t0);
 
         Jump hasCode = masm.branchPtr(Assembler::NotEqual, t0, ImmPtr(0));
 
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1707,18 +1707,27 @@ stubs::ConvertToTypedFloat(JSContext *cx
         JS_ASSERT(success);
         vp->setDouble(d);
     }
 }
 
 void JS_FASTCALL
 stubs::WriteBarrier(VMFrame &f, Value *addr)
 {
+#ifdef JS_GC_ZEAL
+    if (!f.cx->compartment->needsBarrier())
+        return;
+#endif
     gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), addr, "write barrier");
 }
 
 void JS_FASTCALL
 stubs::GCThingWriteBarrier(VMFrame &f, Value *addr)
 {
+#ifdef JS_GC_ZEAL
+    if (!f.cx->compartment->needsBarrier())
+        return;
+#endif
+
     gc::Cell *cell = (gc::Cell *)addr->toGCThing();
     if (cell && !cell->isMarked())
         gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), addr, "write barrier");
 }
--- a/js/src/tests/lib/progressbar.py
+++ b/js/src/tests/lib/progressbar.py
@@ -1,23 +1,24 @@
 # Text progress bar library, like curl or scp.
 
 import sys
-from datetime import datetime
+from datetime import datetime, timedelta
 
 if sys.platform.startswith('win'):
     from lib.terminal_win import Terminal
 else:
     from lib.terminal_unix import Terminal
 
 class NullProgressBar(object):
     def update(self, current, data): pass
     def poke(self): pass
     def finish(self, complete=True): pass
     def message(self, msg): sys.stdout.write(msg + '\n')
+    def update_granularity(self): return timedelta.max
 
 class ProgressBar(object):
     def __init__(self, limit, fmt):
         assert not self.conservative_isatty()
         assert limit < 9999
 
         self.prior = None
         self.counters_fmt = fmt # [{str:str}] Describtion of how to lay out each
@@ -28,16 +29,19 @@ class ProgressBar(object):
         # Compute the width of the counters and build the format string.
         self.counters_width = 1 # [
         for layout in self.counters_fmt:
             self.counters_width += 4 # Less than 9999 tests total.
             self.counters_width += 1 # | (or ']' for the last one)
 
         self.barlen = 64 - self.counters_width
 
+    def update_granularity(self):
+        return timedelta(seconds=0.1)
+
     def update(self, current, data):
         # Record prior for poke.
         self.prior = (current, data)
 
         # Build counters string.
         sys.stdout.write('\r[')
         for layout in self.counters_fmt:
             Terminal.set_color(layout['color'])
--- a/js/src/tests/lib/tasks_unix.py
+++ b/js/src/tests/lib/tasks_unix.py
@@ -1,18 +1,16 @@
 # A unix-oriented process dispatcher.  Uses a single thread with select and
 # waitpid to dispatch tasks.  This avoids several deadlocks that are possible
 # with fork/exec + threads + Python.
 
 import errno, os, sys, select
 from datetime import datetime, timedelta
 from results import TestOutput
 
-PROGRESS_BAR_GRANULARITY = 0.1 #sec
-
 class Task(object):
     def __init__(self, test, pid, stdout, stderr):
         self.test = test
         self.cmd = test.get_command(test.js_cmd_prefix)
         self.pid = pid
         self.stdout = stdout
         self.stderr = stderr
         self.start = datetime.now()
@@ -38,40 +36,41 @@ def spawn_test(test):
 
     os.dup2(wout, 1)
     os.dup2(werr, 2)
 
     cmd = test.get_command(test.js_cmd_prefix)
     os.execvp(cmd[0], cmd)
 
 def total_seconds(td):
-    return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
+    """
+    Return the total number of seconds contained in the duration as a float
+    """
+    return (float(td.microseconds) + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
 
 def get_max_wait(tasks, results, timeout):
     """
     Return the maximum time we can wait before any task should time out.
     """
-    now = datetime.now()
-    wait = timedelta(0)
-    for task in tasks:
-        remaining = timedelta(seconds=timeout) - (now - task.start)
-        if remaining > wait:
-            wait = remaining
-    wait = total_seconds(wait)
-
-    # The test harness uses a timeout of 0 to indicate we should wait forever,
-    # but for select(), a timeout of 0 indicates a zero-length wait.  Instead,
-    # translate the timeout into None to tell select to wait forever.
-    if wait == 0:
-        return None
 
     # If we have a progress-meter, we need to wake up to update it frequently.
-    wait = min(wait, PROGRESS_BAR_GRANULARITY)
+    wait = results.pb.update_granularity()
 
-    return wait
+    # If a timeout is supplied, we need to wake up for the first task to
+    # timeout if that is sooner.
+    if timeout:
+        now = datetime.now()
+        timeout_delta = timedelta(seconds=timeout)
+        for task in tasks:
+            remaining = task.start + timeout_delta - now
+            if remaining < wait:
+                wait = remaining
+
+    # Return the wait time in seconds, clamped to zero.
+    return max(total_seconds(wait), 0)
 
 def flush_input(fd, frags):
     """
     Read any pages sitting in the file descriptor 'fd' into the list 'frags'.
     """
     rv = os.read(fd, 4096)
     frags.append(rv)
     while len(rv) == 4096:
@@ -195,9 +194,8 @@ def run_all_tests(tests, results, option
         read_input(tasks, timeout)
 
         kill_undead(tasks, results, options.timeout)
         tasks = reap_zombies(tasks, results, options.timeout)
 
         results.pb.poke()
 
     return True
-
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -69,17 +69,17 @@ StackFrame::compartment() const
     return scopeChain()->compartment();
 }
 
 #ifdef JS_METHODJIT
 inline mjit::JITScript *
 StackFrame::jit()
 {
     JSScript *script_ = script();
-    return script_->getJIT(isConstructing(), script_->compartment()->needsBarrier());
+    return script_->getJIT(isConstructing(), script_->compartment()->compileBarriers());
 }
 #endif
 
 inline void
 StackFrame::initPrev(JSContext *cx)
 {
     JS_ASSERT(flags_ & HAS_PREVPC);
     if (FrameRegs *regs = cx->maybeRegs()) {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -180,17 +180,17 @@ StackFrame::maybeSuspendedGenerator(JSRu
 }
 
 jsbytecode *
 StackFrame::prevpcSlow(InlinedSite **pinlined)
 {
     JS_ASSERT(!(flags_ & HAS_PREVPC));
 #if defined(JS_METHODJIT) && defined(JS_MONOIC)
     StackFrame *p = prev();
-    mjit::JITScript *jit = p->script()->getJIT(p->isConstructing(), p->compartment()->needsBarrier());
+    mjit::JITScript *jit = p->script()->getJIT(p->isConstructing(), p->compartment()->compileBarriers());
     prevpc_ = jit->nativeToPC(ncode_, &prevInline_);
     flags_ |= HAS_PREVPC;
     if (pinlined)
         *pinlined = prevInline_;
     return prevpc_;
 #else
     JS_NOT_REACHED("Unknown PC for frame");
     return NULL;
@@ -643,45 +643,50 @@ StackSpace::markFrameValues(JSTracer *tr
      */
     analyze::AutoEnterAnalysis aea(script->compartment());
     analyze::ScriptAnalysis *analysis = script->analysis();
     uint32_t offset = pc - script->code;
     Value *fixedEnd = slotsBegin + script->nfixed;
     for (Value *vp = slotsBegin; vp < fixedEnd; vp++) {
         uint32_t slot = analyze::LocalSlot(script, vp - slotsBegin);
 
-        /*
-         * Will this slot be synced by the JIT? If not, replace with a dummy
-         * value with the same type tag.
-         */
+        /* Will this slot be synced by the JIT? */
         if (!analysis->trackSlot(slot) || analysis->liveness(slot).live(offset)) {
             gc::MarkValueRoot(trc, vp, "vm_stack");
-        } else if (vp->isDouble()) {
-            *vp = DoubleValue(0.0);
-        } else {
+        } else if (script->compartment()->isDiscardingJitCode(trc)) {
             /*
-             * It's possible that *vp may not be a valid Value. For example, it
-             * may be tagged as a NullValue but the low bits may be nonzero so
-             * that isNull() returns false. This can cause problems later on
-             * when marking the value. Extracting the type in this way and then
-             * overwriting the value circumvents the problem.
+             * If we're throwing away analysis information, we need to replace
+             * non-live Values with ones that can safely be marked in later
+             * collections.
              */
-            JSValueType type = vp->extractNonDoubleType();
-            if (type == JSVAL_TYPE_INT32)
-                *vp = Int32Value(0);
-            else if (type == JSVAL_TYPE_UNDEFINED)
-                *vp = UndefinedValue();
-            else if (type == JSVAL_TYPE_BOOLEAN)
-                *vp = BooleanValue(false);
-            else if (type == JSVAL_TYPE_STRING)
-                *vp = StringValue(trc->runtime->atomState.nullAtom);
-            else if (type == JSVAL_TYPE_NULL)
-                *vp = NullValue();
-            else if (type == JSVAL_TYPE_OBJECT)
-                *vp = ObjectValue(fp->scopeChain()->global());
+            if (vp->isDouble()) {
+                *vp = DoubleValue(0.0);
+            } else {
+                /*
+                 * It's possible that *vp may not be a valid Value. For example,
+                 * it may be tagged as a NullValue but the low bits may be
+                 * nonzero so that isNull() returns false. This can cause
+                 * problems later on when marking the value. Extracting the type
+                 * in this way and then overwriting the value circumvents the
+                 * problem.
+                 */
+                JSValueType type = vp->extractNonDoubleType();
+                if (type == JSVAL_TYPE_INT32)
+                    *vp = Int32Value(0);
+                else if (type == JSVAL_TYPE_UNDEFINED)
+                    *vp = UndefinedValue();
+                else if (type == JSVAL_TYPE_BOOLEAN)
+                    *vp = BooleanValue(false);
+                else if (type == JSVAL_TYPE_STRING)
+                    *vp = StringValue(trc->runtime->atomState.nullAtom);
+                else if (type == JSVAL_TYPE_NULL)
+                    *vp = NullValue();
+                else if (type == JSVAL_TYPE_OBJECT)
+                    *vp = ObjectValue(fp->scopeChain()->global());
+            }
         }
     }
 
     gc::MarkValueRootRange(trc, fixedEnd, slotsEnd, "vm_stack");
 }
 
 void
 StackSpace::mark(JSTracer *trc)
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -267,17 +267,17 @@ nsXPCComponents_Interfaces::NewEnumerate
         }
         case JSENUMERATE_NEXT:
         {
             nsCOMPtr<nsISupports> isup;
 
             e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
 
             while (1) {
-                if (NS_ENUMERATOR_FALSE == e->IsDone() &&
+                if (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == e->IsDone() &&
                     NS_SUCCEEDED(e->CurrentItem(getter_AddRefs(isup))) && isup) {
                     e->Next();
                     nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(isup));
                     if (iface) {
                         JSString* idstr;
                         const char* name;
                         bool scriptable;
 
@@ -568,17 +568,17 @@ nsXPCComponents_InterfacesByID::NewEnume
         }
         case JSENUMERATE_NEXT:
         {
             nsCOMPtr<nsISupports> isup;
 
             e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
 
             while (1) {
-                if (NS_ENUMERATOR_FALSE == e->IsDone() &&
+                if (static_cast<nsresult>(NS_ENUMERATOR_FALSE) == e->IsDone() &&
                     NS_SUCCEEDED(e->CurrentItem(getter_AddRefs(isup))) && isup) {
                     e->Next();
                     nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(isup));
                     if (iface) {
                         nsIID const *iid;
                         char idstr[NSID_LENGTH];
                         JSString* jsstr;
                         bool scriptable;
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -658,16 +658,34 @@ XPCJSRuntime::ReleaseIncrementally(nsTAr
     mReleaseRunnable = new XPCIncrementalReleaseRunnable(this, array);
 
     nsresult rv = NS_DispatchToMainThread(mReleaseRunnable);
     if (NS_FAILED(rv))
         mReleaseRunnable->ReleaseNow(false);
 }
 
 /* static */ void
+XPCJSRuntime::GCSliceCallback(JSRuntime *rt,
+                              js::GCProgress progress,
+                              const js::GCDescription &desc)
+{
+    XPCJSRuntime *self = nsXPConnect::GetRuntimeInstance();
+    if (!self)
+        return;
+
+#ifdef MOZ_CRASHREPORTER
+    CrashReporter::SetGarbageCollecting(progress == js::GC_CYCLE_BEGIN ||
+                                        progress == js::GC_SLICE_BEGIN);
+#endif
+
+    if (self->mPrevGCSliceCallback)
+        (*self->mPrevGCSliceCallback)(rt, progress, desc);
+}
+
+/* static */ void
 XPCJSRuntime::GCCallback(JSRuntime *rt, JSGCStatus status)
 {
     XPCJSRuntime* self = nsXPConnect::GetRuntimeInstance();
     if (!self)
         return;
 
     switch (status) {
         case JSGC_BEGIN:
@@ -1065,16 +1083,18 @@ XPCJSRuntime::GetJSCycleCollectionContex
     }
     return mJSCycleCollectionContext;
 }
 
 XPCJSRuntime::~XPCJSRuntime()
 {
     MOZ_ASSERT(!mReleaseRunnable);
 
+    js::SetGCSliceCallback(mJSRuntime, mPrevGCSliceCallback);
+
     if (mWatchdogWakeup) {
         // If the watchdog thread is running, tell it to terminate waking it
         // up if necessary and wait until it signals that it finished. As we
         // must release the lock before calling PR_DestroyCondVar, we use an
         // extra block here.
         {
             AutoLockWatchdog lock(this);
             if (mWatchdogThread) {
@@ -2152,16 +2172,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
     JS_SetNativeStackQuota(mJSRuntime, 2 * 128 * sizeof(size_t) * 1024);
 #else  
     JS_SetNativeStackQuota(mJSRuntime, 128 * sizeof(size_t) * 1024);
 #endif
     JS_SetContextCallback(mJSRuntime, ContextCallback);
     JS_SetDestroyCompartmentCallback(mJSRuntime, CompartmentDestroyedCallback);
     JS_SetCompartmentNameCallback(mJSRuntime, CompartmentNameCallback);
     JS_SetGCCallback(mJSRuntime, GCCallback);
+    mPrevGCSliceCallback = js::SetGCSliceCallback(mJSRuntime, GCSliceCallback);
     JS_SetFinalizeCallback(mJSRuntime, FinalizeCallback);
     JS_SetExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this);
     JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
     JS_SetWrapObjectCallbacks(mJSRuntime,
                               xpc::WrapperFactory::Rewrap,
                               xpc::WrapperFactory::WrapForSameCompartment,
                               xpc::WrapperFactory::PrepareForWrapping);
     js::SetPreserveWrapperCallback(mJSRuntime, PreserveWrapper);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -751,16 +751,19 @@ public:
 
     static void TraceBlackJS(JSTracer* trc, void* data);
     static void TraceGrayJS(JSTracer* trc, void* data);
     void TraceXPConnectRoots(JSTracer *trc);
     void AddXPConnectRoots(nsCycleCollectionTraversalCallback& cb);
     void UnmarkSkippableJSHolders();
 
     static void GCCallback(JSRuntime *rt, JSGCStatus status);
+    static void GCSliceCallback(JSRuntime *rt,
+                                js::GCProgress progress,
+                                const js::GCDescription &desc);
     static void FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, JSBool isCompartmentGC);
 
     inline void AddVariantRoot(XPCTraceableVariant* variant);
     inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
     inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
 
     nsresult AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
     nsresult RemoveJSHolder(void* aHolder);
@@ -905,16 +908,17 @@ private:
     JSDHashTable mJSHolders;
     PRLock *mWatchdogLock;
     PRCondVar *mWatchdogWakeup;
     PRThread *mWatchdogThread;
     nsTArray<JSGCCallback> extraGCCallbacks;
     bool mWatchdogHibernating;
     PRTime mLastActiveTime; // -1 if active NOW
     XPCIncrementalReleaseRunnable *mReleaseRunnable;
+    js::GCSliceCallback mPrevGCSliceCallback;
 
     nsCOMPtr<nsIException>   mPendingException;
     nsCOMPtr<nsIExceptionManager> mExceptionManager;
     bool mExceptionManagerNotAvailable;
 
     friend class AutoLockWatchdog;
     friend class XPCIncrementalReleaseRunnable;
 };
--- a/js/xpconnect/tests/chrome/test_weakmaps.xul
+++ b/js/xpconnect/tests/chrome/test_weakmaps.xul
@@ -208,42 +208,24 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   let make_live_map = function () {
     let live = get_live_dom();
     wn_live_map.set(live, {});
   }
 
   make_live_map();
 
-  let unpreservable_native_key = function () {
-    // We only allow natives that support wrapper preservation to be used as weak
-    // map keys.  We should be able to try to add unpreservable natives as keys without
-    // crashing (bug 711616), but we should throw an error (bug 761620).
-
-    let dummy_test_map = new WeakMap;
 
-    let div_fail = false;
-    try {
-      dummy_test_map.set(document.createElement("div").style, 1);
-    } catch (e) {
-      div_fail = true;
-    }
-    ok(div_fail, "Using elem.style as a weak map key should produce an exception because it can't be wrapper preserved.");
+  let dummy_test_map = new WeakMap;
+  // bug 711616: should be able to do this without crashing. JS warning is expected.
+  dummy_test_map.set(document.createElement("div").style, 1);
 
-    let navi_fail = false;
-    try {
-      dummy_test_map.set(window.navigator, 1);
-    } catch (e) {
-      navi_fail = true;
-    }
-    ok(navi_fail, "Using window.navigator as a weak map key should produce an exception because it can't be wrapper preserved.");
+  // JS warning is expected.
+  dummy_test_map.set(window.navigator, 1);
 
-  }
-
-  unpreservable_native_key();
 
   /* set up for running precise GC/CC then checking the results */
 
   SimpleTest.waitForExplicitFinish();
 
   Cu.schedulePreciseGC(function () {
     window.QueryInterface(Ci.nsIInterfaceRequestor)
          .getInterface(Ci.nsIDOMWindowUtils)
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -109,20 +109,20 @@ typedef struct CapturingContentInfo {
   // capture should only be allowed during a mousedown event
   bool mAllowed;
   bool mPointerLock;
   bool mRetargetToElement;
   bool mPreventDrag;
   nsIContent* mContent;
 } CapturingContentInfo;
 
-// fcada634-fdea-45f5-b841-0a361d5f6a68
+// 7E29E8A8-9C77-4445-A523-41B363E0C98A
 #define NS_IPRESSHELL_IID \
-  { 0xfcada634, 0xfdea, 0x45f5, \
-    { 0xb8, 0x41, 0x0a, 0x36, 0x1d, 0x5f, 0x6a, 0x68 } }
+  { 0x7e29e8a8, 0x9c77, 0x4445, \
+    { 0xa5, 0x23, 0x41, 0xb3, 0x63, 0xe0, 0xc9, 0x8a } }
 
 // debug VerifyReflow flags
 #define VERIFY_REFLOW_ON                    0x01
 #define VERIFY_REFLOW_NOISY                 0x02
 #define VERIFY_REFLOW_ALL                   0x04
 #define VERIFY_REFLOW_DUMP_COMMANDS         0x08
 #define VERIFY_REFLOW_NOISY_RC              0x10
 #define VERIFY_REFLOW_REALLY_NOISY_RC       0x20
@@ -1311,16 +1311,20 @@ public:
   bool IsScrollPositionClampingScrollPortSizeSet() {
     return mScrollPositionClampingScrollPortSizeSet;
   }
   nsSize GetScrollPositionClampingScrollPortSize() {
     NS_ASSERTION(mScrollPositionClampingScrollPortSizeSet, "asking for scroll port when its not set?");
     return mScrollPositionClampingScrollPortSize;
   }
 
+  virtual void WindowSizeMoveDone() = 0;
+  virtual void SysColorChanged() = 0;
+  virtual void ThemeChanged() = 0;
+
 protected:
   friend class nsRefreshDriver;
 
   // IMPORTANT: The ownership implicit in the following member variables
   // has been explicitly checked.  If you add any members to this class,
   // please make the ownership explicit (pinkerton, scc).
 
   // These are the same Document and PresContext owned by the DocViewer.
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -5657,26 +5657,16 @@ PresShell::HandleEvent(nsIFrame        *
   if (mIsDestroying ||
       (sDisableNonTestMouseEvents && NS_IS_MOUSE_EVENT(aEvent) &&
        !(aEvent->flags & NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT))) {
     return NS_OK;
   }
 
   RecordMouseLocation(aEvent);
 
-#ifdef ACCESSIBILITY
-  if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT) {
-    NS_TIME_FUNCTION_MIN(1.0);
-
-    // Accessibility events come through OS requests and not from scripts,
-    // so it is safe to handle here
-    return HandleEventInternal(aEvent, aEventStatus);
-  }
-#endif
-
   if (!nsContentUtils::IsSafeToRunScript())
     return NS_OK;
 
   NS_TIME_FUNCTION_MIN(1.0);
 
   nsIContent* capturingContent =
     NS_IS_MOUSE_EVENT(aEvent) || aEvent->eventStructType == NS_WHEEL_EVENT ?
       GetCapturingContent() : nullptr;
@@ -5740,40 +5730,16 @@ PresShell::HandleEvent(nsIFrame        *
           return NS_OK;
 
         nsCOMPtr<nsIPresShell> shell = frame->PresContext()->GetPresShell();
         return shell->HandleEvent(frame, aEvent, true, aEventStatus);
       }
     }
   }
 
-  // Check for a theme change up front, since the frame type is irrelevant
-  if (aEvent->message == NS_THEMECHANGED && mPresContext) {
-    mPresContext->ThemeChanged();
-    return NS_OK;
-  }
-
-  if (aEvent->message == NS_UISTATECHANGED && mDocument) {
-    nsPIDOMWindow* win = mDocument->GetWindow();
-    if (win) {
-      nsUIStateChangeEvent* event = (nsUIStateChangeEvent*)aEvent;
-      win->SetKeyboardIndicators(event->showAccelerators, event->showFocusRings);
-    }
-    return NS_OK;
-  }
-
-  // Check for a system color change up front, since the frame type is
-  // irrelevant
-  if ((aEvent->message == NS_SYSCOLORCHANGED) && mPresContext &&
-      aFrame == mFrameConstructor->GetRootFrame()) {
-    *aEventStatus = nsEventStatus_eConsumeDoDefault;
-    mPresContext->SysColorChanged();
-    return NS_OK;
-  }
-
   if (aEvent->eventStructType == NS_KEY_EVENT &&
       mDocument && mDocument->EventHandlingSuppressed()) {
     if (aEvent->message == NS_KEY_DOWN) {
       mNoDelayedKeyEvents = true;
     } else if (!mNoDelayedKeyEvents) {
       nsDelayedEvent* event =
         new nsDelayedKeyEvent(static_cast<nsKeyEvent*>(aEvent));
       if (!mDelayedEvents.AppendElement(event)) {
@@ -6301,42 +6267,16 @@ static bool CanHandleContextMenuEvent(ns
   return true;
 }
 
 nsresult
 PresShell::HandleEventInternal(nsEvent* aEvent, nsEventStatus* aStatus)
 {
   NS_TIME_FUNCTION_MIN(1.0);
 
-#ifdef ACCESSIBILITY
-  if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
-  {
-    nsAccessibleEvent *accEvent = static_cast<nsAccessibleEvent*>(aEvent);
-    accEvent->mAccessible = nullptr;
-
-    nsCOMPtr<nsIAccessibilityService> accService =
-      do_GetService("@mozilla.org/accessibilityService;1");
-    if (accService) {
-      nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
-      if (!container) {
-        // This presshell is not active. This often happens when a
-        // preshell is being held onto for fastback.
-        return NS_OK;
-      }
-
-      // Accessible creation might be not safe so we make sure it's not created
-      // at unsafe times.
-      accEvent->mAccessible =
-        accService->GetRootDocumentAccessible(this, nsContentUtils::IsSafeToRunScript());
-
-      return NS_OK;
-    }
-  }
-#endif
-
   nsRefPtr<nsEventStateManager> manager = mPresContext->EventStateManager();
   nsresult rv = NS_OK;
 
   if (!NS_EVENT_NEEDS_FRAME(aEvent) || GetCurrentEventFrame()) {
     bool touchIsNew = false;
     bool isHandlingUserInput = false;
 
     // XXX How about IME events and input events for plugins?
@@ -7705,16 +7645,25 @@ PresShell::ProcessReflowCommands(bool aI
         : Telemetry::HTML_BACKGROUND_REFLOW_MS;
     }
     Telemetry::AccumulateTimeDelta(id, timerStart);
   }
 
   return !interrupted;
 }
 
+void
+PresShell::WindowSizeMoveDone()
+{
+  if (mPresContext) {
+    nsEventStateManager::ClearGlobalActiveContent(nullptr);
+    ClearMouseCapture(nullptr);
+  }
+}
+
 #ifdef MOZ_XUL
 /*
  * It's better to add stuff to the |DidSetStyleContext| method of the
  * relevant frames than adding it here.  These methods should (ideally,
  * anyway) go away.
  */
 
 // Return value says whether to walk children.
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -684,17 +684,22 @@ protected:
   nscolor GetDefaultBackgroundColorToDraw();
 
   // The callback for the mPaintSuppressionTimer timer.
   static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell);
 
   // The callback for the mReflowContinueTimer timer.
   static void sReflowContinueCallback(nsITimer* aTimer, void* aPresShell);
   bool ScheduleReflowOffTimer();
-  
+
+  // Widget notificiations
+  virtual void WindowSizeMoveDone();
+  virtual void SysColorChanged() { mPresContext->SysColorChanged(); }
+  virtual void ThemeChanged() { mPresContext->ThemeChanged(); }
+
 #ifdef DEBUG
   // The reflow root under which we're currently reflowing.  Null when
   // not in reflow.
   nsIFrame*                 mCurrentReflowRoot;
   PRUint32                  mUpdateCount;
 #endif
 
 #ifdef MOZ_REFLOW_PERF
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -414,18 +414,17 @@ nsObjectFrame::PrepForDrawing(nsIWidget 
     GetEmptyClipConfiguration(&configuration);
     NS_ASSERTION(configuration.Length() > 0, "Empty widget configuration array!");
     configuration[0].mBounds.width = mRect.width;
     configuration[0].mBounds.height = mRect.height;
     parentWidget->ConfigureChildren(configuration);
 
     nsRefPtr<nsDeviceContext> dx;
     viewMan->GetDeviceContext(*getter_AddRefs(dx));
-    EVENT_CALLBACK eventHandler = mInnerView->AttachWidgetEventHandler(mWidget);
-    mWidget->SetEventCallback(eventHandler, dx);
+    mInnerView->AttachWidgetEventHandler(mWidget);
 
 #ifdef XP_MACOSX
     // On Mac, we need to invalidate ourselves since even windowed
     // plugins are painted through Thebes and we need to ensure
     // the Thebes layer containing the plugin is updated.
     if (parentWidget == GetNearestWidget()) {
       Invalidate(GetContentRectRelativeToSelf());
     }
@@ -2108,22 +2107,25 @@ nsObjectFrame::HandleEvent(nsPresContext
   if ((anEvent->message == NS_MOUSE_ENTER ||
        anEvent->message == NS_WHEEL_WHEEL) &&
       mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
     *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
     return rv;
   }
 #endif
 
+/*
+  // XXXndeakin review note: I don't see how this would ever be called.
   if (anEvent->message == NS_DESTROY) {
 #ifdef MAC_CARBON_PLUGINS
     mInstanceOwner->CancelTimer();
 #endif
     return rv;
   }
+*/
 
   return nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
 }
 
 #ifdef XP_MACOSX
 // Needed to make the routing of mouse events while dragging conform to
 // standard OS X practice, and to the Cocoa NPAPI spec.  See bug 525078.
 NS_IMETHODIMP
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -3045,18 +3045,17 @@ nsFrameSelection::DeleteFromDocument()
   }
 
   // Get an iterator
   nsSelectionIterator iter(mDomSelections[index]);
   res = iter.First();
   if (NS_FAILED(res))
     return res;
 
-  while (iter.IsDone())
-  {
+  while (iter.IsDone() == static_cast<nsresult>(NS_ENUMERATOR_FALSE)) {
     nsRefPtr<nsRange> range = iter.CurrentItem();
     res = range->DeleteContents();
     if (NS_FAILED(res))
       return res;
     iter.Next();
   }
 
   // Collapse to the new location.
--- a/layout/mathml/nsMathMLOperators.cpp
+++ b/layout/mathml/nsMathMLOperators.cpp
@@ -111,17 +111,17 @@ SetProperty(OperatorData* aOperatorData,
       isLeadingSpace = true;
     else if (aName.EqualsLiteral("rspace"))
       isLeadingSpace = false;
     else return;  // input is not applicable
 
     // aValue is assumed to be a digit from 0 to 7
     nsresult error = NS_OK;
     float space = aValue.ToFloat(&error) / 18.0;
-    if (error) return;
+    if (NS_FAILED(error)) return;
 
     if (isLeadingSpace)
       aOperatorData->mLeadingSpace = space;
     else
       aOperatorData->mTrailingSpace = space;
   }
 }
 
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -179,17 +179,17 @@ nsMathMLmpaddedFrame::ParseAttribute(nsS
             NS_LossyConvertUTF16toASCII(aString).get());
 #endif
     aSign = NS_MATHML_SIGN_INVALID;
     return false;
   }
 
   nsresult errorCode;
   float floatValue = number.ToFloat(&errorCode);
-  if (errorCode) {
+  if (NS_FAILED(errorCode)) {
     aSign = NS_MATHML_SIGN_INVALID;
     return false;
   }
 
   // see if this is a percentage-based value
   if (i < stringLength && aString[i] == '%') {
     i++;
     gotPercent = true;
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -318,17 +318,17 @@ ParseAlignAttribute(nsString& aValue, eA
   else if (0 == aValue.Find("axis")) {
     len = 4; // 4 is the length of 'axis'
     aAlign = eAlign_axis;
   }
   if (len) {
     nsresult error;
     aValue.Cut(0, len); // aValue is not a const here
     aRowIndex = aValue.ToInteger(&error);
-    if (error)
+    if (NS_FAILED(error))
       aRowIndex = 0;
   }
 }
 
 #ifdef DEBUG_rbs_off
 // call ListMathMLTree(mParent) to get the big picture
 static void
 ListMathMLTree(nsIFrame* atLeast)
@@ -772,17 +772,17 @@ nsMathMLmtdFrame::GetRowSpan()
 
   // Don't look at the content's rowspan if we're not an mtd or a pseudo cell.
   if ((mContent->Tag() == nsGkAtoms::mtd_) && !GetStyleContext()->GetPseudo()) {
     nsAutoString value;
     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rowspan, value);
     if (!value.IsEmpty()) {
       nsresult error;
       rowspan = value.ToInteger(&error);
-      if (error || rowspan < 0)
+      if (NS_FAILED(error) || rowspan < 0)
         rowspan = 1;
       rowspan = NS_MIN(rowspan, MAX_ROWSPAN);
     }
   }
   return rowspan;
 }
 
 PRInt32
@@ -792,17 +792,17 @@ nsMathMLmtdFrame::GetColSpan()
 
   // Don't look at the content's colspan if we're not an mtd or a pseudo cell.
   if ((mContent->Tag() == nsGkAtoms::mtd_) && !GetStyleContext()->GetPseudo()) {
     nsAutoString value;
     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::columnspan_, value);
     if (!value.IsEmpty()) {
       nsresult error;
       colspan = value.ToInteger(&error);
-      if (error || colspan < 0 || colspan > MAX_COLSPAN)
+      if (NS_FAILED(error) || colspan < 0 || colspan > MAX_COLSPAN)
         colspan = 1;
     }
   }
   return colspan;
 }
 
 NS_IMETHODIMP
 nsMathMLmtdFrame::AttributeChanged(PRInt32  aNameSpaceID,
--- a/layout/style/nsCSSScanner.cpp
+++ b/layout/style/nsCSSScanner.cpp
@@ -279,17 +279,17 @@ nsCSSScanner::~nsCSSScanner()
 
 #ifdef CSS_REPORT_PARSE_ERRORS
 #define CSS_ERRORS_PREF "layout.css.report_errors"
 
 static int
 CSSErrorsPrefChanged(const char *aPref, void *aClosure)
 {
   gReportErrors = Preferences::GetBool(CSS_ERRORS_PREF, true);
-  return NS_OK;
+  return 0;
 }
 #endif
 
 /* static */ bool
 nsCSSScanner::InitGlobals()
 {
 #ifdef CSS_REPORT_PARSE_ERRORS
   if (gConsoleService && gScriptErrorFactory)
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -740,17 +740,17 @@ nsUserFontSet::LogMessage(gfxProxyFontEn
     case NS_ERROR_DOM_BAD_URI:
       msg.Append("bad URI or cross-site access not allowed");
       break;
     case NS_ERROR_CONTENT_BLOCKED:
       msg.Append("content blocked");
       break;
     default:
       msg.Append("status=");
-      msg.AppendInt(aStatus);
+      msg.AppendInt(static_cast<PRUint32>(aStatus));
       break;
     }
   }
   msg.Append("\nsource: ");
   msg.Append(fontURI);
 
 #ifdef PR_LOGGING
   if (PR_LOG_TEST(sUserFontsLog, PR_LOG_DEBUG)) {
--- a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp
+++ b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp
@@ -157,17 +157,18 @@ nsSVGInnerSVGFrame::NotifySVGChanged(PRU
   nsSVGInnerSVGFrameBase::NotifySVGChanged(aFlags);
 }
 
 NS_IMETHODIMP
 nsSVGInnerSVGFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                      nsIAtom* aAttribute,
                                      PRInt32  aModType)
 {
-  if (aNameSpaceID == kNameSpaceID_None) {
+  if (aNameSpaceID == kNameSpaceID_None &&
+      !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
 
     nsSVGSVGElement* content = static_cast<nsSVGSVGElement*>(mContent);
 
     if (aAttribute == nsGkAtoms::width ||
         aAttribute == nsGkAtoms::height) {
       nsSVGUtils::InvalidateAndScheduleReflowSVG(this);
 
       if (content->HasViewBoxOrSyntheticViewBox()) {
--- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
@@ -576,17 +576,17 @@ DependsOnIntrinsicSize(const nsIFrame* a
 }
 
 NS_IMETHODIMP
 nsSVGOuterSVGFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                      nsIAtom* aAttribute,
                                      PRInt32  aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
-      !(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
+      !(GetStateBits() & (NS_FRAME_FIRST_REFLOW | NS_STATE_SVG_NONDISPLAY_CHILD))) {
     if (aAttribute == nsGkAtoms::viewBox ||
         aAttribute == nsGkAtoms::preserveAspectRatio ||
         aAttribute == nsGkAtoms::transform) {
 
       // make sure our cached transform matrix gets (lazily) updated
       mCanvasTM = nullptr;
 
       nsSVGUtils::NotifyChildrenOfSVGChange(GetFirstPrincipalChild(),
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/757751-1.svg
@@ -0,0 +1,8 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <svg id="x" viewBox=" 0 0 10 10"/>
+  </defs>
+  <script>
+    window.addEventListener("load", function() { document.getElementById("x").setAttribute("width", "2"); }, false);
+  </script>
+</svg>
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -126,9 +126,10 @@ load 713413-1.svg
 load 722003-1.svg
 load 725918-1.svg
 load 732836-1.svg
 load 740627-1.svg
 load 740627-2.svg
 load 757704-1.svg
 load 757718-1.svg
 load 768351.svg
+load 757751-1.svg
 
--- a/layout/tools/layout-debug/src/nsILayoutRegressionTester.idl
+++ b/layout/tools/layout-debug/src/nsILayoutRegressionTester.idl
@@ -34,11 +34,11 @@ interface nsILayoutRegressionTester : ns
    * Compares the contents of frame model files
    * @param aBaseFile           the baseline file, opened with read permissions
    * @param aVerFile            file containing the results to verify, opened with read permissions
    * @param aFlags              flags specifying output verbosity
    * @param aResult             result of the comparison: zero if the files are same, non-zero if different
    */
   const short COMPARE_FLAGS_VERBOSE        = 0;
   const short COMPARE_FLAGS_BRIEF          = 1;
-  long compareFrameModels(in nsIFile aBaseFile, in nsIFile aVerFile, in unsigned long aFlags);
+  boolean compareFrameModels(in nsIFile aBaseFile, in nsIFile aVerFile, in unsigned long aFlags);
 };
 
--- a/layout/tools/layout-debug/src/nsRegressionTester.cpp
+++ b/layout/tools/layout-debug/src/nsRegressionTester.cpp
@@ -102,23 +102,24 @@ nsRegressionTester::DumpFrameModel(nsIDO
   if (fp != stdout)
     fclose(fp);
   *aResult = DUMP_RESULT_COMPLETED;
   return NS_OK;
 #endif
 }
 
 NS_IMETHODIMP
-nsRegressionTester::CompareFrameModels(nsIFile *aBaseFile, nsIFile *aVerFile, PRUint32 aFlags, PRInt32 *aResult) 
+nsRegressionTester::CompareFrameModels(nsIFile *aBaseFile, nsIFile *aVerFile,
+                                       PRUint32 aFlags, bool *aResult)
 {
   NS_ENSURE_ARG(aBaseFile);
   NS_ENSURE_ARG(aVerFile);
   NS_ENSURE_ARG_POINTER(aResult);
   
-  *aResult = NS_OK;
+  *aResult = false;
   
   nsresult rv;
   FILE* baseFile;
   rv = aBaseFile->OpenANSIFileDesc("r", &baseFile);
   if (NS_FAILED(rv)) return rv;
 
   FILE* verFile;
   rv = aVerFile->OpenANSIFileDesc("r", &verFile);
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -91,17 +91,17 @@ class GeckoInputConnection
 
     private String mCurrentInputMethod;
 
     // Is a composition active?
     private int mCompositionStart = NO_COMPOSITION_STRING;
     private boolean mCommittingText;
     private KeyCharacterMap mKeyCharacterMap;
     private final Editable mEditable;
-    private boolean mBatchMode;
+    protected int mBatchEditCount;
     private ExtractedTextRequest mUpdateRequest;
     private final ExtractedText mUpdateExtract = new ExtractedText();
 
     public static GeckoInputConnection create(View targetView) {
         if (DEBUG)
             return new DebugGeckoInputConnection(targetView);
         else
             return new GeckoInputConnection(targetView);
@@ -113,23 +113,27 @@ class GeckoInputConnection
         spanAndSelectEditable();
         mIMEState = IME_STATE_DISABLED;
         mIMETypeHint = "";
         mIMEActionHint = "";
     }
 
     @Override
     public boolean beginBatchEdit() {
-        mBatchMode = true;
+        mBatchEditCount++;
         return true;
     }
 
     @Override
     public boolean endBatchEdit() {
-        mBatchMode = false;
+        if (mBatchEditCount > 0) {
+            mBatchEditCount--;
+        } else {
+            Log.w(LOGTAG, "endBatchEdit() called, but mBatchEditCount == 0?!");
+        }
         return true;
     }
 
     @Override
     public boolean commitCompletion(CompletionInfo text) {
         return commitText(text.getText(), 1);
     }
 
@@ -153,37 +157,30 @@ class GeckoInputConnection
     @Override
     public boolean finishComposingText() {
         // finishComposingText() is sometimes called even when we are not composing text.
         if (hasCompositionString()) {
             if (DEBUG) Log.d(LOGTAG, ". . . finishComposingText: endComposition");
             endComposition();
         }
 
-        final Editable content = getEditable();
-        if (content != null) {
-            beginBatchEdit();
-            removeComposingSpans(content);
-            endBatchEdit();
-        }
+        beginBatchEdit();
+        removeComposingSpans(mEditable);
+        endBatchEdit();
         return true;
     }
 
     @Override
     public Editable getEditable() {
         return mEditable;
     }
 
     @Override
     public boolean performContextMenuAction(int id) {
-        final Editable content = getEditable();
-        if (content == null)
-            return false;
-
-        String text = content.toString();
+        String text = mEditable.toString();
         Span selection = getSelection();
 
         switch (id) {
             case R.id.selectAll:
                 setSelection(0, text.length());
                 break;
             case R.id.cut:
                 // Fill the clipboard
@@ -209,41 +206,37 @@ class GeckoInputConnection
         return true;
     }
 
     @Override
     public ExtractedText getExtractedText(ExtractedTextRequest req, int flags) {
         if (req == null)
             return null;
 
-        final Editable content = getEditable();
-        if (content == null)
-            return null;
-
         if ((flags & GET_EXTRACTED_TEXT_MONITOR) != 0)
             mUpdateRequest = req;
 
         Span selection = getSelection();
 
         ExtractedText extract = new ExtractedText();
         extract.flags = 0;
         extract.partialStartOffset = -1;
         extract.partialEndOffset = -1;
         extract.selectionStart = selection.start;
         extract.selectionEnd = selection.end;
         extract.startOffset = 0;
-        extract.text = content.toString();
+        extract.text = mEditable.toString();
 
         return extract;
     }
 
     @Override
     public boolean setSelection(int start, int end) {
         // Some IMEs call setSelection() with negative or stale indexes, so clamp them.
-        Span newSelection = Span.clamp(start, end, getEditable());
+        Span newSelection = Span.clamp(start, end, mEditable);
         GeckoAppShell.sendEventToGecko(GeckoEvent.createIMEEvent(GeckoEvent.IME_SET_SELECTION,
                                                                  newSelection.start,
                                                                  newSelection.length));
         return super.setSelection(newSelection.start, newSelection.end);
     }
 
     @Override
     public CharSequence getTextBeforeCursor(int length, int flags) {
@@ -259,17 +252,17 @@ class GeckoInputConnection
 
         return super.getTextBeforeCursor(length, flags);
     }
 
     @Override
     public CharSequence getTextAfterCursor(int length, int flags) {
         // Avoid overrunning text buffer.
         Span selection = getSelection();
-        int contentLength = getEditable().length();
+        int contentLength = mEditable.length();
         if (selection.end + length > contentLength) {
             length = contentLength - selection.end;
         }
 
         if (length < 1) {
             return "";
         }
 
@@ -285,46 +278,40 @@ class GeckoInputConnection
     }
 
     private static View getView() {
         GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
         return (layerClient == null ? null : layerClient.getView());
     }
 
     private Span getSelection() {
-        Editable content = getEditable();
-        int start = Selection.getSelectionStart(content);
-        int end = Selection.getSelectionEnd(content);
-        return Span.clamp(start, end, content);
+        int start = Selection.getSelectionStart(mEditable);
+        int end = Selection.getSelectionEnd(mEditable);
+        return Span.clamp(start, end, mEditable);
     }
 
     private void replaceText(CharSequence text, int newCursorPosition, boolean composing) {
         if (DEBUG) {
             Log.d(LOGTAG, String.format("IME: replaceText(\"%s\", %d, %b)",
                                         text, newCursorPosition, composing));
             GeckoApp.assertOnUiThread();
         }
 
         if (text == null)
             text = "";
 
-        final Editable content = getEditable();
-        if (content == null) {
-            return;
-        }
-
         beginBatchEdit();
 
         // delete composing text set previously.
         int a;
         int b;
 
         Span composingSpan = getComposingSpan();
         if (composingSpan != null) {
-            removeComposingSpans(content);
+            removeComposingSpans(mEditable);
             a = composingSpan.start;
             b = composingSpan.end;
             composingSpan = null;
         } else {
             Span selection = getSelection();
             a = selection.start;
             b = selection.end;
         }
@@ -345,69 +332,64 @@ class GeckoInputConnection
 
         if (DEBUG) Log.d(LOGTAG, "Replacing from " + a + " to " + b + " with \""
                 + text + "\", composing=" + composing
                 + ", type=" + text.getClass().getCanonicalName());
 
         if (DEBUG) {
             LogPrinter lp = new LogPrinter(Log.VERBOSE, LOGTAG);
             lp.println("Current text:");
-            TextUtils.dumpSpans(content, lp, "  ");
+            TextUtils.dumpSpans(mEditable, lp, "  ");
             lp.println("Composing text:");
             TextUtils.dumpSpans(text, lp, "  ");
         }
 
         // Position the cursor appropriately, so that after replacing the
         // desired range of text it will be located in the correct spot.
         // This allows us to deal with filters performing edits on the text
         // we are providing here.
         if (newCursorPosition > 0) {
             newCursorPosition += b - 1;
         } else {
             newCursorPosition += a;
         }
         if (newCursorPosition < 0) newCursorPosition = 0;
-        if (newCursorPosition > content.length())
-            newCursorPosition = content.length();
-        Selection.setSelection(content, newCursorPosition);
+        if (newCursorPosition > mEditable.length())
+            newCursorPosition = mEditable.length();
+        Selection.setSelection(mEditable, newCursorPosition);
 
-        content.replace(a, b, text);
+        mEditable.replace(a, b, text);
 
         if (DEBUG) {
             LogPrinter lp = new LogPrinter(Log.VERBOSE, LOGTAG);
             lp.println("Final text:");
-            TextUtils.dumpSpans(content, lp, "  ");
+            TextUtils.dumpSpans(mEditable, lp, "  ");
         }
 
         endBatchEdit();
     }
 
     @Override
     public boolean setComposingRegion(int start, int end) {
         if (hasCompositionString()) {
             if (DEBUG) Log.d(LOGTAG, ". . . setComposingRegion: endComposition");
             endComposition();
         }
 
-        Span newComposingRegion = Span.clamp(start, end, getEditable());
+        Span newComposingRegion = Span.clamp(start, end, mEditable);
         return super.setComposingRegion(newComposingRegion.start, newComposingRegion.end);
     }
 
     public String getComposingText() {
-        final Editable content = getEditable();
-        if (content == null) {
-            return null;
-        }
-
         Span composingSpan = getComposingSpan();
         if (composingSpan == null || composingSpan.length == 0) {
             return "";
         }
 
-        return TextUtils.substring(content, composingSpan.start, composingSpan.end);
+        return TextUtils.substring(mEditable, composingSpan.start, composingSpan.end);
     }
 
     public boolean onKeyDel() {
         // Some IMEs don't update us on deletions
         // In that case we are not updated when a composition
         // is destroyed, and Bad Things happen
 
         if (!hasCompositionString())
@@ -431,17 +413,17 @@ class GeckoInputConnection
             return null;
         }
         Context context = view.getContext();
         return InputMethods.getInputMethodManager(context);
     }
 
     protected void notifyTextChange(InputMethodManager imm, String text,
                                     int start, int oldEnd, int newEnd) {
-        if (!mBatchMode) {
+        if (mBatchEditCount == 0) {
             if (!text.contentEquals(mEditable)) {
                 if (DEBUG) Log.d(LOGTAG, ". . . notifyTextChange: current mEditable="
                                          + prettyPrintString(mEditable));
 
                 // Editable will be updated by IME event
                 if (!hasCompositionString())
                     setEditable(text);
             }
@@ -474,20 +456,18 @@ class GeckoInputConnection
 
         mUpdateExtract.text = updatedText;
         mUpdateExtract.startOffset = 0;
 
         imm.updateExtractedText(v, mUpdateRequest.token, mUpdateExtract);
     }
 
     protected void notifySelectionChange(InputMethodManager imm, int start, int end) {
-        if (!mBatchMode) {
-            final Editable content = getEditable();
-
-            Span newSelection = Span.clamp(start, end, content);
+        if (mBatchEditCount == 0) {
+            Span newSelection = Span.clamp(start, end, mEditable);
             start = newSelection.start;
             end = newSelection.end;
 
             Span currentSelection = getSelection();
             int a = currentSelection.start;
             int b = currentSelection.end;
 
             if (start != a || end != b) {
@@ -501,17 +481,17 @@ class GeckoInputConnection
 
                 // Check if the selection is inside composing span
                 Span composingSpan = getComposingSpan();
                 if (composingSpan != null) {
                     int ca = composingSpan.start;
                     int cb = composingSpan.end;
                     if (start < ca || start > cb || end < ca || end > cb) {
                         if (DEBUG) Log.d(LOGTAG, ". . . notifySelectionChange: removeComposingSpans");
-                        removeComposingSpans(content);
+                        removeComposingSpans(mEditable);
                     }
                 }
             }
         }
 
         if (imm != null && imm.isFullscreenMode()) {
             View v = getView();
             if (hasCompositionString()) {
@@ -520,19 +500,24 @@ class GeckoInputConnection
             } else {
                 imm.updateSelection(v, start, end, -1, -1);
             }
 
         }
     }
 
     protected void resetCompositionState() {
+        if (mBatchEditCount > 0) {
+            Log.d(LOGTAG, "resetCompositionState: resetting mBatchEditCount "
+                          + mBatchEditCount + " -> 0");
+            mBatchEditCount = 0;
+        }
+
         removeComposingSpans(mEditable);
         mCompositionStart = NO_COMPOSITION_STRING;
-        mBatchMode = false;
         mUpdateRequest = null;
     }
 
     // TextWatcher
     public void onTextChanged(CharSequence s, int start, int before, int count) {
         if (hasCompositionString() && mCompositionStart != start) {
             // Changed range is different from the composition, need to reset the composition
             endComposition();
@@ -1153,30 +1138,29 @@ class GeckoInputConnection
         Selection.setSelection(mEditable, length);
     }
 
     protected final boolean hasCompositionString() {
         return mCompositionStart != NO_COMPOSITION_STRING;
     }
 
     private Span getComposingSpan() {
-        Editable content = getEditable();
-        int start = getComposingSpanStart(content);
-        int end = getComposingSpanEnd(content);
+        int start = getComposingSpanStart(mEditable);
+        int end = getComposingSpanEnd(mEditable);
 
         // Does the editable have a composing span?
         if (start < 0 || end < 0) {
             if (start != -1 || end != -1) {
                 throw new IndexOutOfBoundsException("Bad composing span [" + start + "," + end
-                                                     + "), contentLength=" + content.length());
+                                                     + "), contentLength=" + mEditable.length());
             }
             return null;
         }
 
-        return new Span(start, end, content);
+        return new Span(start, end, mEditable);
     }
 
     private static String prettyPrintString(CharSequence s) {
         // Quote string and replace newlines with CR arrows.
         return "\"" + s.toString().replace('\n', UNICODE_CRARR) + "\"";
     }
 
     private static void postToUiThread(Runnable runnable) {
@@ -1224,25 +1208,31 @@ class GeckoInputConnection
 private static final class DebugGeckoInputConnection extends GeckoInputConnection {
     public DebugGeckoInputConnection(View targetView) {
         super(targetView);
         GeckoApp.assertOnUiThread();
     }
 
     @Override
     public boolean beginBatchEdit() {
-        Log.d(LOGTAG, "IME: beginBatchEdit");
+        Log.d(LOGTAG, "IME: beginBatchEdit: mBatchEditCount " + mBatchEditCount
+                                                     + " -> " + (mBatchEditCount+1));
         GeckoApp.assertOnUiThread();
         return super.beginBatchEdit();
     }
 
     @Override
     public boolean endBatchEdit() {
-        Log.d(LOGTAG, "IME: endBatchEdit");
+        Log.d(LOGTAG, "IME: endBatchEdit: mBatchEditCount " + mBatchEditCount
+                                                   + " -> " + (mBatchEditCount-1));
         GeckoApp.assertOnUiThread();
+        if (mBatchEditCount <= 0) {
+            throw new IllegalStateException("Expected positive mBatchEditCount, but got "
+                                            + mBatchEditCount);
+        }
         return super.endBatchEdit();
     }
 
     @Override
     public boolean commitCompletion(CompletionInfo text) {
         Log.d(LOGTAG, "IME: commitCompletion");
         GeckoApp.assertOnUiThread();
         return super.commitCompletion(text);
--- a/mobile/android/chrome/content/JSDOMParser.js
+++ b/mobile/android/chrome/content/JSDOMParser.js
@@ -307,16 +307,17 @@
     },
 
     removeChild: function (child) {
       let childNodes = this.childNodes;
       let childIndex = childNodes.indexOf(child);
       if (childIndex == -1) {
         throw "removeChild: node not found";
       } else {
+        child.parentNode = null;
         return childNodes.splice(childIndex, 1)[0];
       }
     },
 
     replaceChild: function (newNode, oldNode) {
       let childNodes = this.childNodes;
       let childIndex = childNodes.indexOf(oldNode);
       if (childIndex == -1) {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -6607,18 +6607,23 @@ let Reader = {
     browser.webNavigation.allowAuth = false;
     browser.webNavigation.allowImages = false;
     browser.webNavigation.allowJavascript = false;
     browser.webNavigation.allowMetaRedirects = true;
     browser.webNavigation.allowPlugins = false;
 
     browser.addEventListener("DOMContentLoaded", function (event) {
       let doc = event.originalTarget;
+
+      // ignore on frames and other documents
+      if (doc != browser.contentDocument)
+        return;
+
       this.log("Done loading: " + doc);
-      if (doc.location.href == "about:blank" || doc.defaultView.frameElement) {
+      if (doc.location.href == "about:blank") {
         callback(null);
 
         // Request has finished with error, remove browser element
         browser.parentNode.removeChild(browser);
         return;
       }
 
       callback(doc);
--- a/mobile/android/themes/core/aboutReader.css
+++ b/mobile/android/themes/core/aboutReader.css
@@ -125,17 +125,17 @@ body {
   overflow: scroll !important;
 }
 
 .content img {
   height: auto !important;
 }
 
 .content pre {
-  overflow: scroll !important;
+  white-space: pre-wrap !important;
 }
 
 .content blockquote {
   margin: 0px !important;
   padding: 0px !important;
   border: 0px !important;
   padding-left: 23px !important;
 }
--- a/netwerk/base/src/nsLoadGroup.cpp
+++ b/netwerk/base/src/nsLoadGroup.cpp
@@ -718,17 +718,18 @@ nsLoadGroup::RemoveRequest(nsIRequest *r
 // hash to an nsISupportsArray.
 static PLDHashOperator
 AppendRequestsToISupportsArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
                                PRUint32 number, void *arg)
 {
     RequestMapEntry *e = static_cast<RequestMapEntry *>(hdr);
     nsISupportsArray *array = static_cast<nsISupportsArray *>(arg);
 
-    bool ok = array->AppendElement(e->mKey);
+    // nsISupportsArray::AppendElement returns a bool disguised as nsresult
+    bool ok = static_cast<bool>(array->AppendElement(e->mKey));
 
     if (!ok) {
         return PL_DHASH_STOP;
     }
 
     return PL_DHASH_NEXT;
 }
 
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -2065,17 +2065,17 @@ nsHttpConnectionMgr::OnMsgReclaimConnect
                 PruneDeadConnectionsAfter(timeToLive);
         }
         else {
             LOG(("  connection cannot be reused; closing connection\n"));
             conn->Close(NS_ERROR_ABORT);
         }
     }
  
-    OnMsgProcessPendingQ(NS_OK, ci); // releases |ci|
+    OnMsgProcessPendingQ(0, ci); // releases |ci|
     NS_RELEASE(conn);
 }
 
 void
 nsHttpConnectionMgr::OnMsgCompleteUpgrade(PRInt32, void *param)
 {
     NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
     nsCompleteUpgradeData *data = (nsCompleteUpgradeData *) param;
@@ -2700,17 +2700,17 @@ nsHalfOpenSocket::OnOutputStreamReady(ns
         }
         else {
             // otherwise just put this in the persistent connection pool
             LOG(("nsHalfOpenSocket::OnOutputStreamReady no transaction match "
                  "returning conn %p to pool\n", conn.get()));
             nsRefPtr<nsHttpConnection> copy(conn);
             // forget() to effectively addref because onmsg*() will drop a ref
             gHttpHandler->ConnMgr()->OnMsgReclaimConnection(
-                NS_OK, conn.forget().get());
+                0, conn.forget().get());
         }
     }
 
     return rv;
 }
 
 // method for nsITransportEventSink
 NS_IMETHODIMP
--- a/netwerk/socket/nsSOCKSIOLayer.cpp
+++ b/netwerk/socket/nsSOCKSIOLayer.cpp
@@ -1258,18 +1258,17 @@ nsSOCKSIOLayerAddToSocket(PRInt32 family
         return NS_ERROR_FAILURE;
     }
 
     NS_ADDREF(infoObject);
     infoObject->Init(socksVersion, family, proxyHost, proxyPort, host, flags);
     layer->secret = (PRFilePrivate*) infoObject;
     rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);
 
-    if (NS_FAILED(rv))
-    {
+    if (rv == PR_FAILURE) {
         LOGERROR(("PR_PushIOLayer() failed. rv = %x.", rv));
         NS_RELEASE(infoObject);
         PR_DELETE(layer);
         return NS_ERROR_FAILURE;
     }
 
     *info = static_cast<nsISOCKSSocketInfo*>(infoObject);
     NS_ADDREF(*info);
--- a/netwerk/wifi/nsIWifiListener.idl
+++ b/netwerk/wifi/nsIWifiListener.idl
@@ -21,10 +21,10 @@ interface nsIWifiListener : nsISupports
 
   /*
    * Called when there is a problem with listening to wifi
    *
    * @param error the error which caused this event.  The
    *              error values will be nsresult codes.
    */
 
-  void onError(in long error);
+  void onError(in nsresult error);
 };
--- a/parser/htmlparser/src/nsHTMLTokens.cpp
+++ b/parser/htmlparser/src/nsHTMLTokens.cpp
@@ -2164,17 +2164,17 @@ CEntityToken::TranslateToUnicodeStr(nsSt
   if (mTextValue.Length() > 1) {
     PRUnichar theChar0 = mTextValue.CharAt(0);
 
     if (kHashsign == theChar0) {
       nsresult err = NS_OK;
 
       value = mTextValue.ToInteger(&err, kAutoDetect);
 
-      if (0 == err) {
+      if (NS_SUCCEEDED(err)) {
         AppendNCR(aString, value);
       }
     } else {
       value = nsHTMLEntities::EntityToUnicode(mTextValue);
       if (-1 < value) {
         // We found a named entity...
         aString.Assign(PRUnichar(value));
       }
--- a/security/manager/ssl/src/nsCertOverrideService.cpp
+++ b/security/manager/ssl/src/nsCertOverrideService.cpp
@@ -270,17 +270,17 @@ nsCertOverrideService::Read()
     PRInt32 port;
     PRInt32 portIndex = host.RFindChar(':');
     if (portIndex == kNotFound)
       continue; // Ignore broken entries
 
     nsresult portParseError;
     nsCAutoString portString(Substring(host, portIndex+1));
     port = portString.ToInteger(&portParseError);
-    if (portParseError)
+    if (NS_FAILED(portParseError))
       continue; // Ignore broken entries
 
     host.Truncate(portIndex);
     
     AddEntryToList(host, port, 
                    nullptr, // don't have the cert
                    false, // not temporary
                    algo_string, fingerprint, bits, db_key);
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -107,20 +107,17 @@ Tester.prototype = {
   },
 
   waitForWindowsState: function Tester_waitForWindowsState(aCallback) {
     let timedOut = this.currentTest && this.currentTest.timedOut;
     let baseMsg = timedOut ? "Found a {elt} after previous test timed out"
                            : this.currentTest ? "Found an unexpected {elt} at the end of test run"
                                               : "Found an unexpected {elt}";
 
-    if (gConfig.testRoot == "browser" &&
-        this.currentTest &&
-        window.gBrowser &&
-        gBrowser.tabs.length > 1) {
+    if (this.currentTest && window.gBrowser && gBrowser.tabs.length > 1) {
       while (gBrowser.tabs.length > 1) {
         let lastTab = gBrowser.tabContainer.lastChild;
         let msg = baseMsg.replace("{elt}", "tab") +
                   ": " + lastTab.linkedBrowser.currentURI.spec;
         this.currentTest.addResult(new testResult(false, msg, "", false));
         gBrowser.removeTab(lastTab);
       }
     }
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -631,17 +631,17 @@ class Mochitest(object):
         self.urlOpts.append("testname=%s" % ("/").join([self.TEST_PATH, options.testPath]))
       if options.testManifest:
         self.urlOpts.append("testManifest=%s" % options.testManifest)
         if hasattr(options, 'runOnly') and options.runOnly:
           self.urlOpts.append("runOnly=true")
         else:
           self.urlOpts.append("runOnly=false")
       if options.failureFile:
-        self.urlOpts.append("failureFile=%s" % options.failureFile)
+        self.urlOpts.append("failureFile=%s" % self.getFullPath(options.failureFile))
 
   def cleanup(self, manifest, options):
     """ remove temporary files and profile """
     os.remove(manifest)
     shutil.rmtree(options.profilePath)
 
   def startVMwareRecording(self, options):
     """ starts recording inside VMware VM using the recording helper dll """
--- a/testing/mochitest/tests/SimpleTest/setup.js
+++ b/testing/mochitest/tests/SimpleTest/setup.js
@@ -82,22 +82,22 @@ if (params.repeat) {
 } 
 
 // closeWhenDone tells us to close the browser when complete
 if (params.closeWhenDone) {
   TestRunner.onComplete = SpecialPowers.quit;
 }
 
 if (params.failureFile) {
-  TestRunner.setFailureFile(params.failureFile);
+  TestRunner.setFailureFile(params.failureFile[0]);
 }
 
 // logFile to write our results
 if (params.logFile) {
-  var spl = new SpecialPowersLogger(params.logFile);
+  var spl = new SpecialPowersLogger(params.logFile[0]);
   TestRunner.logger.addListener("mozLogger", fileLevel + "", spl.getLogCallback());
 }
 
 // if we get a quiet param, don't log to the console
 if (!params.quiet) {
   function dumpListener(msg) {
     dump(msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n");
   }
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -176,18 +176,18 @@ HISTOGRAM_ENUMERATED_VALUES(SPDY_VERSION
 HISTOGRAM(SPDY_PARALLEL_STREAMS, 1, 1000, 50, EXPONENTIAL, "SPDY: Streams concurrent active per connection")
 HISTOGRAM(SPDY_REQUEST_PER_CONN, 1, 1000, 50, EXPONENTIAL,  "SPDY: Streams created per connection")
 HISTOGRAM(SPDY_SERVER_INITIATED_STREAMS, 1, 100000, 250, EXPONENTIAL,  "SPDY: Streams recevied per connection")
 HISTOGRAM(SPDY_CHUNK_RECVD, 1, 1000, 100, EXPONENTIAL,  "SPDY: Recvd Chunk Size (rounded to KB)")
 HISTOGRAM(SPDY_SYN_SIZE, 20, 20000, 50, EXPONENTIAL,  "SPDY: SYN Frame Header Size")
 HISTOGRAM(SPDY_SYN_RATIO, 1, 99, 20, LINEAR,  "SPDY: SYN Frame Header Ratio (lower better)")
 HISTOGRAM(SPDY_SYN_REPLY_SIZE, 16, 20000, 50, EXPONENTIAL,  "SPDY: SYN Reply Header Size")
 HISTOGRAM(SPDY_SYN_REPLY_RATIO, 1, 99, 20, LINEAR,  "SPDY: SYN Reply Header Ratio (lower better)")
-HISTOGRAM(SPDY_NPN_CONNECT, 0, 1, 2, BOOLEAN,  "SPDY: NPN Negotiated")
-HISTOGRAM(SPDY_NPN_JOIN, 0, 1, 2, BOOLEAN,  "SPDY: Coalesce Succeeded")
+HISTOGRAM_BOOLEAN(SPDY_NPN_CONNECT,  "SPDY: NPN Negotiated")
+HISTOGRAM_BOOLEAN(SPDY_NPN_JOIN,  "SPDY: Coalesce Succeeded")
 HISTOGRAM(SPDY_KBREAD_PER_CONN, 1, 3000, 50, EXPONENTIAL, "SPDY: KB read per connection")
 HISTOGRAM(SPDY_PING_EXPERIMENT_PASS, 10, 355, 64, LINEAR, "SPDY: Ping Interval Passed")
 HISTOGRAM(SPDY_PING_EXPERIMENT_FAIL, 10, 355, 64, LINEAR, "SPDY: Ping Interval Failed")
 
 HISTOGRAM(SPDY_SETTINGS_UL_BW, 1, 10000, 100, EXPONENTIAL,  "SPDY: Settings Upload Bandwidth")
 HISTOGRAM(SPDY_SETTINGS_DL_BW, 1, 10000, 100, EXPONENTIAL,  "SPDY: Settings Download Bandwidth")
 HISTOGRAM(SPDY_SETTINGS_RTT, 1, 1000, 100, EXPONENTIAL,  "SPDY: Settings RTT")
 HISTOGRAM(SPDY_SETTINGS_MAX_STREAMS, 1, 5000, 100, EXPONENTIAL,  "SPDY: Settings Max Streams parameter")
@@ -420,17 +420,17 @@ HISTOGRAM(FX_APP_MENU_OPEN_MS, 1, 1000, 
 HISTOGRAM(FX_BOOKMARKS_TOOLBAR_INIT_MS, 50, 5000, 10, EXPONENTIAL, "Firefox: Time to initialize the bookmarks toolbar view (ms)")
 HISTOGRAM(FX_NEW_WINDOW_MS, 1, 10000, 20, EXPONENTIAL, "Firefox: Time taken to open a new browser window (ms)")
 
 /**
  * Thumbnail Service telemetry.
  */
 HISTOGRAM(FX_THUMBNAILS_CAPTURE_TIME_MS, 1, 500, 15, EXPONENTIAL, "THUMBNAILS: Time (ms) it takes to capture a thumbnail")
 HISTOGRAM(FX_THUMBNAILS_STORE_TIME_MS, 1, 500, 15, EXPONENTIAL, "THUMBNAILS: Time (ms) it takes to store a thumbnail in the cache")
-HISTOGRAM(FX_THUMBNAILS_HIT_OR_MISS, 0, 1, 2, BOOLEAN, "THUMBNAILS: Thumbnail found")
+HISTOGRAM_BOOLEAN(FX_THUMBNAILS_HIT_OR_MISS, "THUMBNAILS: Thumbnail found")
 
 
 /*
  * Widget telemetry.
  */
 HISTOGRAM(EVENTLOOP_UI_LAG_EXP_MS, 50, 60000, 20, EXPONENTIAL, "Widget: Time it takes for the message before a UI message (ms)")
 
 /**
@@ -497,17 +497,17 @@ HISTOGRAM_FLAG(TELEMETRY_TEST_FLAG, "a t
  * Startup Crash Detection
  */
 HISTOGRAM_FLAG(STARTUP_CRASH_DETECTED, "Whether there was a crash during the last startup")
 HISTOGRAM_ENUMERATED_VALUES(SAFE_MODE_USAGE, 3, "Whether the user is in safe mode (No, Yes, Forced)")
 
 /**
  * New Tab Page telemetry.
  */
-HISTOGRAM(NEWTAB_PAGE_ENABLED, 0, 1, 2, BOOLEAN, "New tab page is enabled.")
+HISTOGRAM_BOOLEAN(NEWTAB_PAGE_ENABLED, "New tab page is enabled.")
 HISTOGRAM(NEWTAB_PAGE_PINNED_SITES_COUNT, 1, 9, 10, EXPONENTIAL, "Number of pinned sites on the new tab page.")
 HISTOGRAM(NEWTAB_PAGE_BLOCKED_SITES_COUNT, 1, 100, 10, EXPONENTIAL, "Number of sites blocked from the new tab page.")
 
 /**
  * Panorama telemetry.
  */
 HISTOGRAM(PANORAMA_INITIALIZATION_TIME_MS, 1, 10000, 15, EXPONENTIAL, "Time it takes to initialize Panorama (ms)")
 HISTOGRAM(PANORAMA_GROUPS_COUNT, 1, 25, 15, EXPONENTIAL, "Number of groups in Panorama")
--- a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
@@ -342,17 +342,17 @@ nsUrlClassifierStreamUpdater::UpdateErro
   LOG(("nsUrlClassifierStreamUpdater::UpdateError [this=%p]", this));
 
   // DownloadDone() clears mUpdateErrorCallback, so we save it off here.
   nsCOMPtr<nsIUrlClassifierCallback> errorCallback = mDownloadError ? nullptr : mUpdateErrorCallback.get();
 
   DownloadDone();
 
   nsCAutoString strResult;
-  strResult.AppendInt(result);
+  strResult.AppendInt(static_cast<PRUint32>(result));
   if (errorCallback) {
     errorCallback->HandleEvent(strResult);
   }
 
   return NS_OK;
 }
 
 nsresult
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -204,22 +204,27 @@ static const int kOOMAllocationSizeParam
 static const char kAvailablePageFileParameter[] = "AvailablePageFile=";
 static const int kAvailablePageFileParameterLen =
   sizeof(kAvailablePageFileParameter)-1;
 
 static const char kAvailablePhysicalMemoryParameter[] = "AvailablePhysicalMemory=";
 static const int kAvailablePhysicalMemoryParameterLen =
   sizeof(kAvailablePhysicalMemoryParameter)-1;
 
+static const char kIsGarbageCollectingParameter[] = "IsGarbageCollecting=";
+static const int kIsGarbageCollectingParameterLen =
+  sizeof(kIsGarbageCollectingParameter)-1;
+
 // this holds additional data sent via the API
 static Mutex* crashReporterAPILock;
 static Mutex* notesFieldLock;
 static AnnotationTable* crashReporterAPIData_Hash;
 static nsCString* crashReporterAPIData = nullptr;
 static nsCString* notesField = nullptr;
+static bool isGarbageCollecting;
 
 // OOP crash reporting
 static CrashGenerationServer* crashServer; // chrome process has this
 
 #  if defined(XP_WIN) || defined(XP_MACOSX)
 // If crash reporting is disabled, we hand out this "null" pipe to the
 // child process and don't attempt to connect to a parent server.
 static const char kNullNotifyPipe[] = "-";
@@ -521,16 +526,22 @@ bool MinidumpCallback(const XP_CHAR* dum
       WriteFile(hFile, "\n", 1, &nBytes, NULL);
       if (timeSinceLastCrash != 0) {
         WriteFile(hFile, kTimeSinceLastCrashParameter,
                   kTimeSinceLastCrashParameterLen, &nBytes, NULL);
         WriteFile(hFile, timeSinceLastCrashString, timeSinceLastCrashStringLen,
                   &nBytes, NULL);
         WriteFile(hFile, "\n", 1, &nBytes, NULL);
       }
+      if (isGarbageCollecting) {
+        WriteFile(hFile, kIsGarbageCollectingParameter, kIsGarbageCollectingParameterLen,
+                  &nBytes, NULL);
+        WriteFile(hFile, isGarbageCollecting ? "1" : "0", 1, &nBytes, NULL);
+        WriteFile(hFile, "\n", 1, &nBytes, NULL);
+      }
 
       // Try to get some information about memory.
       MEMORYSTATUSEX statex;
       statex.dwLength = sizeof(statex);
       if (GlobalMemoryStatusEx(&statex)) {
         char buffer[128];
         int bufferLen;
 
@@ -606,16 +617,21 @@ bool MinidumpCallback(const XP_CHAR* dum
       ignored = sys_write(fd, "\n", 1);
       if (timeSinceLastCrash != 0) {
         ignored = sys_write(fd, kTimeSinceLastCrashParameter,
                         kTimeSinceLastCrashParameterLen);
         ignored = sys_write(fd, timeSinceLastCrashString,
                         timeSinceLastCrashStringLen);
         ignored = sys_write(fd, "\n", 1);
       }
+      if (isGarbageCollecting) {
+        ignored = sys_write(fd, kIsGarbageCollectingParameter, kIsGarbageCollectingParameterLen);
+        ignored = sys_write(fd, isGarbageCollecting ? "1" : "0", 1);
+        ignored = sys_write(fd, "\n", 1);
+      }
       if (oomAllocationSizeBufferLen) {
         sys_write(fd, kOOMAllocationSizeParameter,
                   kOOMAllocationSizeParameterLen);
         sys_write(fd, oomAllocationSizeBuffer, oomAllocationSizeBufferLen);
         sys_write(fd, "\n", 1);
       }        
       sys_close(fd);
     }
@@ -1381,16 +1397,26 @@ nsresult AnnotateCrashReport(const nsACS
   // now rebuild the file contents
   crashReporterAPIData->Truncate(0);
   crashReporterAPIData_Hash->EnumerateRead(EnumerateEntries,
                                            crashReporterAPIData);
 
   return NS_OK;
 }
 
+nsresult SetGarbageCollecting(bool collecting)
+{
+  if (!GetEnabled())
+    return NS_ERROR_NOT_INITIALIZED;
+
+  isGarbageCollecting = collecting;
+
+  return NS_OK;
+}
+
 nsresult AppendAppNotesToCrashReport(const nsACString& data)
 {
   if (!GetEnabled())
     return NS_ERROR_NOT_INITIALIZED;
 
   if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
     return NS_ERROR_INVALID_ARG;
 
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -35,16 +35,18 @@ nsresult SetMinidumpPath(const nsAString
 
 
 // AnnotateCrashReport and AppendAppNotesToCrashReport may be called from any
 // thread in a chrome process, but may only be called from the main thread in
 // a content process.
 nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data);
 nsresult AppendAppNotesToCrashReport(const nsACString& data);
 
+nsresult SetGarbageCollecting(bool collecting);
+
 nsresult SetRestartArgs(int argc, char** argv);
 nsresult SetupExtraData(nsIFile* aAppDataDirectory,
                         const nsACString& aBuildID);
 bool GetLastRunCrashID(nsAString& id);
 
 // Registers an additional memory region to be included in the minidump
 nsresult RegisterAppMemory(void* ptr, size_t length);
 nsresult UnregisterAppMemory(void* ptr);
--- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
@@ -338,17 +338,17 @@ static bool HostIgnoredByProxy(const nsA
   aIgnore.BeginReading(slash);
   aIgnore.EndReading(end);
   if (FindCharInReadable('/', slash, end)) {
     ++slash;
     nsDependentCSubstring maskStr(slash, end);
     nsCAutoString maskStr2(maskStr);
     nsresult err;
     mask = maskStr2.ToInteger(&err);
-    if (err != 0) {
+    if (NS_FAILED(err)) {
       mask = 128;
     }
     --slash;
   } else {
     slash = end;
   }
 
   nsDependentCSubstring ignoreStripped(start, slash);
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -418,17 +418,17 @@ XRE_InitChildProcess(int aArgc,
   }
 #endif
 
   base::AtExitManager exitManager;
   NotificationService notificationService;
 
   NS_LogInit();
 
-  int rv = XRE_InitCommandLine(aArgc, aArgv);
+  nsresult rv = XRE_InitCommandLine(aArgc, aArgv);
   if (NS_FAILED(rv)) {
     NS_LogTerm();
     return NS_ERROR_FAILURE;
   }
 
   MessageLoop::Type uiLoopType;
   switch (aProcess) {
   case GeckoProcessType_Content:
@@ -542,17 +542,17 @@ XRE_InitParentProcess(int aArgc,
   NS_ENSURE_ARG_MIN(aArgc, 1);
   NS_ENSURE_ARG_POINTER(aArgv);
   NS_ENSURE_ARG_POINTER(aArgv[0]);
 
   ScopedXREEmbed embed;
 
   gArgc = aArgc;
   gArgv = aArgv;
-  int rv = XRE_InitCommandLine(gArgc, gArgv);
+  nsresult rv = XRE_InitCommandLine(gArgc, gArgv);
   if (NS_FAILED(rv))
       return NS_ERROR_FAILURE;
 
   {
     embed.Start();
 
     nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
     NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -1138,18 +1138,18 @@ NS_IMETHODIMP nsDocLoader::OnStatus(nsIR
   //
   // Fire progress notifications out to any registered nsIWebProgressListeners
   //
   if (aStatus) {
     // Remember the current status for this request
     nsRequestInfo *info;
     info = GetRequestInfo(aRequest);
     if (info) {
-      bool uploading = (aStatus == nsITransport::STATUS_WRITING ||
-                          aStatus == nsISocketTransport::STATUS_SENDING_TO);
+      bool uploading = (aStatus == NS_NET_STATUS_WRITING ||
+                        aStatus == NS_NET_STATUS_SENDING_TO);
       // If switching from uploading to downloading (or vice versa), then we
       // need to reset our progress counts.  This is designed with HTTP form
       // submission in mind, where an upload is performed followed by download
       // of possibly several documents.
       if (info->mUploading != uploading) {
         mCurrentSelfProgress  = mMaxSelfProgress  = LL_ZERO;
         mCurrentTotalProgress = mMaxTotalProgress = LL_ZERO;
         mCompletedTotalProgress = LL_ZERO;
--- a/view/public/nsIView.h
+++ b/view/public/nsIView.h
@@ -12,32 +12,31 @@
 #include "nsPoint.h"
 #include "nsNativeWidget.h"
 #include "nsIWidget.h"
 #include "nsWidgetInitData.h"
 
 class nsIViewManager;
 class nsViewManager;
 class nsView;
-class nsWeakView;
 class nsIWidget;
 class nsIFrame;
 
 // Enumerated type to indicate the visibility of a layer.
 // hide - the layer is not shown.
 // show - the layer is shown irrespective of the visibility of 
 //        the layer's parent.
 enum nsViewVisibility {
   nsViewVisibility_kHide = 0,
   nsViewVisibility_kShow = 1
 };
 
 #define NS_IVIEW_IID    \
-  { 0x697948d2, 0x3f10, 0x407d, \
-    { 0xb8, 0x94, 0x9f, 0x36, 0xd2, 0x11, 0xdb, 0xf1 } }
+  { 0xa4577c1d, 0xbc80, 0x444c, \
+    { 0xb0, 0x9d, 0x5b, 0xef, 0x94, 0x7c, 0x43, 0x31 } }
 
 // Public view flags
 
 // Indicates that the view is using auto z-indexing
 #define NS_VIEW_FLAG_AUTO_ZINDEX          0x0004
 
 // Indicates that the view is a floating view.
 #define NS_VIEW_FLAG_FLOATING             0x0008
@@ -308,17 +307,17 @@ public:
    */
   bool HasWidget() const { return mWindow != nullptr; }
 
   /**
    * Make aWidget direct its events to this view.
    * The caller must call DetachWidgetEventHandler before this view
    * is destroyed.
    */
-  EVENT_CALLBACK AttachWidgetEventHandler(nsIWidget* aWidget);
+  void AttachWidgetEventHandler(nsIWidget* aWidget);
   /**
    * Stop aWidget directing its events to this view.
    */
   void DetachWidgetEventHandler(nsIWidget* aWidget);
 
 #ifdef DEBUG
   /**
    * Output debug info to FILE
@@ -331,94 +330,47 @@ public:
 
   /**
    * @result true iff this is the root view for its view manager
    */
   bool IsRoot() const;
 
   virtual bool ExternalIsRoot() const;
 
-  void SetDeletionObserver(nsWeakView* aDeletionObserver);
-
   nsIntRect CalcWidgetBounds(nsWindowType aType);
 
   bool IsEffectivelyVisible();
 
   // This is an app unit offset to add when converting view coordinates to
   // widget coordinates.  It is the offset in view coordinates from widget
   // origin (unlike views, widgets can't extend above or to the left of their
   // origin) to view origin expressed in appunits of this.
   nsPoint ViewToWidgetOffset() const { return mViewToWidgetOffset; }
 
 protected:
-  friend class nsWeakView;
   nsViewManager     *mViewManager;
   nsView            *mParent;
   nsIWidget         *mWindow;
   nsView            *mNextSibling;
   nsView            *mFirstChild;
   nsIFrame          *mFrame;
   PRInt32           mZIndex;
   nsViewVisibility  mVis;
   // position relative our parent view origin but in our appunits
   nscoord           mPosX, mPosY;
   // relative to parent, but in our appunits
   nsRect            mDimBounds;
   // in our appunits
   nsPoint           mViewToWidgetOffset;
   float             mOpacity;
   PRUint32          mVFlags;
-  nsWeakView*       mDeletionObserver;
   bool              mWidgetIsTopLevel;
 
   virtual ~nsIView() {}
 
 private:
   nsView* Impl();
   const nsView* Impl() const;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIView, NS_IVIEW_IID)
 
-// nsWeakViews must *not* be used in heap!
-class nsWeakView
-{
-public:
-  nsWeakView(nsIView* aView) : mPrev(nullptr), mView(aView)
-  {
-    if (mView) {
-      mView->SetDeletionObserver(this);
-    }
-  }
-
-  ~nsWeakView()
-  {
-    if (mView) {
-      NS_ASSERTION(mView->mDeletionObserver == this,
-                   "nsWeakViews deleted in wrong order!");
-      // Clear deletion observer temporarily.
-      mView->SetDeletionObserver(nullptr);
-      // Put back the previous deletion observer.
-      mView->SetDeletionObserver(mPrev);
-    }
-  }
-
-  bool IsAlive() { return !!mView; }
-
-  nsIView* GetView() { return mView; }
-
-  void SetPrevious(nsWeakView* aWeakView) { mPrev = aWeakView; }
-
-  void Clear()
-  {
-    if (mPrev) {
-      mPrev->Clear();
-    }
-    mView = nullptr;
-  }
-private:
-  static void* operator new(size_t) CPP_THROW_NEW { return 0; }
-  static void operator delete(void*, size_t) {}
-  nsWeakView* mPrev;
-  nsIView*    mView;
-};
-
 #endif
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -2,184 +2,37 @@
 /* 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 "nsView.h"
 #include "nsIWidget.h"
 #include "nsWidgetsCID.h"
 #include "nsViewManager.h"
+#include "nsIFrame.h"
 #include "nsGUIEvent.h"
 #include "nsIComponentManager.h"
 #include "nsGfxCIID.h"
 #include "nsIInterfaceRequestor.h"
 #include "mozilla/Attributes.h"
-
-//mmptemp
-
-static nsEventStatus HandleEvent(nsGUIEvent *aEvent);
-
-
-//#define SHOW_VIEW_BORDERS
-
-#define VIEW_WRAPPER_IID \
-  { 0xbf4e1841, 0xe9ec, 0x47f2, \
-    { 0xb4, 0x77, 0x0f, 0xf6, 0x0f, 0x5a, 0xac, 0xbd } }
-
-/**
- * nsISupports-derived helper class that allows to store and get a view
- */
-class ViewWrapper MOZ_FINAL : public nsIInterfaceRequestor
-{
-  public:
-    NS_DECLARE_STATIC_IID_ACCESSOR(VIEW_WRAPPER_IID)
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIINTERFACEREQUESTOR
-
-    ViewWrapper(nsView* aView) : mView(aView) {}
-
-    nsView* GetView() { return mView; }
-  private:
-    nsView* mView;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(ViewWrapper, VIEW_WRAPPER_IID)
-
-NS_IMPL_ADDREF(ViewWrapper)
-NS_IMPL_RELEASE(ViewWrapper)
-#ifndef DEBUG
-NS_IMPL_QUERY_INTERFACE2(ViewWrapper, ViewWrapper, nsIInterfaceRequestor)
-
-#else
-NS_IMETHODIMP ViewWrapper::QueryInterface(REFNSIID aIID, void** aInstancePtr)
-{
-  NS_ENSURE_ARG_POINTER(aInstancePtr);
-
-  NS_ASSERTION(!aIID.Equals(NS_GET_IID(nsIView)),
-               "Someone expects a viewwrapper to be a view!");
-  
-  *aInstancePtr = nullptr;
-  
-  if (aIID.Equals(NS_GET_IID(nsISupports))) {
-    *aInstancePtr = static_cast<nsISupports*>(this);
-  }
-  else if (aIID.Equals(NS_GET_IID(ViewWrapper))) {
-    *aInstancePtr = this;
-  }
-  else if (aIID.Equals(NS_GET_IID(nsIInterfaceRequestor))) {
-    *aInstancePtr = this;
-  }
-
-
-  if (*aInstancePtr) {
-    AddRef();
-    return NS_OK;
-  }
-
-  return NS_NOINTERFACE;
-}
-#endif
-
-NS_IMETHODIMP ViewWrapper::GetInterface(REFNSIID aIID, void** aInstancePtr)
-{
-  if (aIID.Equals(NS_GET_IID(nsIView))) {
-    *aInstancePtr = mView;
-    return NS_OK;
-  }
-  return QueryInterface(aIID, aInstancePtr);
-}
-
-/**
- * Given a widget, returns the stored ViewWrapper on it, or NULL if no
- * ViewWrapper is there.
- */
-static ViewWrapper* GetWrapperFor(nsIWidget* aWidget)
-{
-  // The widget's client data points back to the owning view
-  if (aWidget) {
-    void* clientData;
-    aWidget->GetClientData(clientData);
-    nsISupports* data = (nsISupports*)clientData;
-    
-    if (data) {
-      ViewWrapper* wrapper;
-      CallQueryInterface(data, &wrapper);
-      // Give a weak reference to the caller. There will still be at least one
-      // reference left, since the wrapper was addrefed when set on the widget.
-      if (wrapper)
-        wrapper->Release();
-      return wrapper;
-    }
-  }
-  return nullptr;
-}
-
-// Main events handler
-static nsEventStatus HandleEvent(nsGUIEvent *aEvent)
-{
-#if 0
-  printf(" %d %d %d (%d,%d) \n", aEvent->widget, aEvent->message);
-#endif
-  nsEventStatus result = nsEventStatus_eIgnore;
-  nsView *view = nsView::GetViewFor(aEvent->widget);
-
-  if (view)
-  {
-    nsCOMPtr<nsIViewManager> vm = view->GetViewManager();
-    vm->DispatchEvent(aEvent, view, &result);
-  }
-
-  return result;
-}
-
-// Attached widget event helpers
-static ViewWrapper* GetAttachedWrapperFor(nsIWidget* aWidget)
-{
-  NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
-  return aWidget->GetAttachedViewPtr();
-}
-
-static nsView* GetAttachedViewFor(nsIWidget* aWidget)
-{           
-  NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
-
-  ViewWrapper* wrapper = GetAttachedWrapperFor(aWidget);
-  if (!wrapper)
-    return nullptr;
-  return wrapper->GetView();
-}
-
-// event handler
-static nsEventStatus AttachedHandleEvent(nsGUIEvent *aEvent)
-{ 
-  nsEventStatus result = nsEventStatus_eIgnore;
-  nsView *view = GetAttachedViewFor(aEvent->widget);
-
-  if (view)
-  {
-    nsCOMPtr<nsIViewManager> vm = view->GetViewManager();
-    vm->DispatchEvent(aEvent, view, &result);
-  }
-
-  return result;
-}
+#include "nsXULPopupManager.h"
+#include "nsIWidgetListener.h"
 
 nsView::nsView(nsViewManager* aViewManager, nsViewVisibility aVisibility)
 {
   MOZ_COUNT_CTOR(nsView);
 
   mVis = aVisibility;
   // Views should be transparent by default. Not being transparent is
   // a promise that the view will paint all its pixels opaquely. Views
   // should make this promise explicitly by calling
   // SetViewContentTransparency.
   mVFlags = 0;
   mViewManager = aViewManager;
   mDirtyRegion = nullptr;
-  mDeletionObserver = nullptr;
   mWidgetIsTopLevel = false;
 }
 
 void nsView::DropMouseGrabbing()
 {
   nsIPresShell* presShell = mViewManager->GetPresShell();
   if (presShell)
     presShell->ClearMouseCaptureOnView(this);
@@ -231,42 +84,31 @@ nsView::~nsView()
   {
     mParent->RemoveChild(this);
   }
 
   // Destroy and release the widget
   DestroyWidget();
 
   delete mDirtyRegion;
-
-  if (mDeletionObserver) {
-    mDeletionObserver->Clear();
-  }
 }
 
 void nsView::DestroyWidget()
 {
   if (mWindow)
   {
-    // Release memory for the view wrapper
-    ViewWrapper* wrapper = GetWrapperFor(mWindow);
-    NS_IF_RELEASE(wrapper);
-
     // If we are not attached to a base window, we're going to tear down our
     // widget here. However, if we're attached to somebody elses widget, we
     // want to leave the widget alone: don't reset the client data or call
     // Destroy. Just clear our event view ptr and free our reference to it. 
     if (mWidgetIsTopLevel) {
-      ViewWrapper* wrapper = GetAttachedWrapperFor(mWindow);
-      NS_IF_RELEASE(wrapper);
-
-      mWindow->SetAttachedViewPtr(nullptr);
+      mWindow->SetAttachedWidgetListener(nullptr);
     }
     else {
-      mWindow->SetClientData(nullptr);
+      mWindow->SetWidgetListener(nullptr);
       mWindow->Destroy();
     }
 
     NS_RELEASE(mWindow);
   }
 }
 
 nsresult nsView::QueryInterface(const nsIID& aIID, void** aInstancePtr)
@@ -284,30 +126,28 @@ nsresult nsView::QueryInterface(const ns
     *aInstancePtr = (void*)(nsIView*)this;
     return NS_OK;
   }
 
   return NS_NOINTERFACE;
 }
 
 nsIView* nsIView::GetViewFor(nsIWidget* aWidget)
-{           
+{
   NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
 
-  ViewWrapper* wrapper = GetWrapperFor(aWidget);
-
-  if (!wrapper) {
-    wrapper = GetAttachedWrapperFor(aWidget);
+  nsIWidgetListener* listener = aWidget->GetWidgetListener();
+  if (listener) {
+    nsIView* view = listener->GetView();
+    if (view)
+      return view;
   }
 
-  if (wrapper) {
-    return wrapper->GetView();
-  }
-
-  return nullptr;
+  listener = aWidget->GetAttachedWidgetListener();
+  return listener ? listener->GetView() : nullptr;
 }
 
 void nsIView::Destroy()
 {
   delete this;
 }
 
 void nsView::SetPosition(nscoord aX, nscoord aY)
@@ -690,18 +530,17 @@ nsresult nsView::CreateWidget(nsWidgetIn
     GetParent() ? GetParent()->GetNearestWidget(nullptr) : nullptr;
   if (!parentWidget) {
     NS_ERROR("nsView::CreateWidget without suitable parent widget??");
     return NS_ERROR_FAILURE;
   }
 
   // XXX: using aForceUseIWidgetParent=true to preserve previous
   // semantics.  It's not clear that it's actually needed.
-  mWindow = parentWidget->CreateChild(trect, ::HandleEvent,
-                                      dx, aWidgetInitData,
+  mWindow = parentWidget->CreateChild(trect, dx, aWidgetInitData,
                                       true).get();
   if (!mWindow) {
     return NS_ERROR_FAILURE;
   }
  
   InitializeWindow(aEnableDragDrop, aResetVisibility);
 
   return NS_OK;
@@ -722,18 +561,17 @@ nsresult nsView::CreateWidgetForParent(n
   aWidgetInitData = aWidgetInitData ? aWidgetInitData : &defaultInitData;
 
   nsIntRect trect = CalcWidgetBounds(aWidgetInitData->mWindowType);
 
   nsRefPtr<nsDeviceContext> dx;
   mViewManager->GetDeviceContext(*getter_AddRefs(dx));
 
   mWindow =
-    aParentWidget->CreateChild(trect, ::HandleEvent,
-                               dx, aWidgetInitData).get();
+    aParentWidget->CreateChild(trect, dx, aWidgetInitData).get();
   if (!mWindow) {
     return NS_ERROR_FAILURE;
   }
 
   InitializeWindow(aEnableDragDrop, aResetVisibility);
 
   return NS_OK;
 }
@@ -755,50 +593,46 @@ nsresult nsView::CreateWidgetForPopup(ns
 
   // XXX/cjones: having these two separate creation cases seems ... um
   // ... unnecessary, but it's the way the old code did it.  Please
   // unify them by first finding a suitable parent nsIWidget, then
   // getting rid of aForceUseIWidgetParent.
   if (aParentWidget) {
     // XXX: using aForceUseIWidgetParent=true to preserve previous
     // semantics.  It's not clear that it's actually needed.
-    mWindow = aParentWidget->CreateChild(trect, ::HandleEvent,
-                                         dx, aWidgetInitData,
+    mWindow = aParentWidget->CreateChild(trect, dx, aWidgetInitData,
                                          true).get();
   }
   else {
     nsIWidget* nearestParent = GetParent() ? GetParent()->GetNearestWidget(nullptr)
                                            : nullptr;
     if (!nearestParent) {
       // Without a parent, we can't make a popup.  This can happen
       // when printing
       return NS_ERROR_FAILURE;
     }
 
     mWindow =
-      nearestParent->CreateChild(trect, ::HandleEvent,
-                                 dx, aWidgetInitData).get();
+      nearestParent->CreateChild(trect, dx, aWidgetInitData).get();
   }
   if (!mWindow) {
     return NS_ERROR_FAILURE;
   }
 
   InitializeWindow(aEnableDragDrop, aResetVisibility);
 
   return NS_OK;
 }
 
 void
 nsView::InitializeWindow(bool aEnableDragDrop, bool aResetVisibility)
 {
   NS_ABORT_IF_FALSE(mWindow, "Must have a window to initialize");
 
-  ViewWrapper* wrapper = new ViewWrapper(this);
-  NS_ADDREF(wrapper); // Will be released in ~nsView
-  mWindow->SetClientData(wrapper);
+  mWindow->SetWidgetListener(this);
 
   if (aEnableDragDrop) {
     mWindow->EnableDragDrop(true);
   }
       
   // propagate the z-index to the widget.
   UpdateNativeWidgetZIndexes(this, FindNonAutoZIndex(this));
 
@@ -810,37 +644,37 @@ nsView::InitializeWindow(bool aEnableDra
 }
 
 // Attach to a top level widget and start receiving mirrored events.
 nsresult nsIView::AttachToTopLevelWidget(nsIWidget* aWidget)
 {
   NS_PRECONDITION(nullptr != aWidget, "null widget ptr");
   /// XXXjimm This is a temporary workaround to an issue w/document
   // viewer (bug 513162).
-  nsIView *oldView = GetAttachedViewFor(aWidget);
-  if (oldView) {
-    oldView->DetachFromTopLevelWidget();
+  nsIWidgetListener* listener = aWidget->GetAttachedWidgetListener();
+  if (listener) {
+    nsIView *oldView = listener->GetView();
+    if (oldView) {
+      oldView->DetachFromTopLevelWidget();
+    }
   }
 
   nsRefPtr<nsDeviceContext> dx;
   mViewManager->GetDeviceContext(*getter_AddRefs(dx));
 
   // Note, the previous device context will be released. Detaching
   // will not restore the old one.
-  nsresult rv = aWidget->AttachViewToTopLevel(
-    nsIWidget::UsePuppetWidgets() ? ::HandleEvent : ::AttachedHandleEvent, dx);
+  nsresult rv = aWidget->AttachViewToTopLevel(!nsIWidget::UsePuppetWidgets(), dx);
   if (NS_FAILED(rv))
     return rv;
 
   mWindow = aWidget;
   NS_ADDREF(mWindow);
 
-  ViewWrapper* wrapper = new ViewWrapper(Impl());
-  NS_ADDREF(wrapper);
-  mWindow->SetAttachedViewPtr(wrapper);
+  mWindow->SetAttachedWidgetListener(Impl());
   mWindow->EnableDragDrop(true);
   mWidgetIsTopLevel = true;
 
   // Refresh the view bounds
   nsWindowType type;
   mWindow->GetWindowType(type);
   CalcWidgetBounds(type);
 
@@ -848,21 +682,17 @@ nsresult nsIView::AttachToTopLevelWidget
 }
 
 // Detach this view from an attached widget. 
 nsresult nsIView::DetachFromTopLevelWidget()
 {
   NS_PRECONDITION(mWidgetIsTopLevel, "Not attached currently!");
   NS_PRECONDITION(mWindow, "null mWindow for DetachFromTopLevelWidget!");
 
-  // Release memory for the view wrapper
-  ViewWrapper* wrapper = GetAttachedWrapperFor(mWindow);
-  NS_IF_RELEASE(wrapper);
-
-  mWindow->SetAttachedViewPtr(nullptr);
+  mWindow->SetAttachedWidgetListener(nullptr);
   NS_RELEASE(mWindow);
 
   mWidgetIsTopLevel = false;
   
   return NS_OK;
 }
 
 void nsView::SetZIndex(bool aAuto, PRInt32 aZIndex, bool aTopMost)
@@ -877,49 +707,39 @@ void nsView::SetZIndex(bool aAuto, PRInt
   }
 }
 
 void nsView::AssertNoWindow()
 {
   // XXX: it would be nice to make this a strong assert
   if (NS_UNLIKELY(mWindow)) {
     NS_ERROR("We already have a window for this view? BAD");
-    ViewWrapper* wrapper = GetWrapperFor(mWindow);
-    NS_IF_RELEASE(wrapper);
-    mWindow->SetClientData(nullptr);
+    mWindow->SetWidgetListener(nullptr);
     mWindow->Destroy();
     NS_RELEASE(mWindow);
   }
 }
 
 //
 // internal window creation functions
 //
-EVENT_CALLBACK nsIView::AttachWidgetEventHandler(nsIWidget* aWidget)
+void nsIView::AttachWidgetEventHandler(nsIWidget* aWidget)
 {
 #ifdef DEBUG
-  void* data = nullptr;
-  aWidget->GetClientData(data);
-  NS_ASSERTION(!data, "Already got client data");
+  NS_ASSERTION(!aWidget->GetWidgetListener(), "Already have a widget listener");
 #endif
 
-  ViewWrapper* wrapper = new ViewWrapper(Impl());
-  if (!wrapper)
-    return nullptr;
-  NS_ADDREF(wrapper); // Will be released in DetachWidgetEventHandler
-  aWidget->SetClientData(wrapper);
-  return ::HandleEvent;
+  aWidget->SetWidgetListener(Impl());
 }
 
 void nsIView::DetachWidgetEventHandler(nsIWidget* aWidget)
 {
-  ViewWrapper* wrapper = GetWrapperFor(aWidget);
-  NS_ASSERTION(!wrapper || wrapper->GetView() == this, "Wrong view");
-  NS_IF_RELEASE(wrapper);
-  aWidget->SetClientData(nullptr);
+  NS_ASSERTION(!aWidget->GetWidgetListener() ||
+               aWidget->GetWidgetListener()->GetView() == this, "Wrong view");
+  aWidget->SetWidgetListener(nullptr);
 }
 
 #ifdef DEBUG
 void nsIView::List(FILE* out, PRInt32 aIndent) const
 {
   PRInt32 i;
   for (i = aIndent; --i >= 0; ) fputs("  ", out);
   fprintf(out, "%p ", (void*)this);
@@ -1092,25 +912,16 @@ bool nsIView::IsRoot() const
   return mViewManager->GetRootViewImpl() == this;
 }
 
 bool nsIView::ExternalIsRoot() const
 {
   return nsIView::IsRoot();
 }
 
-void
-nsIView::SetDeletionObserver(nsWeakView* aDeletionObserver)
-{
-  if (mDeletionObserver && aDeletionObserver) {
-    aDeletionObserver->SetPrevious(mDeletionObserver);
-  }
-  mDeletionObserver = aDeletionObserver;
-}
-
 nsView*
 nsIView::Impl()
 {
   return static_cast<nsView*>(this);
 }
 
 const nsView*
 nsIView::Impl() const
@@ -1138,8 +949,115 @@ nsIView::ConvertFromParentCoords(nsPoint
   const nsView* parent = view->GetParent();
   if (parent) {
     aPt = aPt.ConvertAppUnits(parent->GetViewManager()->AppUnitsPerDevPixel(),
                               view->GetViewManager()->AppUnitsPerDevPixel());
   }
   aPt -= GetPosition();
   return aPt;
 }
+
+static bool
+IsPopupWidget(nsIWidget* aWidget)
+{
+  nsWindowType type;
+  aWidget->GetWindowType(type);
+  return (type == eWindowType_popup);
+}
+
+nsIPresShell*
+nsView::GetPresShell()
+{
+  return GetViewManager()->GetPresShell();
+}
+
+bool
+nsView::WindowMoved(nsIWidget* aWidget, PRInt32 x, PRInt32 y)
+{
+  nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+  if (pm && IsPopupWidget(aWidget)) {
+    pm->PopupMoved(mFrame, nsIntPoint(x, y));
+    return true;
+  }
+
+  return false;
+}
+
+bool
+nsView::WindowResized(nsIWidget* aWidget, PRInt32 aWidth, PRInt32 aHeight)
+{
+  // The root view may not be set if this is the resize associated with
+  // window creation
+  if (this == mViewManager->GetRootView()) {
+    nsRefPtr<nsDeviceContext> devContext;
+    mViewManager->GetDeviceContext(*getter_AddRefs(devContext));
+    PRInt32 p2a = devContext->AppUnitsPerDevPixel();
+    mViewManager->SetWindowDimensions(NSIntPixelsToAppUnits(aWidth, p2a),
+                                      NSIntPixelsToAppUnits(aHeight, p2a));
+    return true;
+  }
+  else if (IsPopupWidget(aWidget)) {
+    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+    if (pm) {
+      pm->PopupResized(mFrame, nsIntSize(aWidth, aHeight));
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool
+nsView::RequestWindowClose(nsIWidget* aWidget)
+{
+  if (mFrame && IsPopupWidget(aWidget) &&
+      mFrame->GetType() == nsGkAtoms::menuPopupFrame) {
+    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+    if (pm) {
+      pm->HidePopup(mFrame->GetContent(), false, true, false);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void
+nsView::WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint)
+{
+  mViewManager->WillPaintWindow(aWidget, aWillSendDidPaint);
+}
+
+bool
+nsView::PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion, bool aSentWillPaint, bool aWillSendDidPaint)
+{
+  nsCOMPtr<nsViewManager> vm = mViewManager;
+  return vm->PaintWindow(aWidget, aRegion, aSentWillPaint, aWillSendDidPaint);
+}
+
+void
+nsView::DidPaintWindow()
+{
+  mViewManager->DidPaintWindow();
+}
+
+nsEventStatus
+nsView::HandleEvent(nsGUIEvent* aEvent, bool aUseAttachedEvents)
+{
+  NS_PRECONDITION(nullptr != aEvent->widget, "null widget ptr");
+
+  nsEventStatus result = nsEventStatus_eIgnore;
+  nsIView* view;
+  if (aUseAttachedEvents) {
+    nsIWidgetListener* listener = aEvent->widget->GetAttachedWidgetListener();
+    view = listener ? listener->GetView() : nullptr;
+  }
+  else {
+    view = GetViewFor(aEvent->widget);
+  }
+
+  if (view) {
+    nsCOMPtr<nsIViewManager> vm = view->GetViewManager();
+    vm->DispatchEvent(aEvent, view, &result);
+  }
+
+  return result;
+}
--- a/view/src/nsView.h
+++ b/view/src/nsView.h
@@ -7,24 +7,26 @@
 #define nsView_h___
 
 #include "nsIView.h"
 #include "nsRegion.h"
 #include "nsRect.h"
 #include "nsCRT.h"
 #include "nsIFactory.h"
 #include "nsEvent.h"
+#include "nsIWidgetListener.h"
 #include <stdio.h>
 
 //mmptemp
 
 class nsIViewManager;
 class nsViewManager;
 
-class nsView : public nsIView
+class nsView : public nsIView,
+               public nsIWidgetListener
 {
 public:
   nsView(nsViewManager* aViewManager = nullptr,
          nsViewVisibility aVisibility = nsViewVisibility_kShow);
 
   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 
   NS_IMETHOD  QueryInterface(const nsIID& aIID, void** aInstancePtr);
@@ -150,16 +152,27 @@ public:
   void NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible);
 
   // Update the cached RootViewManager for all view manager descendents,
   // If the hierarchy is being removed, aViewManagerParent points to the view
   // manager for the hierarchy's old parent, and will have its mouse grab
   // released if it points to any view in this view hierarchy.
   void InvalidateHierarchy(nsViewManager *aViewManagerParent);
 
+  // nsIWidgetListener
+  virtual nsIPresShell* GetPresShell();
+  virtual nsIView* GetView() { return this; }
+  bool WindowMoved(nsIWidget* aWidget, PRInt32 x, PRInt32 y);
+  bool WindowResized(nsIWidget* aWidget, PRInt32 aWidth, PRInt32 aHeight);
+  bool RequestWindowClose(nsIWidget* aWidget);
+  void WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint);
+  bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion, bool aSentDidPaint, bool aWillSendDidPaint);
+  void DidPaintWindow();
+  nsEventStatus HandleEvent(nsGUIEvent* aEvent, bool aUseAttachedEvents);
+
   virtual ~nsView();
 
   nsPoint GetOffsetTo(const nsView* aOther) const;
   nsIWidget* GetNearestWidget(nsPoint* aOffset) const;
   nsPoint GetOffsetTo(const nsView* aOther, const PRInt32 aAPD) const;
   nsIWidget* GetNearestWidget(nsPoint* aOffset, const PRInt32 aAPD) const;
 
 protected:
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -640,298 +640,135 @@ void nsViewManager::InvalidateViews(nsVi
   // Invalidate all children as well.
   nsView* childView = aView->GetFirstChild();
   while (nullptr != childView)  {
     childView->GetViewManager()->InvalidateViews(childView);
     childView = childView->GetNextSibling();
   }
 }
 
-static bool
-IsViewForPopup(nsIView* aView)
+void nsViewManager::WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint)
 {
-  nsIWidget* widget = aView->GetWidget();
-  if (widget) {
-    nsWindowType type;
-    widget->GetWindowType(type);
-    return (type == eWindowType_popup);
+  if (IsRefreshDriverPaintingEnabled())
+    return;
+
+  if (!aWidget || !mContext)
+    return;
+
+  // If an ancestor widget was hidden and then shown, we could
+  // have a delayed resize to handle.
+  for (nsViewManager *vm = this; vm;
+       vm = vm->mRootView->GetParent()
+              ? vm->mRootView->GetParent()->GetViewManager()
+              : nullptr) {
+    if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
+        vm->mRootView->IsEffectivelyVisible() &&
+        mPresShell && mPresShell->IsVisible()) {
+      vm->FlushDelayedResize(true);
+      vm->InvalidateView(vm->mRootView);
+    }
+  }
+
+  // Flush things like reflows and plugin widget geometry updates by
+  // calling WillPaint on observer presShells.
+  nsRefPtr<nsViewManager> rootVM = RootViewManager();
+  if (mPresShell) {
+    rootVM->CallWillPaintOnObservers(aWillSendDidPaint);
+  }
+
+  // Flush view widget geometry updates and invalidations.
+  rootVM->ProcessPendingUpdates();
+}
+
+bool nsViewManager::PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion,
+                                bool aSentWillPaint, bool aWillSendDidPaint)
+ {
+  if (!aWidget || !mContext)
+    return false;
+
+  NS_ASSERTION(IsPaintingAllowed(),
+               "shouldn't be receiving paint events while painting is disallowed!");
+
+  if (!aSentWillPaint && !IsRefreshDriverPaintingEnabled()) {
+    WillPaintWindow(aWidget, aWillSendDidPaint);
+  }
+
+  // Get the view pointer here since NS_WILL_PAINT might have
+  // destroyed it during CallWillPaintOnObservers (bug 378273).
+  nsView* view = nsView::GetViewFor(aWidget);
+  if (view && !aRegion.IsEmpty()) {
+    Refresh(view, aRegion, aWillSendDidPaint);
   }
 
-  return false;
+  return true;
+}
+
+void nsViewManager::DidPaintWindow()
+{
+  if (!IsRefreshDriverPaintingEnabled()) {
+    mRootViewManager->CallDidPaintOnObserver();
+  }
 }
 
-NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
-                                           nsIView* aView, nsEventStatus *aStatus)
+nsresult nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsIView* aView, nsEventStatus* aStatus)
 {
-  NS_ASSERTION(!aView || static_cast<nsView*>(aView)->GetViewManager() == this,
-               "wrong view manager");
+  SAMPLE_LABEL("event", "nsViewManager::DispatchEvent");
+
+  if ((NS_IS_MOUSE_EVENT(aEvent) &&
+       // Ignore mouse events that we synthesize.
+       static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal &&
+       // Ignore mouse exit and enter (we'll get moves if the user
+       // is really moving the mouse) since we get them when we
+       // create and destroy widgets.
+       aEvent->message != NS_MOUSE_EXIT &&
+       aEvent->message != NS_MOUSE_ENTER) ||
+      NS_IS_KEY_EVENT(aEvent) ||
+      NS_IS_IME_EVENT(aEvent) ||
+      aEvent->message == NS_PLUGIN_INPUT_EVENT) {
+    gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
+  }
+
+  // Find the view whose coordinates system we're in.
+  nsIView* view = aView;
+  bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
+  if (dispatchUsingCoordinates) {
+    // Will dispatch using coordinates. Pretty bogus but it's consistent
+    // with what presshell does.
+    view = GetDisplayRootFor(view);
+  }
 
-  SAMPLE_LABEL("event", "nsViewManager::DispatchEvent");
+  // If the view has no frame, look for a view that does.
+  nsIFrame* frame = view->GetFrame();
+  if (!frame &&
+      (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
+       NS_IS_IME_RELATED_EVENT(aEvent) ||
+       NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) ||
+       aEvent->message == NS_PLUGIN_ACTIVATE ||
+       aEvent->message == NS_PLUGIN_FOCUS)) {
+    while (view && !view->GetFrame()) {
+      view = view->GetParent();
+    }
+
+    if (view) {
+      frame = view->GetFrame();
+    }
+  }
+
+  if (nullptr != frame) {
+    // Hold a refcount to the presshell. The continued existence of the
+    // presshell will delay deletion of this view hierarchy should the event
+    // want to cause its destruction in, say, some JavaScript event handler.
+    nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell();
+    if (shell) {
+      return shell->HandleEvent(frame, aEvent, false, aStatus);
+    }
+  }
 
   *aStatus = nsEventStatus_eIgnore;
 
-  switch(aEvent->message)
-    {
-    case NS_SIZE:
-      {
-        if (aView)
-          {
-            // client area dimensions are set on the view
-            nscoord width = ((nsSizeEvent*)aEvent)->windowSize->width;
-            nscoord height = ((nsSizeEvent*)aEvent)->windowSize->height;
-
-            // The root view may not be set if this is the resize associated with
-            // window creation
-
-            if (aView == mRootView)
-              {
-                PRInt32 p2a = AppUnitsPerDevPixel();
-                SetWindowDimensions(NSIntPixelsToAppUnits(width, p2a),
-                                    NSIntPixelsToAppUnits(height, p2a));
-                *aStatus = nsEventStatus_eConsumeNoDefault;
-              }
-            else if (IsViewForPopup(aView))
-              {
-                nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-                if (pm)
-                  {
-                    pm->PopupResized(aView->GetFrame(), nsIntSize(width, height));
-                    *aStatus = nsEventStatus_eConsumeNoDefault;
-                  }
-              }
-          }
-        }
-
-        break;
-
-    case NS_MOVE:
-      {
-        // A popup's parent view is the root view for the parent window, so when
-        // a popup moves, the popup's frame and view position must be updated
-        // to match.
-        if (aView && IsViewForPopup(aView))
-          {
-            nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-            if (pm)
-              {
-                pm->PopupMoved(aView->GetFrame(), aEvent->refPoint);
-                *aStatus = nsEventStatus_eConsumeNoDefault;
-              }
-          }
-        break;
-      }
-
-    case NS_DONESIZEMOVE:
-      {
-        if (mPresShell) {
-          nsPresContext* presContext = mPresShell->GetPresContext();
-          if (presContext) {
-            nsEventStateManager::ClearGlobalActiveContent(nullptr);
-          }
-
-        }
-
-        nsIPresShell::ClearMouseCapture(nullptr);
-      }
-      break;
-  
-    case NS_XUL_CLOSE:
-      {
-        // if this is a popup, make a request to hide it. Note that a popuphidden
-        // event listener may cancel the event and the popup will not be hidden.
-        nsIWidget* widget = aView->GetWidget();
-        if (widget) {
-          nsWindowType type;
-          widget->GetWindowType(type);
-          if (type == eWindowType_popup) {
-            nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-            if (pm) {
-              pm->HidePopup(aView->GetFrame());
-              *aStatus = nsEventStatus_eConsumeNoDefault;
-            }
-          }
-        }
-      }
-      break;
-
-    case NS_WILL_PAINT:
-      {
-        if (!aView || !mContext)
-          break;
-
-        *aStatus = nsEventStatus_eConsumeNoDefault;
-    
-        if (!IsRefreshDriverPaintingEnabled()) {
-
-          nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
-
-          NS_ASSERTION(static_cast<nsView*>(aView) ==
-                         nsView::GetViewFor(event->widget),
-                       "view/widget mismatch");
-
-          // If an ancestor widget was hidden and then shown, we could
-          // have a delayed resize to handle.
-          for (nsViewManager *vm = this; vm;
-               vm = vm->mRootView->GetParent()
-                      ? vm->mRootView->GetParent()->GetViewManager()
-                      : nullptr) {
-            if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
-                vm->mRootView->IsEffectivelyVisible() &&
-                mPresShell && mPresShell->IsVisible()) {
-              vm->FlushDelayedResize(true);
-              vm->InvalidateView(vm->mRootView);
-            }
-          }
-
-          // Flush things like reflows and plugin widget geometry updates by
-          // calling WillPaint on observer presShells.
-          nsRefPtr<nsViewManager> rootVM = RootViewManager();
-          if (mPresShell) {
-            rootVM->CallWillPaintOnObservers(event->willSendDidPaint);
-          }
-          // Flush view widget geometry updates and invalidations.
-          rootVM->ProcessPendingUpdates();
-        }
-      }
-      break;
-
-    case NS_PAINT:
-      {
-        if (!aView || !mContext)
-          break;
-
-        *aStatus = nsEventStatus_eConsumeNoDefault;
-        nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
-        nsView* view = static_cast<nsView*>(aView);
-        NS_ASSERTION(view == nsView::GetViewFor(event->widget),
-                     "view/widget mismatch");
-        NS_ASSERTION(IsPaintingAllowed(),
-                     "shouldn't be receiving paint events while painting is "
-                     "disallowed!");
-
-        if (!event->didSendWillPaint && !IsRefreshDriverPaintingEnabled()) {
-          // Send NS_WILL_PAINT event ourselves.
-          nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget);
-          willPaintEvent.willSendDidPaint = event->willSendDidPaint;
-          DispatchEvent(&willPaintEvent, view, aStatus);
-
-          // Get the view pointer again since NS_WILL_PAINT might have
-          // destroyed it during CallWillPaintOnObservers (bug 378273).
-          view = nsView::GetViewFor(event->widget);
-        }
-
-        if (!view || event->region.IsEmpty())
-          break;
-
-        // Paint.
-        Refresh(view, event->region, event->willSendDidPaint);
-
-        break;
-      }
-
-    case NS_DID_PAINT: {
-      if (!IsRefreshDriverPaintingEnabled()) {
-        nsRefPtr<nsViewManager> rootVM = RootViewManager();
-        rootVM->CallDidPaintOnObserver();
-      }
-      break;
-    }
-
-    case NS_CREATE:
-    case NS_DESTROY:
-    case NS_SETZLEVEL:
-      /* Don't pass these events through. Passing them through
-         causes performance problems on pages with lots of views/frames 
-         @see bug 112861 */
-      *aStatus = nsEventStatus_eConsumeNoDefault;
-      break;
-
-    case NS_DISPLAYCHANGED:
-
-      //Destroy the cached backbuffer to force a new backbuffer
-      //be constructed with the appropriate display depth.
-      //@see bugzilla bug 6061
-      *aStatus = nsEventStatus_eConsumeDoDefault;
-      break;
-
-    case NS_SYSCOLORCHANGED:
-      {
-        if (mPresShell) {
-          // Hold a refcount to the presshell. The continued existence of the observer will
-          // delay deletion of this view hierarchy should the event want to cause its
-          // destruction in, say, some JavaScript event handler.
-          nsCOMPtr<nsIPresShell> presShell = mPresShell;
-          presShell->HandleEvent(aView->GetFrame(), aEvent, false, aStatus);
-        }
-      }
-      break; 
-
-    default:
-      {
-        if ((NS_IS_MOUSE_EVENT(aEvent) &&
-             // Ignore mouse events that we synthesize.
-             static_cast<nsMouseEvent*>(aEvent)->reason ==
-               nsMouseEvent::eReal &&
-             // Ignore mouse exit and enter (we'll get moves if the user
-             // is really moving the mouse) since we get them when we
-             // create and destroy widgets.
-             aEvent->message != NS_MOUSE_EXIT &&
-             aEvent->message != NS_MOUSE_ENTER) ||
-            NS_IS_KEY_EVENT(aEvent) ||
-            NS_IS_IME_EVENT(aEvent) ||
-            aEvent->message == NS_PLUGIN_INPUT_EVENT) {
-          gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
-        }
-
-        if (aEvent->message == NS_DEACTIVATE) {
-          // if a window is deactivated, clear the mouse capture regardless
-          // of what is capturing
-          nsIPresShell::ClearMouseCapture(nullptr);
-        }
-
-        // Find the view whose coordinates system we're in.
-        nsIView* view = aView;
-        bool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
-        if (dispatchUsingCoordinates) {
-          // Will dispatch using coordinates. Pretty bogus but it's consistent
-          // with what presshell does.
-          view = GetDisplayRootFor(view);
-        }
-  
-        // If the view has no frame, look for a view that does.
-        nsIFrame* frame = view->GetFrame();
-        if (!frame &&
-            (dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
-             NS_IS_IME_RELATED_EVENT(aEvent) ||
-             NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) ||
-             aEvent->message == NS_PLUGIN_ACTIVATE ||
-             aEvent->message == NS_PLUGIN_FOCUS)) {
-          while (view && !view->GetFrame()) {
-            view = view->GetParent();
-          }
-
-          if (view) {
-            frame = view->GetFrame();
-          }
-        }
-
-        if (nullptr != frame) {
-          // Hold a refcount to the presshell. The continued existence of the
-          // presshell will delay deletion of this view hierarchy should the event
-          // want to cause its destruction in, say, some JavaScript event handler.
-          nsCOMPtr<nsIPresShell> shell = view->GetViewManager()->GetPresShell();
-          if (shell) {
-            shell->HandleEvent(frame, aEvent, false, aStatus);
-          }
-        }
-    
-        break;
-      }
-    }
-
   return NS_OK;
 }
 
 // Recursively reparent widgets if necessary 
 
 void nsViewManager::ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget)
 {
   NS_PRECONDITION(aNewWidget, "");
--- a/view/src/nsViewManager.h
+++ b/view/src/nsViewManager.h
@@ -163,16 +163,21 @@ public: // NOT in nsIViewManager, so pri
   nsViewManager* RootViewManager() const { return mRootViewManager; }
   bool IsRootVM() const { return this == RootViewManager(); }
 
   // Whether synchronous painting is allowed at the moment. For example,
   // widget geometry changes can cause synchronous painting, so they need to
   // be deferred while refresh is disabled.
   bool IsPaintingAllowed() { return RootViewManager()->mRefreshDisableCount == 0; }
 
+  void WillPaintWindow(nsIWidget* aWidget, bool aWillSendDidPaint);
+  bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion,
+                   bool aSentWillPaint, bool aWillSendDidPaint);
+  void DidPaintWindow();
+
   // Call this when you need to let the viewmanager know that it now has
   // pending updates.
   void PostPendingUpdate();
 
   PRUint32 AppUnitsPerDevPixel() const
   {
     return mContext->AppUnitsPerDevPixel();
   }
--- a/webapprt/CommandLineHandler.js
+++ b/webapprt/CommandLineHandler.js
@@ -3,127 +3,69 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://webapprt/modules/WebappRT.jsm");
 
 function CommandLineHandler() {}
 
 CommandLineHandler.prototype = {
   classID: Components.ID("{6d69c782-40a3-469b-8bfd-3ee366105a4a}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
 
   handle: function handle(cmdLine) {
     let args = Cc["@mozilla.org/hash-property-bag;1"].
                createInstance(Ci.nsIWritablePropertyBag);
     let inTestMode = this._handleTestMode(cmdLine, args);
-    Services.obs.notifyObservers(args, "webapprt-command-line", null);
 
-    // Initialize DOMApplicationRegistry by importing Webapps.jsm, but only
-    // after broadcasting webapprt-command-line.  Webapps.jsm calls
-    // DOMApplicationRegistry.init() when it's first imported.  init() accesses
-    // the WebappRegD directory, which in test mode is special-cased by
-    // DirectoryProvider.js after it observes webapprt-command-line.
-    Cu.import("resource://gre/modules/Webapps.jsm");
-
-    if (!inTestMode) {
-      startUp(inTestMode);
+    if (inTestMode) {
+      // Open the mochitest shim window, which configures the runtime for tests.
+      Services.ww.openWindow(null,
+                             "chrome://webapprt/content/mochitest.xul",
+                             "_blank",
+                             "chrome,dialog=no",
+                             args);
     } else {
-      DOMApplicationRegistry.allAppsLaunchable = true;
-
-      // startUp() accesses WebappRT.config, which in test mode is not valid
-      // until WebappRT.jsm observes an app installation.
-      Services.obs.addObserver(function onInstall(subj, topic, data) {
-        Services.obs.removeObserver(onInstall, "webapprt-test-did-install");
-        startUp(inTestMode);
-      }, "webapprt-test-did-install", false);
+      args.setProperty("url", WebappRT.launchURI.spec);
+      Services.ww.openWindow(null,
+                             "chrome://webapprt/content/webapp.xul",
+                             "_blank",
+                             "chrome,dialog=no,resizable,scrollbars,centerscreen",
+                             args);
     }
-
-    // Open the window with arguments to identify it as the main window
-    Services.ww.openWindow(null,
-                           "chrome://webapprt/content/webapp.xul",
-                           "_blank",
-                           "chrome,dialog=no,resizable,scrollbars,centerscreen",
-                           args);
   },
 
   _handleTestMode: function _handleTestMode(cmdLine, args) {
     // -test-mode [url]
     let idx = cmdLine.findFlag("test-mode", true);
     if (idx < 0)
       return false;
-    let url = null;
+    let url;
     let urlIdx = idx + 1;
     if (urlIdx < cmdLine.length) {
       let potentialURL = cmdLine.getArgument(urlIdx);
       if (potentialURL && potentialURL[0] != "-") {
-        url = potentialURL;
         try {
-          Services.io.newURI(url, null, null);
+          url = Services.io.newURI(potentialURL, null, null);
         } catch (err) {
           throw Components.Exception(
-            "-test-mode argument is not a valid URL: " + url,
+            "-test-mode argument is not a valid URL: " + potentialURL,
             Components.results.NS_ERROR_INVALID_ARG);
         }
         cmdLine.removeArguments(urlIdx, urlIdx);
+        args.setProperty("url", url.spec);
       }
     }
     cmdLine.removeArguments(idx, idx);
-    args.setProperty("test-mode", url);
     return true;
   },
 
   helpInfo : "",
 };
 
 let components = [CommandLineHandler];
 let NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
-
-/* There's some work we need to do on startup, before we load the webapp,
- * and this seems as good a place as any to do it, although it's possible
- * that in the future we will find a lazier place to do it.
- *
- * NOTE: it's very important that the stuff we do here doesn't prevent
- * the command-line handler from being registered/accessible, since otherwise
- * the app won't start, which is catastrophic failure.  That's why it's all
- * wrapped in a try/catch block. */
-function startUp(inTestMode) {
-  try {
-    if (!inTestMode) {
-      // Initialize window-independent handling of webapps- notifications.  Skip
-      // this in test mode, since it interferes with test app installations.
-      // We'll have to revisit this when we actually want to test installations
-      // and other functionality provided by WebappsHandler.
-      Cu.import("resource://webapprt/modules/WebappsHandler.jsm");
-      WebappsHandler.init();
-    }
-
-    // On firstrun, set permissions to their default values.
-    if (!Services.prefs.getBoolPref("webapprt.firstrun")) {
-      Cu.import("resource://webapprt/modules/WebappRT.jsm");
-      let uri = Services.io.newURI(WebappRT.config.app.origin, null, null);
-
-      // Set AppCache-related permissions.
-      Services.perms.add(uri, "pin-app",
-                         Ci.nsIPermissionManager.ALLOW_ACTION);
-      Services.perms.add(uri, "offline-app",
-                         Ci.nsIPermissionManager.ALLOW_ACTION);
-
-      Services.perms.add(uri, "indexedDB",
-                         Ci.nsIPermissionManager.ALLOW_ACTION);
-      Services.perms.add(uri, "indexedDB-unlimited",
-                         Ci.nsIPermissionManager.ALLOW_ACTION);
-
-      // Now that we've set the appropriate permissions, twiddle the firstrun
-      // flag so we don't try to do so again.
-      Services.prefs.setBoolPref("webapprt.firstrun", true);
-    }
-  } catch(ex) {
-#ifdef MOZ_DEBUG
-    dump(ex + "\n");
-#endif
-  }
-}
--- a/webapprt/DirectoryProvider.js
+++ b/webapprt/DirectoryProvider.js
@@ -9,40 +9,26 @@ const Cu = Components.utils;
 const WEBAPP_REGISTRY_DIR = "WebappRegD";
 const NS_APP_CHROME_DIR_LIST = "AChromDL";
 
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://webapprt/modules/WebappRT.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-let gInTestMode = false;
-Services.obs.addObserver(function observe(subj, topic, data) {
-  Services.obs.removeObserver(observe, "webapprt-command-line");
-  let args = subj.QueryInterface(Ci.nsIPropertyBag2);
-  gInTestMode = args.hasKey("test-mode");
-}, "webapprt-command-line", false);
-
 function DirectoryProvider() {}
 
 DirectoryProvider.prototype = {
   classID: Components.ID("{e1799fda-4b2f-4457-b671-e0641d95698d}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider,
                                          Ci.nsIDirectoryServiceProvider2]),
 
   getFile: function(prop, persistent) {
     if (prop == WEBAPP_REGISTRY_DIR) {
-      if (gInTestMode) {
-        // In test mode, apps are registered in the runtime's profile.  Note
-        // that in test mode WebappRT.config may not be valid at this point.
-        // It's only valid after WebappRT.jsm observes an app installation, and
-        // we can get here before any app is installed.
-        return FileUtils.getDir("ProfD", []);
-      }
       let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
       dir.initWithPath(WebappRT.config.registryDir);
       return dir;
     }
 
     // We return null to show failure instead of throwing an error,
     // which works with the way the interface is called (per bug 529077).
     return null;
--- a/webapprt/Makefile.in
+++ b/webapprt/Makefile.in
@@ -34,16 +34,17 @@ EXTRA_PP_COMPONENTS = \
   components.manifest \
   CommandLineHandler.js \
   ContentPermission.js \
   ContentPolicy.js \
   DirectoryProvider.js \
   $(NULL)
 
 EXTRA_JS_MODULES = \
+  Startup.jsm \
   WebappRT.jsm \
   WebappsHandler.jsm \
   $(NULL)
 
 PREF_JS_EXPORTS = $(srcdir)/prefs.js \
                   $(NULL)
 
 TEST_DIRS += \
new file mode 100644
--- /dev/null
+++ b/webapprt/Startup.jsm
@@ -0,0 +1,44 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This is imported by each new webapp window but is only evaluated the first
+ * time it is imported.  Put stuff here that you want to happen once on startup
+ * before the webapp is loaded.  But note that the "stuff" happens immediately
+ * the first time this module is imported.  So only put stuff here that must
+ * happen before the webapp is loaded. */
+
+const EXPORTED_SYMBOLS = [];
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+// Initialize DOMApplicationRegistry by importing Webapps.jsm.
+Cu.import("resource://gre/modules/Webapps.jsm");
+
+// Initialize window-independent handling of webapps- notifications.
+Cu.import("resource://webapprt/modules/WebappsHandler.jsm");
+WebappsHandler.init();
+
+// On firstrun, set permissions to their default values.
+if (!Services.prefs.getBoolPref("webapprt.firstrun")) {
+  Cu.import("resource://webapprt/modules/WebappRT.jsm");
+  let uri = Services.io.newURI(WebappRT.config.app.origin, null, null);
+
+  // Set AppCache-related permissions.
+  Services.perms.add(uri, "pin-app",
+                     Ci.nsIPermissionManager.ALLOW_ACTION);
+  Services.perms.add(uri, "offline-app",
+                     Ci.nsIPermissionManager.ALLOW_ACTION);
+
+  Services.perms.add(uri, "indexedDB",
+                     Ci.nsIPermissionManager.ALLOW_ACTION);
+  Services.perms.add(uri, "indexedDB-unlimited",
+                     Ci.nsIPermissionManager.ALLOW_ACTION);
+
+  // Now that we've set the appropriate permissions, twiddle the firstrun
+  // flag so we don't try to do so again.
+  Services.prefs.setBoolPref("webapprt.firstrun", true);
+}
--- a/webapprt/WebappRT.jsm
+++ b/webapprt/WebappRT.jsm
@@ -16,64 +16,45 @@ XPCOMUtils.defineLazyGetter(this, "FileU
   return FileUtils;
 });
 
 XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function() {
   Cu.import("resource://gre/modules/Webapps.jsm");
   return DOMApplicationRegistry;
 });
 
-// In test mode, observe webapps-ask-install so tests can install apps.
-Services.obs.addObserver(function observeCmdLine(subj, topic, data) {
-  Services.obs.removeObserver(observeCmdLine, "webapprt-command-line");
-  let args = subj.QueryInterface(Ci.nsIPropertyBag2);
-  if (!args.hasKey("test-mode"))
-    return;
-  Services.obs.addObserver(function observeInstall(subj, topic, data) {
-    // observeInstall is present for the lifetime of the runtime.
-    let config = JSON.parse(data);
-    config.registryDir = Services.dirsvc.get("ProfD", Ci.nsIFile).path;
-    DOMApplicationRegistry.confirmInstall(config);
-    delete WebappRT.config;
-    WebappRT.config = deepFreeze(config);
-    Services.obs.notifyObservers(null, "webapprt-test-did-install",
-                                 JSON.stringify(config));
-  }, "webapps-ask-install", false);
-}, "webapprt-command-line", false);
+let WebappRT = {
+  _config: null,
 
-let WebappRT = {
   get config() {
+    if (this._config)
+      return this._config;
+
+    let config;
     let webappFile = FileUtils.getFile("AppRegD", ["webapp.json"]);
+
     let inputStream = Cc["@mozilla.org/network/file-input-stream;1"].
                       createInstance(Ci.nsIFileInputStream);
     inputStream.init(webappFile, -1, 0, 0);
     let json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
-    let config = json.decodeFromStream(inputStream, webappFile.fileSize);
+    config = json.decodeFromStream(inputStream, webappFile.fileSize);
+
+    return this._config = config;
+  },
 
-    // Memoize the getter, freezing the `config` object in the meantime so
-    // consumers don't inadvertently (or intentionally) change it, as the object
-    // is meant to be a read-only representation of the webapp's configuration.
-    config = deepFreeze(config);
-    delete this.config;
-    Object.defineProperty(this, "config", { get: function getConfig() config });
-    return this.config;
+  // This exists to support test mode, which installs webapps after startup.
+  // Ideally we wouldn't have to have a setter, as tests can just delete
+  // the getter and then set the property.  But the object to which they set it
+  // will have a reference to its global object, so our reference to it
+  // will leak that object (per bug 780674).  The setter enables us to clone
+  // the new value so we don't actually retain a reference to it.
+  set config(newVal) {
+    this._config = JSON.parse(JSON.stringify(newVal));
+  },
+
+  get launchURI() {
+    let url = Services.io.newURI(this.config.app.origin, null, null);
+    if (this.config.app.manifest.launch_path) {
+      url = Services.io.newURI(this.config.app.manifest.launch_path, null, url);
+    }
+    return url;
   }
 };
-
-function deepFreeze(o) {
-  // First, freeze the object.
-  Object.freeze(o);
-
-  // Then recursively call deepFreeze() to freeze its properties.
-  for (let p in o) {
-    // If the object is on the prototype, not an object, or is already frozen,
-    // skip it.  Note that this might leave an unfrozen reference somewhere in
-    // the object if there is an already frozen object containing an unfrozen
-    // object.
-    if (!o.hasOwnProperty(p) || !(typeof o[p] == "object") ||
-        Object.isFrozen(o[p]))
-      continue;
-
-    deepFreeze(o[p]);
-  }
-
-  return o;
-}
new file mode 100644
--- /dev/null
+++ b/webapprt/content/mochitest.js
@@ -0,0 +1,74 @@
+/* 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/. */
+
+/* Note: this script is loaded by both mochitest.xul and head.js, so make sure
+ * the code you put here can be evaluated by both! */
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://webapprt/modules/WebappRT.jsm");
+
+const MANIFEST_URL_BASE = Services.io.newURI(
+  "http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/", null, null);
+
+// When WebappsHandler opens an install confirmation dialog for apps we install,
+// close it, which will be seen as the equivalent of cancelling the install.
+// This doesn't prevent us from installing those apps, as we listen for the same
+// notification as WebappsHandler and do the install ourselves.  It just
+// prevents the modal installation confirmation dialogs from hanging tests.
+Services.ww.registerNotification({
+  observe: function(win, topic) {
+    if (topic == "domwindowopened") {
+      // Wait for load because the window is not yet sufficiently initialized.
+      win.addEventListener("load", function onLoadWindow() {
+        win.removeEventListener("load", onLoadWindow, false);
+        if (win.location == "chrome://global/content/commonDialog.xul" &&
+            win.opener == window) {
+          win.close();
+        }
+      }, false);
+    }
+  }
+});
+
+/**
+ * Transmogrify the runtime session into one for the given webapp.
+ *
+ * @param {String} manifestURL
+ *        The URL of the webapp's manifest, relative to the base URL.
+ *        Note that the base URL points to the *chrome* WebappRT mochitests,
+ *        so you must supply an absolute URL to manifests elsewhere.
+ * @param {Object} parameters
+ *        The value to pass as the "parameters" argument to
+ *        mozIDOMApplicationRegistry.install, e.g., { receipts: ... }.
+ *        Use undefined to pass nothing.
+ * @param {Function} onBecome
+ *        The callback to call once the transmogrification is complete.
+ */
+function becomeWebapp(manifestURL, parameters, onBecome) {
+  function observeInstall(subj, topic, data) {
+    Services.obs.removeObserver(observeInstall, "webapps-ask-install");
+
+    // Step 2: Configure the runtime session to represent the app.
+    // We load DOMApplicationRegistry into a local scope to avoid appearing
+    // to leak it.
+
+    let scope = {};
+    Cu.import("resource://gre/modules/Webapps.jsm", scope);
+    scope.DOMApplicationRegistry.confirmInstall(JSON.parse(data));
+
+    let installRecord = JSON.parse(data);
+    installRecord.registryDir = Services.dirsvc.get("ProfD", Ci.nsIFile).path;
+    WebappRT.config = installRecord;
+
+    onBecome();
+  }
+  Services.obs.addObserver(observeInstall, "webapps-ask-install", false);
+
+  // Step 1: Install the app at the URL specified by the manifest.
+  let url = Services.io.newURI(manifestURL, null, MANIFEST_URL_BASE);
+  navigator.mozApps.install(url.spec, parameters);
+}
new file mode 100644
--- /dev/null
+++ b/webapprt/content/mochitest.xul
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this file,
+   - You can obtain one at http://mozilla.org/MPL/2.0/.  -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window windowtype="webapprt:mochitest"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script type="application/javascript" src="chrome://webapprt/content/mochitest.js"/>
+
+<script type="application/javascript">
+  Cu.import("resource://webapprt/modules/WebappRT.jsm");
+
+  // In test mode, the runtime isn't configured until we tell it to become
+  // an app, which requires us to use DOMApplicationRegistry to install one.
+  // But DOMApplicationRegistry needs to know the location of its registry dir,
+  // so we need to configure the runtime with at least that information.
+  WebappRT.config = {
+    registryDir: Services.dirsvc.get("ProfD", Ci.nsIFile).path,
+  };
+
+  Cu.import("resource://gre/modules/Webapps.jsm");
+
+  DOMApplicationRegistry.allAppsLaunchable = true;
+
+  becomeWebapp("http://mochi.test:8888/tests/webapprt/test/content/test.webapp",
+               undefined, function onBecome() {
+    Services.ww.openWindow(
+      null,
+      "chrome://webapprt/content/webapp.xul",
+      "_blank",
+      "chrome,dialog=no,resizable,scrollbars,centerscreen",
+      window.arguments[0]
+    );
+    window.close();
+  });
+</script>
+
+<description value="WebappRT Test Shim"/>
+
+</window>
--- a/webapprt/content/webapp.js
+++ b/webapprt/content/webapp.js
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
+Cu.import("resource://webapprt/modules/Startup.jsm");
 Cu.import("resource://webapprt/modules/WebappRT.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "gAppBrowser",
                             function() document.getElementById("content"));
 
 #ifdef MOZ_CRASHREPORTER
@@ -43,79 +44,45 @@ let progressListener = {
       updateCrashReportURL(aRequest.URI);
     }
   }
 };
 
 function onLoad() {
   window.removeEventListener("load", onLoad, false);
 
-  let cmdLineArgs = window.arguments && window.arguments[0] ?
-                    window.arguments[0].QueryInterface(Ci.nsIPropertyBag2) :
-                    null;
-
-  // In test mode, listen for test app installations and load the -test-mode URL
-  // if present.
-  if (cmdLineArgs && cmdLineArgs.hasKey("test-mode")) {
-    // This observer is only present until the first app gets installed.
-    // It adds the progress listener, which can't happen until then because
-    // the progress listener needs to access the app manifest, which isn't
-    // available beforehand.
-    Services.obs.addObserver(function observeOnce(subj, topic, data) {
-      Services.obs.removeObserver(observeOnce, "webapprt-test-did-install");
-      gAppBrowser.addProgressListener(progressListener,
-                                      Ci.nsIWebProgress.NOTIFY_LOCATION);
-    }, "webapprt-test-did-install", false);
-
-    // This observer is present for the lifetime of the runtime.
-    Services.obs.addObserver(function observe(subj, topic, data) {
-      initWindow(false);
-    }, "webapprt-test-did-install", false);
+  let args = window.arguments && window.arguments[0] ?
+             window.arguments[0].QueryInterface(Ci.nsIPropertyBag2) :
+             null;
 
-    let testURL = cmdLineArgs.get("test-mode");
-    if (testURL) {
-      gAppBrowser.loadURI(testURL);
-    }
-
-    return;
-  }
-
-  gAppBrowser.webProgress.
-    addProgressListener(progressListener, Ci.nsIWebProgress.NOTIFY_LOCATION |
-                                          Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
-
-  initWindow(!!cmdLineArgs);
-}
-window.addEventListener("load", onLoad, false);
-
-function onUnload() {
-  gAppBrowser.removeProgressListener(progressListener);
-}
-window.addEventListener("unload", onUnload, false);
-
-function initWindow(isMainWindow) {
-  let manifest = WebappRT.config.app.manifest;
+  gAppBrowser.addProgressListener(progressListener,
+                                  Ci.nsIWebProgress.NOTIFY_LOCATION |
+                                  Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
 
   updateMenuItems();
 
   // Listen for clicks to redirect <a target="_blank"> to the browser.
   // This doesn't capture clicks so content can capture them itself and do
   // something different if it doesn't want the default behavior.
   gAppBrowser.addEventListener("click", onContentClick, false, true);
 
-  // Only load the webapp on the initially launched main window
-  if (isMainWindow) {
-    // Load the webapp's launch URL
-    let installRecord = WebappRT.config.app;
-    let url = Services.io.newURI(installRecord.origin, null, null);
-    if (manifest.launch_path)
-      url = Services.io.newURI(manifest.launch_path, null, url);
-    gAppBrowser.setAttribute("src", url.spec);
+  // This is not the only way that a URL gets loaded in the app browser.
+  // When content calls openWindow(), there are no window.arguments,
+  // but something in the platform loads the URL specified by the content.
+  if (args && args.hasKey("url")) {
+    gAppBrowser.setAttribute("src", args.get("url"));
   }
+
 }
+window.addEventListener("load", onLoad, false);
+
+function onUnload() {
+  gAppBrowser.removeProgressListener(progressListener);
+}
+window.addEventListener("unload", onUnload, false);
 
 /**
  * Direct a click on <a target="_blank"> to the user's default browser.
  *
  * In the long run, it might be cleaner to move this to an extension of
  * nsIWebBrowserChrome3::onBeforeLinkTraversal.
  *
  * @param {DOMEvent} event the DOM event
@@ -194,17 +161,19 @@ function updateEditUIVisibility() {
 }
 
 function updateCrashReportURL(aURI) {
 #ifdef MOZ_CRASHREPORTER
   if (!gCrashReporter.enabled)
     return;
 
   let uri = aURI.clone();
-  if (uri.userPass != "") {
-    try {
+  // uri.userPass throws on protocols without the concept of authentication,
+  // like about:, which tests can load, so we catch and ignore an exception.
+  try {
+    if (uri.userPass != "") {
       uri.userPass = "";
-    } catch (e) {}
-  }
+    }
+  } catch (e) {}
 
   gCrashReporter.annotateCrashReport("URL", uri.spec);
 #endif
 }
--- a/webapprt/jar.mn
+++ b/webapprt/jar.mn
@@ -1,8 +1,10 @@
 # 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/.
 
 webapprt.jar:
 % content webapprt %content/
 * content/webapp.js                     (content/webapp.js)
 * content/webapp.xul                    (content/webapp.xul)
+  content/mochitest.js                  (content/mochitest.js)
+  content/mochitest.xul                 (content/mochitest.xul)
--- a/webapprt/test/chrome/Makefile.in
+++ b/webapprt/test/chrome/Makefile.in
@@ -7,17 +7,16 @@ topsrcdir      = @top_srcdir@
 srcdir         = @srcdir@
 VPATH          = @srcdir@
 relativesrcdir = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_WEBAPPRT_CHROME_FILES = \
   head.js \
-  install.html \
   browser_sample.js \
     sample.webapp \
     sample.html \
   browser_window-title.js \
     window-title.webapp \
     window-title.html \
   $(NULL)
 
--- a/webapprt/test/chrome/browser_sample.js
+++ b/webapprt/test/chrome/browser_sample.js
@@ -1,19 +1,20 @@
 // This is a sample WebappRT chrome test.  It's just a browser-chrome mochitest.
 
+Cu.import("resource://webapprt/modules/WebappRT.jsm");
+
 function test() {
   waitForExplicitFinish();
   ok(true, "true is true!");
-  installWebapp("sample.webapp", undefined, function onInstall(appConfig) {
+  loadWebapp("sample.webapp", undefined, function onLoad() {
     is(document.documentElement.getAttribute("title"),
-       appConfig.app.manifest.name,
+       WebappRT.config.app.manifest.name,
        "Window title should be webapp name");
-    let content = document.getElementById("content");
-    let msg = content.contentDocument.getElementById("msg");
+    let msg = gAppBrowser.contentDocument.getElementById("msg");
     var observer = new MutationObserver(function (mutations) {
       ok(/^Webapp getSelf OK:/.test(msg.textContent),
          "The webapp should have successfully installed and updated its msg");
       finish();
     });
     observer.observe(msg, { childList: true });
   });
 }
--- a/webapprt/test/chrome/browser_window-title.js
+++ b/webapprt/test/chrome/browser_window-title.js
@@ -1,28 +1,26 @@
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://webapprt/modules/WebappRT.jsm");
 
 function test() {
   waitForExplicitFinish();
 
-  installWebapp("window-title.webapp", undefined,
-                function onInstall(appConfig) {
+  loadWebapp("window-title.webapp", undefined, function onLoad() {
     is(document.documentElement.getAttribute("title"),
-       appConfig.app.manifest.name,
+       WebappRT.config.app.manifest.name,
        "initial window title should be webapp name");
 
-    let appBrowser = document.getElementById("content");
-
     // Tests are triples of [URL to load, expected window title, test message].
     let tests = [
       ["http://example.com/webapprtChrome/webapprt/test/chrome/window-title.html",
-       "http://example.com" + " - " + appConfig.app.manifest.name,
+       "http://example.com" + " - " + WebappRT.config.app.manifest.name,
        "window title should show origin of page at different origin"],
       ["http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/window-title.html",
-       appConfig.app.manifest.name,
+       WebappRT.config.app.manifest.name,
        "after returning to app origin, window title should no longer show origin"],
     ];
 
     let title, message;
 
     let progressListener = {
       QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
                                              Ci.nsISupportsWeakReference]),
@@ -31,25 +29,25 @@ function test() {
         // Do test in timeout to give runtime time to change title.
         window.setTimeout(function() {
           is(document.documentElement.getAttribute("title"), title, message);
           testNext();
         }, 0);
       }
     };
 
-    appBrowser.addProgressListener(progressListener,
-                                   Ci.nsIWebProgress.NOTIFY_LOCATION);
+    gAppBrowser.addProgressListener(progressListener,
+                                    Ci.nsIWebProgress.NOTIFY_LOCATION);
 
     function testNext() {
       if (!tests.length) {
-        appBrowser.removeProgressListener(progressListener);
-        appBrowser.stop();
+        gAppBrowser.removeProgressListener(progressListener);
+        gAppBrowser.stop();
         finish();
         return;
       }
 
-      [appBrowser.contentDocument.location, title, message] = tests.shift();
+      [gAppBrowser.contentDocument.location, title, message] = tests.shift();
     }
 
     testNext();
   });
 }
--- a/webapprt/test/chrome/head.js
+++ b/webapprt/test/chrome/head.js
@@ -1,63 +1,31 @@
 /* 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/. */
-
-const INSTALL_URL =
-  "http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/install.html";
+ * 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/. */
 
 Cu.import("resource://gre/modules/Services.jsm");
 
-/**
- * Installs the given webapp and navigates to it.
- *
- * @param manifestPath
- *        The path of the webapp's manifest relative to
- *        http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/.
- * @param parameters
- *        The value to pass as the "parameters" argument to
- *        mozIDOMApplicationRegistry.install, e.g., { receipts: ... }.  Use
- *        undefined to pass nothing.
- * @param callback
- *        Called when the newly installed webapp is navigated to.  It's passed
- *        the webapp's config object.
- */
-function installWebapp(manifestPath, parameters, onInstall) {
-  // Three steps: (1) Load install.html, (2) listen for webapprt-test-did-
-  // install to get the app config object, and then (3) listen for load of the
-  // webapp page to call the callback.  webapprt-test-did-install will be
-  // broadcasted before install.html navigates to the webapp page.  (This is due
-  // to some implementation details: WebappRT.jsm confirms the installation by
-  // calling DOMApplicationRegistry.confirmInstall, and then it immediately
-  // broadcasts webapprt-test-did-install.  confirmInstall asynchronously
-  // notifies the mozApps consumer via onsuccess, which is when install.html
-  // navigates to the webapp page.)
-
-  let content = document.getElementById("content");
+// Some of the code we want to provide to chrome mochitests is in another file
+// so we can share it with the mochitest shim window, thus we need to load it.
+Services.scriptloader.loadSubScript("chrome://webapprt/content/mochitest.js",
+                                    this);
 
-  Services.obs.addObserver(function observe(subj, topic, data) {
-    // step 2
-    Services.obs.removeObserver(observe, "webapprt-test-did-install");
-    let appConfig = JSON.parse(data);
-
-    content.addEventListener("load", function onLoad(event) {
-      // step 3
-      content.removeEventListener("load", onLoad, true);
-      let webappURL = appConfig.app.origin + appConfig.app.manifest.launch_path;
-      is(event.target.URL, webappURL,
-         "No other page should have loaded between installation and " +
-         "the webapp's page load: " + event.target.URL);
-      onInstall(appConfig);
-    }, true);
-  }, "webapprt-test-did-install", false);
-
-  // step 1
-  let args = [["manifestPath", manifestPath]];
-  if (parameters !== undefined) {
-    args.push(["parameters", parameters]);
-  }
-  let queryStr = args.map(function ([key, val])
-                          key + "=" + encodeURIComponent(JSON.stringify(val))).
-                 join("&");
-  let installURL = INSTALL_URL + "?" + queryStr;
-  content.loadURI(installURL);
+/**
+ * Load the webapp in the app browser.
+ *
+ * @param {String} manifestURL
+ *        @see becomeWebapp
+ * @param {Object} parameters
+ *        @see becomeWebapp
+ * @param {Function} onLoad
+ *        The callback to call once the webapp is loaded.
+ */
+function loadWebapp(manifest, parameters, onLoad) {
+  becomeWebapp(manifest, parameters, function onBecome() {
+    function onLoadApp() {
+      gAppBrowser.removeEventListener("load", onLoadApp, true);
+      onLoad();
+    }
+    gAppBrowser.addEventListener("load", onLoadApp, true);
+    gAppBrowser.setAttribute("src", WebappRT.launchURI.spec);
+  });
 }
deleted file mode 100644
--- a/webapprt/test/chrome/install.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE HTML>
-
-<!--
-  Chrome tests load this file to install their webapps.  Pass manifestPath=path
-  in the query string to install the app with the manifest at
-  http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/<path>.
--->
-
-<html>
-  <head>
-    <meta charset="utf-8">
-    <script>
-
-function parseQueryStr() {
-  return window.location.search.substr(1).split("&").
-         map(function (pairStr) pairStr.split("=")).
-         reduce(function (memo, [key, val]) {
-           memo[key] = JSON.parse(decodeURIComponent(val));
-           return memo;
-         }, {});
-}
-
-function msg(str) {
-  document.getElementById("msg").textContent = str;
-}
-
-function onLoad() {
-  var args = parseQueryStr();
-  if (!args.manifestPath) {
-    msg("No manifest path given, so standing by.");
-    return;
-  }
-  var manifestURL =
-    "http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/" +
-     args.manifestPath;
-  var installArgs = [manifestURL, args.parameters];
-  msg("Installing webapp with arguments " + installArgs.toSource() + "...");
-  var install = navigator.mozApps.install.apply(navigator.mozApps, installArgs);
-  install.onsuccess = function (event) {
-    msg("Webapp installed, now navigating to it.");
-    var testAppURL = install.result.origin +
-                     install.result.manifest.launch_path;
-    window.location = testAppURL;
-  };
-  install.onerror = function () {
-    msg("Webapp installation failed with " + install.error.name +
-        " for manifest " + manifestURL);
-  };
-}
-
-    </script>
-  </head>
-  <body onload="onLoad();" onunload="">
-    <p id="msg">Installation page waiting for page load...</p>
-  </body>
-</html>
--- a/webapprt/test/content/Makefile.in
+++ b/webapprt/test/content/Makefile.in
@@ -6,15 +6,13 @@ DEPTH          = @DEPTH@
 topsrcdir      = @top_srcdir@
 srcdir         = @srcdir@
 VPATH          = @srcdir@
 relativesrcdir = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES = \
-  helpers.js \
+  test.webapp \
   webapprt_sample.html \
-    sample.webapp \
-    sample.html \
   $(NULL)
 
<