Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Thu, 16 Aug 2012 14:04:20 -0700
changeset 113560 d1b17b12a472efd78831ef9f6b9f331c96c438b0
parent 113559 599a761c17fe37433d1177c445bbd99c49f4f0df (current diff)
parent 108523 57e59b2e017e9ed8ab2389b23a675431dbe83d1f (diff)
child 113561 f6c3f006b57a8136dd40d4e4b530c630300d1c0b
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
b2g/chrome/jar.mn
browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
build/autoconf/mozconfig2client-mk
build/mobile/devicemanagerADB.py
build/mobile/devicemanagerSUT.py
configure.in
content/base/src/nsAttrValue.cpp
content/base/src/nsAttrValue.h
content/base/src/nsDOMFile.cpp
content/base/src/nsDocumentEncoder.cpp
content/base/src/nsObjectLoadingContent.cpp
content/canvas/test/webgl/resources/js-test-post.js
content/events/public/nsEventNameList.h
content/events/src/nsDOMEvent.cpp
content/xbl/src/nsXBLWindowKeyHandler.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsScriptNameSpaceManager.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/ipc/PPluginModule.ipdl
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/ipc/PluginModuleParent.cpp
editor/libeditor/html/nsHTMLDataTransfer.cpp
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsHTMLEditor.h
editor/libeditor/html/nsHTMLEditorStyle.cpp
editor/libeditor/text/nsPlaintextDataTransfer.cpp
editor/libeditor/text/nsPlaintextEditor.h
editor/txmgr/tests/TestTXMgr.cpp
embedding/browser/webBrowser/nsWebBrowser.cpp
embedding/browser/webBrowser/nsWebBrowser.h
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
extensions/cookie/nsPermissionManager.cpp
gfx/2d/QuartzSupport.mm
gfx/layers/Layers.h
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/ThebesLayerOGL.cpp
image/decoders/nsJPEGDecoder.cpp
image/encoders/jpeg/nsJPEGEncoder.cpp
intl/strres/src/nsStringBundle.cpp
ipc/ipdl/ipdl/builtin.py
js/src/configure.in
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeCompiler.h
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/FoldConstants.cpp
js/src/frontend/ParseNode.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/SemanticAnalysis.cpp
js/src/gc/Marking.cpp
js/src/gc/Marking.h
js/src/ion/IonBuilder.cpp
js/src/ion/IonBuilder.h
js/src/js.msg
js/src/jsanalyze.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsdbgapi.cpp
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsopcode.cpp
js/src/jsreflect.cpp
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsscriptinlines.h
js/src/jsweakmap.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/FastOps.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MethodJIT.cpp
js/src/methodjit/MethodJIT.h
js/src/methodjit/MonoIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/SPSProfiler.cpp
js/src/vm/ScopeObject-inl.h
js/src/vm/ScopeObject.cpp
js/src/vm/ScopeObject.h
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/vm/String.h
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcprivate.h
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
layout/build/nsLayoutStatics.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsSelection.cpp
layout/mathml/nsMathMLOperators.cpp
layout/mathml/nsMathMLmpaddedFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/reftests/bugs/reftest.list
layout/style/nsCSSScanner.cpp
layout/style/nsFontFaceLoader.cpp
layout/svg/base/src/nsSVGInnerSVGFrame.cpp
layout/svg/base/src/nsSVGOuterSVGFrame.cpp
layout/tools/layout-debug/src/nsRegressionTester.cpp
mobile/android/base/GeckoApp.java
mobile/android/chrome/content/browser.js
mobile/android/themes/core/aboutReader.css
netwerk/base/public/nsIIPCSerializable.idl
netwerk/base/src/nsBufferedStreams.cpp
netwerk/base/src/nsBufferedStreams.h
netwerk/base/src/nsFileStreams.cpp
netwerk/base/src/nsFileStreams.h
netwerk/base/src/nsLoadGroup.cpp
netwerk/base/src/nsMIMEInputStream.cpp
netwerk/base/src/nsSimpleNestedURI.cpp
netwerk/base/src/nsSimpleNestedURI.h
netwerk/base/src/nsSimpleURI.cpp
netwerk/base/src/nsSimpleURI.h
netwerk/base/src/nsStandardURL.cpp
netwerk/base/src/nsStandardURL.h
netwerk/protocol/about/nsAboutProtocolHandler.cpp
netwerk/protocol/http/PHttpChannelParams.h
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/socket/nsSOCKSIOLayer.cpp
parser/htmlparser/src/nsHTMLTokens.cpp
security/manager/ssl/src/nsCertOverrideService.cpp
security/manager/ssl/src/nsCrypto.cpp
testing/mochitest/runtests.py
testing/mochitest/tests/SimpleTest/setup.js
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
toolkit/mozapps/extensions/LightweightThemeManager.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/content/setting.xml
toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
toolkit/xre/nsEmbedFunctions.cpp
uriloader/base/nsDocLoader.cpp
view/public/nsIView.h
view/src/nsView.cpp
view/src/nsView.h
view/src/nsViewManager.cpp
view/src/nsViewManager.h
webapprt/test/chrome/install.html
webapprt/test/content/helpers.js
webapprt/test/content/sample.html
webapprt/test/content/sample.webapp
widget/android/nsClipboard.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/gtk2/nsWindow.cpp
widget/gtk2/nsWindow.h
widget/nsGUIEvent.h
widget/nsIWidget.h
widget/os2/nsWindow.cpp
widget/qt/nsWindow.cpp
widget/qt/nsWindow.h
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
widget/windows/nsWindowGfx.cpp
widget/xpwidgets/PuppetWidget.cpp
widget/xpwidgets/PuppetWidget.h
widget/xpwidgets/nsBaseWidget.cpp
widget/xpwidgets/nsBaseWidget.h
widget/xpwidgets/nsTransferable.cpp
xpcom/base/nsError.h
xpcom/base/nsErrorService.cpp
xpcom/io/nsDirectoryService.cpp
xpcom/io/nsMultiplexInputStream.cpp
xpcom/io/nsStringStream.cpp
xpcom/tests/TestObserverService.cpp
xpfe/appshell/src/nsWebShellWindow.cpp
xpfe/appshell/src/nsWebShellWindow.h
xpfe/appshell/src/nsXULWindow.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -32,17 +32,16 @@ tier_base_dirs = \
   probes \
   mfbt \
   $(NULL)
 
 ifndef LIBXUL_SDK
 ifeq (android,$(MOZ_WIDGET_TOOLKIT))
 tier_base_dirs += \
   other-licenses/android \
-  other-licenses/skia-npapi \
   $(NULL)
 endif
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 tier_base_dirs += \
   other-licenses/android \
   $(NULL)
 endif
 
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -39,17 +39,17 @@ var AccessFu = {
     this.chromeWin = aWindow;
     this.presenters = [];
 
     this.prefsBranch = Cc['@mozilla.org/preferences-service;1']
       .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.');
     this.prefsBranch.addObserver('activate', this, false);
     this.prefsBranch.addObserver('explorebytouch', this, false);
 
-    if (Utils.OS == 'Android')
+    if (Utils.MozBuildApp == 'mobile/android')
       Services.obs.addObserver(this, 'Accessibility:Settings', false);
 
     this._processPreferences();
   },
 
   /**
    * Start AccessFu mode, this primarily means controlling the virtual cursor
    * with arrow keys.
@@ -111,17 +111,17 @@ var AccessFu = {
 
     let ebtPref = ACCESSFU_DISABLE;
     try {
       ebtPref = (aTouchEnabled == undefined) ?
         this.prefsBranch.getIntPref('explorebytouch') : aTouchEnabled;
     } catch (x) {
     }
 
-    if (Utils.OS == 'Android') {
+    if (Utils.MozBuildApp == 'mobile/android') {
       if (accessPref == ACCESSFU_AUTO) {
         Cc['@mozilla.org/android/bridge;1'].
           getService(Ci.nsIAndroidBridge).handleGeckoMessage(
             JSON.stringify({ gecko: { type: 'Accessibility:Ready' } }));
         return;
       }
     }
 
--- a/accessible/src/jsat/UtteranceGenerator.jsm
+++ b/accessible/src/jsat/UtteranceGenerator.jsm
@@ -147,17 +147,17 @@ var UtteranceGenerator = {
     'toolbar': INCLUDE_DESC,
     'table': INCLUDE_DESC | INCLUDE_NAME,
     'link': INCLUDE_DESC,
     'listitem': INCLUDE_DESC,
     'outline': INCLUDE_DESC,
     'outlineitem': INCLUDE_DESC,
     'pagetab': INCLUDE_DESC,
     'graphic': INCLUDE_DESC,
-    'pushbutton': INCLUDE_DESC,
+    'pushbutton': INCLUDE_DESC | INCLUDE_NAME,
     'checkbutton': INCLUDE_DESC,
     'radiobutton': INCLUDE_DESC,
     'combobox': INCLUDE_DESC,
     'droplist': INCLUDE_DESC,
     'progressbar': INCLUDE_DESC,
     'slider': INCLUDE_DESC,
     'spinbutton': INCLUDE_DESC,
     'diagram': INCLUDE_DESC,
--- a/accessible/src/jsat/VirtualCursorController.jsm
+++ b/accessible/src/jsat/VirtualCursorController.jsm
@@ -255,38 +255,16 @@ var VirtualCursorController = {
         let methodName = '', rule = {};
         try {
           [methodName, rule] = this.keyMap[key];
         } catch (x) {
           return;
         }
         this[methodName](document, false, rule);
         break;
-      case aEvent.DOM_VK_END:
-        if (this.editableState) {
-          if (target.selectionEnd != target.textLength)
-            // Don't move forward if caret is not at end of entry.
-            // XXX: Fix for rtl
-            return;
-          else
-            target.blur();
-        }
-        this.moveForward(document, true);
-        break;
-      case aEvent.DOM_VK_HOME:
-        if (this.editableState) {
-          if (target.selectionEnd != 0)
-            // Don't move backward if caret is not at start of entry.
-            // XXX: Fix for rtl
-            return;
-          else
-            target.blur();
-        }
-        this.moveBackward(document, true);
-        break;
       case aEvent.DOM_VK_RIGHT:
         if (this.editableState) {
           if (target.selectionEnd != target.textLength)
             // Don't move forward if caret is not at end of entry.
             // XXX: Fix for rtl
             return;
           else
             target.blur();
@@ -308,17 +286,17 @@ var VirtualCursorController = {
         if (this.editableState & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) {
           if (target.selectionEnd != 0)
             // Don't blur content if caret is not at start of text area.
             return;
           else
             target.blur();
         }
 
-        if (Utils.OS == 'Android')
+        if (Utils.MozBuildApp == 'mobile/android')
           // Return focus to native Android browser chrome.
           Cc['@mozilla.org/android/bridge;1'].
             getService(Ci.nsIAndroidBridge).handleGeckoMessage(
               JSON.stringify({ gecko: { type: 'ToggleChrome:Focus' } }));
         break;
       case aEvent.DOM_VK_RETURN:
       case aEvent.DOM_VK_ENTER:
         if (this.editableState)
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -497,8 +497,14 @@ pref("ui.showHideScrollbars", 1);
 pref("dom.ipc.processPriorityManager.enabled", true);
 pref("dom.ipc.processPriorityManager.gracePeriodMS", 1000);
 pref("hal.processPriorityManager.gonk.masterOomAdjust", 0);
 pref("hal.processPriorityManager.gonk.foregroundOomAdjust", 1);
 pref("hal.processPriorityManager.gonk.backgroundOomAdjust", 2);
 pref("hal.processPriorityManager.gonk.masterNice", -1);
 pref("hal.processPriorityManager.gonk.foregroundNice", 0);
 pref("hal.processPriorityManager.gonk.backgroundNice", 10);
+
+// Enable pre-launching content processes for improved startup time
+// (hiding latency).
+pref("dom.ipc.processPrelauch.enabled", true);
+// Wait this long before pre-launching a new subprocess.
+pref("dom.ipc.processPrelauch.delayMs", 1000);
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/arrow.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="11px" style="position: absolute; top: -moz-calc(50% - 2px);">
+  <polyline points="1 1 5 6 9 1" stroke="#414141" stroke-width="2" stroke-linecap="round" fill="transparent" stroke-linejoin="round"/>
+</svg>
--- a/b2g/chrome/content/content.css
+++ b/b2g/chrome/content/content.css
@@ -69,8 +69,221 @@ xul|thumb {
   border: 1px solid rgba(255, 255, 255, 0.4) !important;
   border-radius: 3px;
 }
 
 /* -moz-touch-enabled? media elements */
 :-moz-any(video, audio) > xul|videocontrols {
   -moz-binding: url("chrome://global/content/bindings/videocontrols.xml#touchControls");
 }
+
+select:not([size]):not([multiple]) > xul|scrollbar,
+select[size="1"] > xul|scrollbar,
+select:not([size]):not([multiple]) xul|scrollbarbutton,
+select[size="1"] xul|scrollbarbutton {
+  display: block;
+  margin-left: 0;
+  min-width: 16px;
+}
+
+/* Override inverse OS themes */
+select,
+textarea,
+button,
+xul|button,
+* > input:not([type="image"]) {
+  -moz-appearance: none !important;  /* See bug 598421 for fixing the platform */
+  border-radius: 3px;
+}
+
+select[size],
+select[multiple],
+select[size][multiple],
+textarea,
+* > input:not([type="image"]) {
+  border-style: solid;
+  border-color: #7d7d7d;
+  color: #414141;
+  background: white -moz-linear-gradient(top, rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 3px, rgba(255,255,255,0.2) 16px);
+}
+
+/* Selects are handled by the form helper, see bug 685197 */
+select option, select optgroup {
+  pointer-events: none;
+}
+
+input:-moz-placeholder,
+textarea:-moz-placeholder {
+  color: GrayText;
+}
+
+select:not([size]):not([multiple]),
+select[size="0"],
+select[size="1"],
+* > input[type="button"],
+* > input[type="submit"],
+* > input[type="reset"],
+button {
+  border-style: solid;
+  border-color: #7d7d7d;
+  color: #414141;
+  background: white -moz-linear-gradient(top, rgba(255,255,255,0.2) 0, rgba(215,215,215,0.5) 18px, rgba(115,115,115,0.5) 100%);
+}
+
+input[type="checkbox"] {
+  background: white -moz-linear-gradient(top, rgba(115,115,115,0.5) 0, rgba(215,215,215,0.5) 2px, rgba(255,255,255,0.2) 6px);
+}
+
+input[type="radio"] {
+  background: -moz-radial-gradient(6px 6px, cover, rgba(255,255,255,0.2) 3px, rgba(195,195,195,0.5) 5px, rgba(115,115,115,0.5) 100%);
+}
+
+select {
+  border-width: 1px;
+  padding: 1px;
+}
+
+select:not([size]):not([multiple]),
+select[size="0"],
+select[size="1"] {
+  padding: 0 1px 0 1px;
+}
+
+* > input:not([type="image"]) {
+  border-width: 1px;
+  padding: 1px;
+}
+
+textarea {
+  resize: none;
+  border-width: 1px;
+  padding: 2px 1px 2px 1px;
+}
+
+input[type="button"],
+input[type="submit"],
+input[type="reset"],
+button {
+  border-width: 1px;
+  padding: 0 7px 0 7px;
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+  max-width: 14px;
+  max-height: 14px;
+  border: 1px solid #a7a7a7 !important;
+  padding: 2px 1px 2px 1px;
+}
+
+select > button {
+  border-width: 0px !important;
+  margin: 0px !important;
+  padding: 0px !important;
+  border-radius: 0;
+  color: #414141;
+
+  background-image: -moz-radial-gradient(bottom left, #bbbbbb 40%, #f5f5f5), url(arrow.svg) !important;
+  background-color: transparent;
+  background-position: -15px center, 4px center !important;
+  background-repeat: no-repeat, no-repeat !important;
+  background-size: 100% 90%, normal normal;
+
+  -moz-binding: none !important;
+  position: relative !important;
+  font-size: inherit;
+}
+
+select[size]:focus,
+select[multiple]:focus,
+select[size][multiple]:focus,
+textarea:focus,
+input[type="file"]:focus > input[type="text"],
+* > input:not([type="image"]):focus {
+  outline: 0px !important;
+  border-style: solid;
+  border-color: rgb(94,128,153);
+  background: white -moz-linear-gradient(top, rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 3px, rgba(255,255,255,0.2) 16px);
+}
+
+select:not([size]):not([multiple]):focus,
+select[size="0"]:focus,
+select[size="1"]:focus,
+input[type="button"]:focus,
+input[type="submit"]:focus,
+input[type="reset"]:focus,
+button:focus {
+  outline: 0px !important;
+  border-style: solid;
+  border-color: rgb(94,128,153);
+  background: white -moz-linear-gradient(top, rgba(255,255,255,0.2) 0, rgba(198,225,256,0.2) 18px, rgba(27,113,177,0.5) 100%);
+}
+
+input[type="checkbox"]:focus,
+input[type="radio"]:focus {
+  border-color: #99c6e0 !important;
+}
+
+input[type="checkbox"]:focus {
+  background: white -moz-linear-gradient(top, rgba(27,113,177,0.5) 0, rgba(198,225,246,0.2) 2px, rgba(255,255,255,0.2) 6px);
+}
+
+input[type="radio"]:focus {
+  background: -moz-radial-gradient(6px 6px, cover, rgba(255,255,255,0.2) 3px, rgba(198,225,246,0.2) 5px, rgba(27,113,177,0.5) 100%);
+}
+
+/* we need to be specific for selects because the above rules are specific too */
+textarea[disabled],
+select[size][disabled],
+select[multiple][disabled],
+select[size][multiple][disabled],
+select:not([size]):not([multiple])[disabled],
+select[size="0"][disabled],
+select[size="1"][disabled],
+button[disabled],
+* > input:not([type="image"])[disabled] {
+  color: rgba(0,0,0,0.3);
+  border-color: rgba(125,125,125,0.4);
+  border-style: solid;
+  border-width: 1px;
+  background: transparent -moz-linear-gradient(top, rgba(185,185,185,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(255,255,255,0.4) 100%);
+}
+
+select:not([size]):not([multiple])[disabled],
+select[size="0"][disabled],
+select[size="1"][disabled] {
+  background: transparent -moz-linear-gradient(top, rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
+}
+
+input[type="button"][disabled],
+input[type="submit"][disabled],
+input[type="reset"][disabled],
+button[disabled="true"] {
+  padding: 0 7px 0 7px;
+  background: transparent -moz-linear-gradient(top, rgba(255,255,255,0.4) 0, rgba(235,235,235,0.4) 3px, rgba(185,185,185,0.4) 100%);
+}
+
+input[type="radio"][disabled],
+input[type="radio"][disabled]:active,
+input[type="radio"][disabled]:hover,
+input[type="radio"][disabled]:hover:active,
+input[type="checkbox"][disabled],
+input[type="checkbox"][disabled]:active,
+input[type="checkbox"][disabled]:hover,
+input[type="checkbox"][disabled]:hover:active {
+  border:1px solid rgba(125,125,125,0.4) !important;
+}
+
+select[disabled] > button {
+  opacity: 0.6;
+  padding: 1px 7px 1px 7px;
+}
+
+*:-moz-any-link:active,
+*[role=button]:active,
+button:active,
+input:active,
+option:active,
+select:active,
+label:active,
+textarea:active {
+  background-color: rgba(141, 184, 216, 0.5);
+}
--- 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/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -3,16 +3,17 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 chrome.jar:
 % content branding %content/branding/
 % content browser %content/
 
+  content/arrow.svg                     (content/arrow.svg)
   content/dbg-browser-actors.js         (content/dbg-browser-actors.js)
   content/forms.js                      (content/forms.js)
   content/settings.js                   (content/settings.js)
 * content/shell.xul                     (content/shell.xul)
 * content/shell.js                      (content/shell.js)
 #ifndef ANDROID
   content/screen.js                     (content/screen.js)
 #endif
--- 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/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
@@ -111,26 +111,26 @@ let TestObserver = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
 
   observe: function test_observe(aSubject)
   {
     if (testEnded || !(aSubject instanceof Ci.nsIScriptError)) {
       return;
     }
 
-    is(aSubject.category, TESTS[pos].category,
-      "test #" + pos + ": error category '" + TESTS[pos].category + "'");
+    var expectedCategory = TESTS[pos].category;
 
-    if (aSubject.category == TESTS[pos].category) {
+    info("test #" + pos + " console observer got " + aSubject.category + ", is expecting " + expectedCategory);
+
+    if (aSubject.category == expectedCategory) {
       foundCategory = true;
     }
     else {
-      ok(false, aSubject.sourceName + ':' + aSubject.lineNumber + '; ' +
+      info("unexpected message was: " + aSubject.sourceName + ':' + aSubject.lineNumber + '; ' +
                 aSubject.errorMessage);
-      testEnded = true;
     }
   }
 };
 
 function consoleOpened(hud) {
   output = hud.outputNode;
   output.addEventListener("DOMNodeInserted", onDOMNodeInserted, false);
   jsterm = hud.jsterm;
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -115,16 +115,17 @@ distribution/extensions/testpilot@labs.m
 #endif
 extensions/talkback@mozilla.org/
 extensions/talkback@mozilla.org/chrome.manifest
 extensions/talkback@mozilla.org/components/@DLL_PREFIX@qfaservices@DLL_SUFFIX@
 extensions/talkback@mozilla.org/components/qfaservices.xpt
 extensions/talkback@mozilla.org/install.rdf
 extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/
 extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/install.rdf
+extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png
 extensions/testpilot@labs.mozilla.com/chrome.manifest
 extensions/testpilot@labs.mozilla.com/components/TestPilot.js
 extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
 extensions/testpilot@labs.mozilla.com/content/all-studies-window.xul
 extensions/testpilot@labs.mozilla.com/content/browser.css
 extensions/testpilot@labs.mozilla.com/content/browser.js
 extensions/testpilot@labs.mozilla.com/content/debug.html
 extensions/testpilot@labs.mozilla.com/content/experiment-page.js
--- 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/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -38,16 +38,18 @@ class B2GRemoteAutomation(Automation):
                  marionette=None, context_chrome=True):
         self._devicemanager = deviceManager
         self._appName = appName
         self._remoteProfile = None
         self._remoteLog = remoteLog
         self.marionette = marionette
         self.context_chrome = context_chrome
         self._is_emulator = False
+        self.test_script = None
+        self.test_script_args = None
 
         # Default our product to b2g
         self._product = "b2g"
         # Default log finish to mochitest standard
         self.logFinish = 'INFO SimpleTest FINISHED' 
         Automation.__init__(self)
 
     def setEmulator(self, is_emulator):
@@ -249,24 +251,24 @@ class B2GRemoteAutomation(Automation):
 
         # start the tests
         if hasattr(self, 'testURL'):
             # Start the tests by navigating to the mochitest url, by setting it
             # as the 'src' attribute to the homescreen mozbrowser element
             # provided by B2G's shell.js.
             self.marionette.execute_script("document.getElementById('homescreen').src='%s';" % self.testURL)
         # run the script that starts the tests
-        elif hasattr(self, 'testScript'):
-            if os.path.isfile(self.testScript):
-                script = open(self.testScript, 'r')
-                self.marionette.execute_script(script.read())
+        elif self.test_script:
+            if os.path.isfile(self.test_script):
+                script = open(self.test_script, 'r')
+                self.marionette.execute_script(script.read(), script_args=self.test_script_args)
                 script.close()
             else:
-                # assume testScript is a string
-                self.marionette.execute_script(self.testScript)
+                # assume test_script is a string
+                self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
         else:
             # assumes the tests are started on startup automatically
             pass
 
         return instance
 
     # be careful here as this inner class doesn't have access to outer class members
     class B2GInstance(object):
--- 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/client.py
+++ b/client.py
@@ -81,16 +81,31 @@ def do_cvs_export(modules, tag, cvsroot,
 
         (parent, leaf) = os.path.split(module)
         print "CVS export begin: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
         check_call_noisy([cvs, '-d', cvsroot,
                           'export', '-r', tag, '-d', leaf, cvs_module],
                          cwd=os.path.join(topsrcdir, parent))
         print "CVS export end: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
 
+def toggle_trailing_blank_line(depname):
+  """If the trailing line is empty, then we'll delete it.
+  Otherwise we'll add a blank line."""
+  lines = open(depname, "r").readlines()
+  if not lines:
+      print >>sys.stderr, "unexpected short file"
+      return
+
+  if not lines[-1].strip():
+      # trailing line is blank, removing it
+      open(depname, "w").writelines(lines[:-1])
+  else:
+      # adding blank line
+      open(depname, "a").write("\n")
+
 o = OptionParser(usage="client.py [options] update_nspr tagname | update_nss tagname | update_libffi tagname | update_webidlparser tagname")
 o.add_option("--skip-mozilla", dest="skip_mozilla",
              action="store_true", default=False,
              help="Obsolete")
 
 o.add_option("--cvs", dest="cvs", default=os.environ.get('CVS', 'cvs'),
              help="The location of the cvs binary")
 o.add_option("--cvsroot", dest="cvsroot",
@@ -109,23 +124,25 @@ if action in ('checkout', 'co'):
     print >>sys.stderr, "Warning: client.py checkout is obsolete."
     pass
 elif action in ('update_nspr'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
     do_cvs_export(NSPR_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("nsprpub/TAG-INFO", "w"), tag
+    toggle_trailing_blank_line("nsprpub/config/prdepend.h")
 elif action in ('update_nss'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
     do_cvs_export(NSS_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("security/nss/TAG-INFO", "w"), tag
     print >>file("security/nss/TAG-INFO-CKBI", "w"), tag
+    toggle_trailing_blank_line("security/coreconf/coreconf.dep")
 elif action in ('update_nssckbi'):
     tag, = args[1:]
     if not options.cvsroot:
         options.cvsroot = os.environ.get('CVSROOT', CVSROOT_MOZILLA)
     do_cvs_export(NSSCKBI_DIRS, tag, options.cvsroot, options.cvs)
     print >>file("security/nss/TAG-INFO-CKBI", "w"), tag
 elif action in ('update_libffi'):
     tag, = args[1:]
--- 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/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -12,17 +12,18 @@
 #include "nsError.h"
 #include "nsICharsetDetector.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIClassInfo.h"
 #include "nsIConverterInputStream.h"
 #include "nsIDocument.h"
 #include "nsIFileStreams.h"
 #include "nsIInputStream.h"
-#include "nsIIPCSerializable.h"
+#include "nsIIPCSerializableInputStream.h"
+#include "nsIIPCSerializableObsolete.h"
 #include "nsIMIMEService.h"
 #include "nsIPlatformCharset.h"
 #include "nsISeekableStream.h"
 #include "nsIUnicharInputStream.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsIUUIDGenerator.h"
@@ -42,63 +43,70 @@ using namespace mozilla::dom;
 
 // XXXkhuey the input stream that we pass out of a DOMFile
 // can outlive the actual DOMFile object.  Thus, we must
 // ensure that the buffer underlying the stream we get
 // from NS_NewByteInputStream is held alive as long as the
 // stream is.  We do that by passing back this class instead.
 class DataOwnerAdapter MOZ_FINAL : public nsIInputStream,
                                    public nsISeekableStream,
-                                   public nsIIPCSerializable,
-                                   public nsIClassInfo
+                                   public nsIIPCSerializableObsolete,
+                                   public nsIClassInfo,
+                                   public nsIIPCSerializableInputStream
 {
   typedef nsDOMMemoryFile::DataOwner DataOwner;
 public:
   static nsresult Create(DataOwner* aDataOwner,
                          PRUint32 aStart,
                          PRUint32 aLength,
                          nsIInputStream** _retval);
 
   NS_DECL_ISUPPORTS
 
   // These are mandatory.
   NS_FORWARD_NSIINPUTSTREAM(mStream->)
   NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
 
   // These are optional. We use a conditional QI to keep them from being called
   // if the underlying stream doesn't QI to either interface.
-  NS_FORWARD_NSIIPCSERIALIZABLE(mSerializable->)
+  NS_FORWARD_NSIIPCSERIALIZABLEOBSOLETE(mSerializableObsolete->)
   NS_FORWARD_NSICLASSINFO(mClassInfo->)
+  NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
 
 private:
   DataOwnerAdapter(DataOwner* aDataOwner,
                    nsIInputStream* aStream)
     : mDataOwner(aDataOwner), mStream(aStream),
       mSeekableStream(do_QueryInterface(aStream)),
-      mSerializable(do_QueryInterface(aStream)),
-      mClassInfo(do_QueryInterface(aStream))
+      mSerializableObsolete(do_QueryInterface(aStream)),
+      mClassInfo(do_QueryInterface(aStream)),
+      mSerializableInputStream(do_QueryInterface(aStream))
   {
     NS_ASSERTION(mSeekableStream, "Somebody gave us the wrong stream!");
   }
 
   nsRefPtr<DataOwner> mDataOwner;
   nsCOMPtr<nsIInputStream> mStream;
   nsCOMPtr<nsISeekableStream> mSeekableStream;
-  nsCOMPtr<nsIIPCSerializable> mSerializable;
+  nsCOMPtr<nsIIPCSerializableObsolete> mSerializableObsolete;
   nsCOMPtr<nsIClassInfo> mClassInfo;
+  nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
 };
 
 NS_IMPL_THREADSAFE_ADDREF(DataOwnerAdapter)
 NS_IMPL_THREADSAFE_RELEASE(DataOwnerAdapter)
 
 NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializable, mSerializable)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableObsolete,
+                                     mSerializableObsolete)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIClassInfo, mClassInfo)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
+                                     mSerializableInputStream)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
 
 nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
                                   PRUint32 aStart,
                                   PRUint32 aLength,
                                   nsIInputStream** _retval)
 {
--- 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/public/nsEventNameList.h
+++ b/content/events/public/nsEventNameList.h
@@ -312,16 +312,20 @@ EVENT(timeupdate,
 EVENT(volumechange,
       NS_VOLUMECHANGE,
       EventNameType_HTML,
       NS_EVENT_NULL)
 EVENT(waiting,
       NS_WAITING,
       EventNameType_HTML,
       NS_EVENT_NULL)
+EVENT(wheel,
+      NS_WHEEL_WHEEL,
+      EventNameType_All,
+      NS_WHEEL_EVENT)
 // Gecko-specific extensions that apply to elements
 EVENT(copy,
       NS_COPY,
       EventNameType_HTMLXUL,
       NS_EVENT)
 EVENT(cut,
       NS_CUT,
       EventNameType_HTMLXUL,
@@ -595,20 +599,16 @@ NON_IDL_EVENT(draggesture,
 NON_IDL_EVENT(overflow,
               NS_SCROLLPORT_OVERFLOW,
               EventNameType_XUL,
               NS_EVENT_NULL)
 NON_IDL_EVENT(underflow,
               NS_SCROLLPORT_UNDERFLOW,
               EventNameType_XUL,
               NS_EVENT_NULL)
-NON_IDL_EVENT(wheel,
-              NS_WHEEL_WHEEL,
-              EventNameType_XUL,
-              NS_WHEEL_EVENT)
 
 // Various SVG events
 NON_IDL_EVENT(SVGLoad,
               NS_SVG_LOAD,
               EventNameType_None,
               NS_SVG_EVENT)
 NON_IDL_EVENT(SVGUnload,
               NS_SVG_UNLOAD,
--- 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/test_dom_wheel_event.html
+++ b/content/events/test/test_dom_wheel_event.html
@@ -647,16 +647,52 @@ function testEventOrder()
   window.removeEventListener("DOMMouseScroll", handler, true);
   window.removeEventListener("MozMousePixelScroll", handler, true);
 
   SpecialPowers.removeSystemEventListener(window, "wheel", systemHandler, true);
   SpecialPowers.removeSystemEventListener(window, "DOMMouseScroll", systemHandler, true);
   SpecialPowers.removeSystemEventListener(window, "MozMousePixelScroll", systemHandler, true);
 }
 
+var gOnWheelAttrHandled = new Array;
+
+function testOnWheelAttr()
+{
+  document.documentElement.setAttribute("onwheel", "gOnWheelAttrHandled['html'] = true;");
+  document.body.setAttribute("onwheel", "gOnWheelAttrHandled['body'] = true;");
+  gScrollableElement.setAttribute("onwheel", "gOnWheelAttrHandled['div'] = true;");
+  var target = document.getElementById("onwheel");
+  synthesizeWheel(gScrollableElement, 10, 10,
+                  { deltaMode: WheelEvent.DOM_DELTA_LINE,
+                    deltaX: 1.0, deltaY: 2.0 });
+  ok(gOnWheelAttrHandled['html'], "html element's onwheel attribute isn't performed");
+  ok(gOnWheelAttrHandled['body'], "body element's onwheel attribute isn't performed");
+  ok(gOnWheelAttrHandled['div'], "div element's onwheel attribute isn't performed");
+}
+
+var gOnWheelPropHandled = new Array;
+
+function testOnWheelProperty()
+{
+  window.onwheel = function (e) { gOnWheelPropHandled["window"] = true; }
+  document.onwheel = function (e) { gOnWheelPropHandled["document"] = true; }
+  document.documentElement.onwheel = function (e) { gOnWheelPropHandled["html"] = true; };
+  document.body.onwheel = function (e) { gOnWheelPropHandled["body"] = true; };
+  gScrollableElement.onwheel = function (e) { gOnWheelPropHandled["div"] = true; };
+  var target = document.getElementById("onwheel");
+  synthesizeWheel(gScrollableElement, 10, 10,
+                  { deltaMode: WheelEvent.DOM_DELTA_LINE,
+                    deltaX: 1.0, deltaY: 2.0 });
+  ok(gOnWheelPropHandled['window'], "window's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['document'], "document's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['html'], "html element's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['body'], "body element's onwheel property isn't performed");
+  ok(gOnWheelPropHandled['div'], "div element's onwheel property isn't performed");
+}
+
 function runTests()
 {
   SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_x", 100);
   SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_y", 100);
   SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_z", 100);
   SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_x", 100);
   SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_y", 100);
   SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_z", 100);
@@ -673,16 +709,18 @@ function runTests()
   SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_y", 100);
   SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_z", 100);
 
   prepareScrollUnits();
   testMakingUntrustedEvent();
   testDeltaMultiplierPrefs();
   testDispatchingUntrustEvent();
   testEventOrder();
+  testOnWheelAttr();
+  testOnWheelProperty();
 
   SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_x");
   SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_y");
   SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_z");
   SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_x");
   SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_y");
   SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_z");
   SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_x");
--- 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/docshell/base/SerializedLoadContext.h
+++ b/docshell/base/SerializedLoadContext.h
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef SerializedLoadContext_h
 #define SerializedLoadContext_h
 
 #include "base/basictypes.h"
 #include "IPC/IPCMessageUtils.h"
-#include "nsIIPCSerializable.h"
 #include "nsILoadContext.h"
 
 /*
  *  This file contains the IPC::SerializedLoadContext class, which is used to
  *  copy data across IPDL from Child process contexts so it is available in the
  *  Parent.
  */
 
--- 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
           });
         }
       };
@@ -243,17 +246,21 @@ let Activities = {
     let errorCb = function errorCb(aError) {
       // Something unexpected happened. Should we send an error back?
       debug("Error in startActivity: " + aError + "\n");
     };
 
     let matchFunc = function matchFunc(aResult) {
       // Bug 773383: arrays of strings / regexp.
       for (let prop in aResult.description.filters) {
-        if (aMsg.options.data[prop] !== aResult.description.filters[prop]) {
+        if (Array.isArray(aResult.description.filters[prop])) {
+          if (aResult.description.filters[prop].indexOf(aMsg.options.data[prop]) == -1) {
+            return false;
+          }
+        } else if (aResult.description.filters[prop] !== aMsg.options.data[prop] ) {
           return false;
         }
       }
       return true;
     };
 
     this.db.find(aMsg, successCb, errorCb, matchFunc);
   },
--- 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
@@ -34,16 +34,18 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 XPCOMUtils.defineLazyGetter(this, "msgmgr", function() {
   return Cc["@mozilla.org/system-message-internal;1"]
          .getService(Ci.nsISystemMessagesInternal);
 });
 
 #ifdef MOZ_WIDGET_GONK
   const DIRECTORY_NAME = "webappsDir";
+#elifdef ANDROID
+  const DIRECTORY_NAME = "webappsDir";
 #else
   // If we're executing in the context of the webapp runtime, the data files
   // are in a different directory (currently the Firefox profile that installed
   // the webapp); otherwise, they're in the current profile.
   const DIRECTORY_NAME = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
 #endif
 
 let DOMApplicationRegistry = {
@@ -53,17 +55,17 @@ let DOMApplicationRegistry = {
 
   init: function() {
     this.messages = ["Webapps:Install", "Webapps:Uninstall",
                     "Webapps:GetSelf",
                     "Webapps:GetInstalled", "Webapps:GetNotInstalled",
                     "Webapps:Launch", "Webapps:GetAll",
                     "Webapps:InstallPackage", "Webapps:GetBasePath",
                     "WebApps:GetAppByManifestURL", "WebApps:GetAppLocalIdByManifestURL",
-                    "WebApps:GetAppByLocalId", "Webapps:GetManifestURLByLocalId"];
+                    "WebApps:GetAppByLocalId", "WebApps:GetManifestURLByLocalId"];
 
     this.messages.forEach((function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }).bind(this));
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
 
     this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
@@ -109,16 +111,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/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -35,19 +35,21 @@ public:
   {
   }
   
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (!mEnabled || gInShutdown) {
-      nsCOMPtr<nsIThread> t;
-      gBluetoothService->mBluetoothCommandThread.swap(t);
-      t->Shutdown();
+      if (gBluetoothService->mBluetoothCommandThread) {
+        nsCOMPtr<nsIThread> t;
+        gBluetoothService->mBluetoothCommandThread.swap(t);
+        t->Shutdown();
+      }
     }
     
     if (gInShutdown) {
       gBluetoothService = nullptr;
     }
 
     return NS_OK;
   }
--- 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/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -74,60 +74,61 @@ ContactAddress.prototype = {
                                      contractID: CONTACTADDRESS_CONTRACTID,
                                      classDescription: "ContactAddress",
                                      interfaces: [nsIDOMContactAddress],
                                      flags: nsIClassInfo.DOM_OBJECT}),
 
   QueryInterface : XPCOMUtils.generateQI([nsIDOMContactAddress])
 }
 
-//ContactEmail
+//ContactField
 
-const CONTACTEMAIL_CONTRACTID = "@mozilla.org/contactEmail;1";
-const CONTACTEMAIL_CID        = Components.ID("{94811520-c11f-11e1-afa7-0800200c9a66}");
-const nsIDOMContactEmail      = Components.interfaces.nsIDOMContactEmail;
+const CONTACTFIELD_CONTRACTID = "@mozilla.org/contactField;1";
+const CONTACTFIELD_CID        = Components.ID("{e2cb19c0-e4aa-11e1-9b23-0800200c9a66}");
+const nsIDOMContactField      = Components.interfaces.nsIDOMContactField;
 
-function ContactEmail(aType, aAddress) {
+function ContactField(aType, aValue) {
   this.type = aType || null;
-  this.address = aAddress || null;
+  this.value = aValue || null;
 };
 
-ContactEmail.prototype = {
+ContactField.prototype = {
 
-  classID : CONTACTEMAIL_CID,
-  classInfo : XPCOMUtils.generateCI({classID: CONTACTEMAIL_CID,
-                                     contractID: CONTACTEMAIL_CONTRACTID,
-                                     classDescription: "ContactEmail",
-                                     interfaces: [nsIDOMContactEmail],
+  classID : CONTACTFIELD_CID,
+  classInfo : XPCOMUtils.generateCI({classID: CONTACTFIELD_CID,
+                                     contractID: CONTACTFIELD_CONTRACTID,
+                                     classDescription: "ContactField",
+                                     interfaces: [nsIDOMContactField],
                                      flags: nsIClassInfo.DOM_OBJECT}),
 
-  QueryInterface : XPCOMUtils.generateQI([nsIDOMContactEmail])
+  QueryInterface : XPCOMUtils.generateQI([nsIDOMContactField])
 }
 
-//ContactTelephone
+//ContactTelField
 
-const CONTACTTELEPHONE_CONTRACTID = "@mozilla.org/contactTelephone;1";
-const CONTACTTELEPHONE_CID        = Components.ID("{82601b20-89e8-11e1-b0c4-0800200c9a66}");
-const nsIDOMContactTelephone      = Components.interfaces.nsIDOMContactTelephone;
+const CONTACTTELFIELD_CONTRACTID = "@mozilla.org/contactTelField;1";
+const CONTACTTELFIELD_CID        = Components.ID("{ed0ab260-e4aa-11e1-9b23-0800200c9a66}");
+const nsIDOMContactTelField      = Components.interfaces.nsIDOMContactTelField;
 
-function ContactTelephone(aType, aNumber) {
+function ContactTelField(aType, aValue, aCarrier) {
   this.type = aType || null;
-  this.number = aNumber || null;
+  this.value = aValue || null;
+  this.carrier = aCarrier || null;
 };
 
-ContactTelephone.prototype = {
+ContactTelField.prototype = {
 
-  classID : CONTACTTELEPHONE_CID,
-  classInfo : XPCOMUtils.generateCI({classID: CONTACTTELEPHONE_CID,
-                                     contractID: CONTACTTELEPHONE_CONTRACTID,
-                                     classDescription: "ContactTelephone",
-                                     interfaces: [nsIDOMContactTelephone],
+  classID : CONTACTTELFIELD_CID,
+  classInfo : XPCOMUtils.generateCI({classID: CONTACTTELFIELD_CID,
+                                     contractID: CONTACTTELFIELD_CONTRACTID,
+                                     classDescription: "ContactTelField",
+                                     interfaces: [nsIDOMContactTelField],
                                      flags: nsIClassInfo.DOM_OBJECT}),
 
-  QueryInterface : XPCOMUtils.generateQI([nsIDOMContactTelephone])
+  QueryInterface : XPCOMUtils.generateQI([nsIDOMContactTelField])
 }
 
 //ContactFindOptions
 
 const CONTACTFINDOPTIONS_CONTRACTID = "@mozilla.org/contactFindOptions;1";
 const CONTACTFINDOPTIONS_CID        = Components.ID("{e31daea0-0cb6-11e1-be50-0800200c9a66}");
 const nsIDOMContactFindOptions      = Components.interfaces.nsIDOMContactFindOptions;
 
@@ -191,23 +192,22 @@ Contact.prototype = {
     this.familyName =      _create(aProp.familyName) || null;
     this.honorificSuffix = _create(aProp.honorificSuffix) || null;
     this.nickname =        _create(aProp.nickname) || null;
 
     if (aProp.email) {
       aProp.email = Array.isArray(aProp.email) ? aProp.email : [aProp.email];
       this.email = new Array();
       for (let i = 0; i < aProp.email.length; i++)
-        this.email.push(new ContactEmail(aProp.email[i].type, aProp.email[i].address));
+        this.email.push(new ContactField(aProp.email[i].type, aProp.email[i].value));
     } else {
       this.email = null;
     }
 
     this.photo =           _checkBlobArray(aProp.photo) || null;
-    this.url =             _create(aProp.url) || null;
     this.category =        _create(aProp.category) || null;
 
     if (aProp.adr) {
       // Make sure adr argument is an array. Instanceof doesn't work.
       aProp.adr = Array.isArray(aProp.adr) ? aProp.adr : [aProp.adr];
 
       this.adr = new Array();
       for (let i = 0; i < aProp.adr.length; i++)
@@ -216,26 +216,44 @@ Contact.prototype = {
     } else {
       this.adr = null;
     }
 
     if (aProp.tel) {
       aProp.tel = Array.isArray(aProp.tel) ? aProp.tel : [aProp.tel];
       this.tel = new Array();
       for (let i = 0; i < aProp.tel.length; i++)
-        this.tel.push(new ContactTelephone(aProp.tel[i].type, aProp.tel[i].number));
+        this.tel.push(new ContactTelField(aProp.tel[i].type, aProp.tel[i].value, aProp.tel[i].carrier));
     } else {
       this.tel = null;
     }
 
     this.org =             _create(aProp.org) || null;
     this.jobTitle =        _create(aProp.jobTitle) || null;
     this.bday =            (aProp.bday == "undefined" || aProp.bday == null) ? null : new Date(aProp.bday);
     this.note =            _create(aProp.note) || null;
-    this.impp =            _create(aProp.impp) || null;
+
+    if (aProp.impp) {
+      aProp.impp = Array.isArray(aProp.impp) ? aProp.impp : [aProp.impp];
+      this.impp = new Array();
+      for (let i = 0; i < aProp.impp.length; i++)
+        this.impp.push(new ContactField(aProp.impp[i].type, aProp.impp[i].value));
+    } else {
+      this.impp = null;
+    }
+
+    if (aProp.url) {
+      aProp.url = Array.isArray(aProp.url) ? aProp.url : [aProp.url];
+      this.url = new Array();
+      for (let i = 0; i < aProp.url.length; i++)
+        this.url.push(new ContactField(aProp.url[i].type, aProp.url[i].value));
+    } else {
+      this.url = null;
+    }
+
     this.anniversary =     (aProp.anniversary == "undefined" || aProp.anniversary == null) ? null : new Date(aProp.anniversary);
     this.sex =             (aProp.sex != "undefined") ? aProp.sex : null;
     this.genderIdentity =  (aProp.genderIdentity != "undefined") ? aProp.genderIdentity : null;
   },
 
   get published () {
     return this._published;
   },
@@ -534,9 +552,9 @@ ContactManager.prototype = {
   classInfo : XPCOMUtils.generateCI({classID: CONTACTMANAGER_CID,
                                      contractID: CONTACTMANAGER_CONTRACTID,
                                      classDescription: "ContactManager",
                                      interfaces: [nsIDOMContactManager],
                                      flags: nsIClassInfo.DOM_OBJECT})
 }
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory(
-                       [Contact, ContactManager, ContactProperties, ContactAddress, ContactTelephone, ContactFindOptions, ContactEmail])
+                       [Contact, ContactManager, ContactProperties, ContactAddress, ContactField, ContactTelField, ContactFindOptions])
--- a/dom/contacts/ContactManager.manifest
+++ b/dom/contacts/ContactManager.manifest
@@ -1,19 +1,19 @@
 component {f5181640-89e8-11e1-b0c4-0800200c9a66} ContactManager.js
 contract @mozilla.org/contactProperties;1 {f5181640-89e8-11e1-b0c4-0800200c9a66}
 
 component {eba48030-89e8-11e1-b0c4-0800200c9a66} ContactManager.js
 contract @mozilla.org/contactAddress;1 {eba48030-89e8-11e1-b0c4-0800200c9a66}
 
-component {82601b20-89e8-11e1-b0c4-0800200c9a66} ContactManager.js
-contract @mozilla.org/contactTelephone;1 {82601b20-89e8-11e1-b0c4-0800200c9a66}
+component {e2cb19c0-e4aa-11e1-9b23-0800200c9a66} ContactManager.js
+contract @mozilla.org/contactField;1 {e2cb19c0-e4aa-11e1-9b23-0800200c9a66}
 
-component {94811520-c11f-11e1-afa7-0800200c9a66} ContactManager.js
-contract @mozilla.org/contactEmail;1 {94811520-c11f-11e1-afa7-0800200c9a66}
+component {ed0ab260-e4aa-11e1-9b23-0800200c9a66} ContactManager.js
+contract @mozilla.org/contactTelField;1 {ed0ab260-e4aa-11e1-9b23-0800200c9a66}
 
 component {e31daea0-0cb6-11e1-be50-0800200c9a66} ContactManager.js
 contract @mozilla.org/contactFindOptions;1 {e31daea0-0cb6-11e1-be50-0800200c9a66}
 
 component {da0f7040-388b-11e1-b86c-0800200c9a66} ContactManager.js
 contract @mozilla.org/contact;1 {da0f7040-388b-11e1-b86c-0800200c9a66}
 category JavaScript-global-constructor mozContact @mozilla.org/contact;1
 
--- a/dom/contacts/fallback/ContactDB.jsm
+++ b/dom/contacts/fallback/ContactDB.jsm
@@ -17,17 +17,17 @@ if (DEBUG) {
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 
 const DB_NAME = "contacts";
-const DB_VERSION = 3;
+const DB_VERSION = 4;
 const STORE_NAME = "contacts";
 
 function ContactDB(aGlobal) {
   debug("Constructor");
   this._global = aGlobal;
 }
 
 ContactDB.prototype = {
@@ -121,16 +121,47 @@ ContactDB.prototype = {
             cursor.update(cursor.value);
             debug("upgrade email2: " + JSON.stringify(cursor.value));
             cursor.continue();
           }
         };
 
         // Create new searchable indexes.
         objectStore.createIndex("email", "search.email", { unique: false, multiEntry: true });
+      } else if (currVersion == 3) {
+        debug("upgrade 3");
+
+        if (!objectStore) {
+          objectStore = aTransaction.objectStore(STORE_NAME);
+        }
+
+        // Upgrade existing impp field in the DB.
+        objectStore.openCursor().onsuccess = function(event) {
+          let cursor = event.target.result;
+          if (cursor) {
+            debug("upgrade impp1: " + JSON.stringify(cursor.value));
+            cursor.value.properties.impp =
+              cursor.value.properties.impp.map(function(value) { return { value: value }; });
+            cursor.update(cursor.value);
+            debug("upgrade impp2: " + JSON.stringify(cursor.value));
+            cursor.continue();
+          }
+        };
+        // Upgrade existing url field in the DB.
+        objectStore.openCursor().onsuccess = function(event) {
+          let cursor = event.target.result;
+          if (cursor) {
+            debug("upgrade url1: " + JSON.stringify(cursor.value));
+            cursor.value.properties.url =
+              cursor.value.properties.url.map(function(value) { return { value: value }; });
+            cursor.update(cursor.value);
+            debug("upgrade impp2: " + JSON.stringify(cursor.value));
+            cursor.continue();
+          }
+        };
       }
     }
   },
 
   makeImport: function makeImport(aContact) {
     let contact = {};
     contact.properties = {
       name:            [],
@@ -179,34 +210,41 @@ ContactDB.prototype = {
       if (aContact.properties[field] && contact.search[field]) {
         for (let i = 0; i <= aContact.properties[field].length; i++) {
           if (aContact.properties[field][i]) {
             if (field == "tel") {
               // Special case telephone number.
               // "+1-234-567" should also be found with 1234, 234-56, 23456
 
               // Chop off the first characters
-              let number = aContact.properties[field][i].number;
-              for(let i = 0; i < number.length; i++) {
-                contact.search[field].push(number.substring(i, number.length));
+              let number = aContact.properties[field][i].value;
+              if (number) {
+                for (let i = 0; i < number.length; i++) {
+                  contact.search[field].push(number.substring(i, number.length));
+                }
+                // Store +1-234-567 as ["1234567", "234567"...]
+                let digits = number.match(/\d/g);
+                if (digits && number.length != digits.length) {
+                  digits = digits.join('');
+                  for(let i = 0; i < digits.length; i++) {
+                    contact.search[field].push(digits.substring(i, digits.length));
+                  }
+                }
+              debug("lookup: " + JSON.stringify(contact.search[field]));
               }
-              // Store +1-234-567 as ["1234567", "234567"...]
-              let digits = number.match(/\d/g);
-              if (digits && number.length != digits.length) {
-                digits = digits.join('');
-                for(let i = 0; i < digits.length; i++) {
-                  contact.search[field].push(digits.substring(i, digits.length));
-                }
-              }
-              debug("lookup: " + JSON.stringify(contact.search[field]));
             } else if (field == "email") {
-              let address = aContact.properties[field][i].address;
+              let address = aContact.properties[field][i].value;
               if (address && typeof address == "string") {
                 contact.search[field].push(address.toLowerCase());
               }
+            } else if (field == "impp") {
+              let value = aContact.properties[field][i].value;
+              if (value && typeof value == "string") {
+                contact.search[field].push(value.toLowerCase());
+              }
             } else {
               let val = aContact.properties[field][i];
               if (typeof val == "string") {
                 contact.search[field].push(val.toLowerCase());
               }
             }
           }
         }
--- a/dom/contacts/tests/test_contacts_basics.html
+++ b/dom/contacts/tests/test_contacts_basics.html
@@ -73,39 +73,39 @@ var adr2 = {
   countryName: "country2"
 };
 
 var properties1 = {
   name: "Testname1",
   familyName: ["TestFamilyName","Wagner"],
   givenName: ["Test1","Test2"],
   nickname: "nicktest",
-  tel: [{type: "work", number: "123456"} , {type: "home", number: "+9-876-5432"}],
+  tel: [{type: ["work"], value: "123456", carrier: "testCarrier"} , {type: ["home", "fax"], value: "+9-876-5432"}],
   adr: adr1,
-  email: [{type: "work", address: "x@y.com"}]
+  email: [{type: ["work"], value: "x@y.com"}]
 };
 
 var properties2 = {
   name: ["dummyName", "dummyName2"],
   familyName: "dummyFamilyName",
   givenName: "dummyGivenName",
   honorificPrefix: ["dummyHonorificPrefix","dummyHonorificPrefix2"],
   honorificSuffix: "dummyHonorificSuffix",
   additionalName: "dummyadditionalName",
   nickname: "dummyNickname",
-  tel: [{type: "test", number: "123456789"},{type: "home", number: "234567890"}],
-  email: [{type: "test", address: "a@b.c"}, {address: "b@c.d"}],
+  tel: [{type: ["test"], value: "123456789"},{type: ["home", "custom"], value: "234567890"}],
+  email: [{type: ["test"], value: "a@b.c"}, {value: "b@c.d"}],
   adr: [adr1, adr2],
-  impp: ["im1", "im2"],
+  impp: [{type: ["aim"], value:"im1"}, {value: "im2"}],
   org: ["org1", "org2"],
   jobTitle: ["boss", "superboss"],
   bday: new Date("1980, 12, 01"),
   note: "test note",
   category: ["cat1", "cat2"],
-  url: ["www.1.com", "www.2.com"],
+  url: [{type: ["work", "work2"], value: "www.1.com"}, {value:"www2.com"}],
   anniversary: new Date("2000, 12, 01"),
   sex: "male",
   genderIdentity: "test"
 };
 
 var sample_id1;
 var sample_id2;
 
@@ -143,49 +143,87 @@ function checkAddress(adr1, adr2) {
   checkStr(adr1.locality, adr2.locality, "Same locality");
   checkStr(adr1.region, adr2.region, "Same region");
   checkStr(adr1.postalCode, adr2.postalCode, "Same postalCode");
   checkStr(adr1.countryName, adr2.countryName, "Same countryName");
 }
 
 function checkTel(tel1, tel2) {
   checkStr(tel1.type, tel2.type, "Same type");
-  checkStr(tel1.number, tel2.number, "Same number");
+  checkStr(tel1.value, tel2.value, "Same value");
+  checkStr(tel1.carrier, tel2.carrier, "Same carrier");
 }
 
-function checkEmail(email1, email2) {
-  checkStr(email1.type, email2.type, "Same type");
-  checkStr(email1.address, email2.address, "Same address");
+function checkField(field1, field2) {
+  checkStr(field1.type, field1.type, "Same type");
+  checkStr(field1.value, field1.value, "Same value");
 }
 
 function checkContacts(contact1, contact2) {
   checkStr(contact1.name, contact2.name, "Same name");
   checkStr(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
   checkStr(contact1.givenName, contact2.givenName, "Same givenName");
   checkStr(contact1.additionalName, contact2.additionalName, "Same additionalName");
   checkStr(contact1.familyName, contact2.familyName, "Same familyName");
   checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
   checkStr(contact1.nickname, contact2.nickname, "Same nickname");
-  checkStr(contact1.url, contact2.url, "Same url");
   checkStr(contact1.category, contact2.category, "Same category");
   checkStr(contact1.org, contact2.org, "Same org");
   checkStr(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
   is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
   checkStr(contact1.note, contact2.note, "Same note");
-  checkStr(contact1.impp, contact2.impp, "Same impp");
   is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
   is(contact1.sex, contact2.sex, "Same sex");
   is(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
 
-  for (var i in contact1.email)
-    checkEmail(contact1.email[i], contact2.email[i]);
-  for (var i in contact1.adr)
+  for (var i in contact1.email) {
+    if (contact1.email) {
+      ok(contact2.email != null, "conatct2.email exists");
+    }
+    if (contact2.email) {
+      ok(contact1.email != null, "conatct1.email exists");
+    }
+    checkField(contact1.email[i], contact2.email[i]);
+  }
+  for (var i in contact1.adr) {
+    if (contact1.adr) {
+      ok(contact2.adr != null, "conatct2.adr exists");
+    }
+    if (contact2.adr) {
+      ok(contact1.adr != null, "conatct1.adr exists");
+    }
     checkAddress(contact1.adr[i], contact2.adr[i]);
-  for (var i in contact1.tel)
+  }
+  for (var i in contact1.tel) {
+    if (contact1.tel) {
+      ok(contact2.tel != null, "conatct2.tel exists");
+    }
+    if (contact2.tel) {
+      ok(contact1.tel != null, "conatct1.tel exists");
+    }
     checkTel(contact1.tel[i], contact2.tel[i]);
+  }
+  for (var i in contact1.url) {
+    if (contact1.url) {
+      ok(contact2.url != null, "conatct2.url exists");
+    }
+    if (contact2.url) {
+      ok(contact1.url != null, "conatct1.url exists");
+    }
+    checkField(contact1.url[i], contact2.url[i]);
+  }
+  for (var i in contact1.impp) {
+    if (contact1.impp) {
+      ok(contact2.impp != null, "conatct2.impp exists");
+    }
+    if (contact2.impp) {
+      ok(contact1.impp != null, "conatct1.impp exists");
+    }
+    checkField(contact1.impp[i], contact2.impp[i]);
+  }
 }
 
 var req;
 var index = 0;
 
 var mozContacts = window.navigator.mozContacts
 
 var steps = [
@@ -276,17 +314,17 @@ var steps = [
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching for exact email");
     var options = {filterBy: ["email"],
                    filterOp: "equals",
-                   filterValue: properties1.email[0].address};
+                   filterValue: properties1.email[0].value};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
       checkContacts(findResult1, createResult1);
       next();
     };
@@ -415,17 +453,17 @@ var steps = [
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Retrieving by substring tel1");
     var options = {filterBy: ["tel"],
                    filterOp: "contains",
-                   filterValue: properties1.tel[1].number.substring(1,5)};
+                   filterValue: properties1.tel[1].value.substring(1,5)};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
       checkContacts(createResult1, properties1);
       next();
     };
@@ -517,17 +555,17 @@ var steps = [
       ok(findResult1.updated, "Has updated field");
       ok(findResult1.published, "Has published field");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Modifying contact1");
-    findResult1.impp = properties1.impp = (["phil impp"]);
+    findResult1.impp = properties1.impp = [{value:"phil impp"}];
     req = navigator.mozContacts.save(findResult1);
     req.onsuccess = function () {
       var req2 = mozContacts.find({});
       req2.onsuccess = function() {
         ok(req2.result.length == 1, "Found exactly 1 contact.");
         findResult2 = req2.result[0];
         ok(findResult2.id == sample_id1, "Same ID");
         checkContacts(findResult2, properties1);
@@ -549,47 +587,47 @@ var steps = [
     var options = {filterBy: ["id"],
                    filterOp: "equals",
                    filterValue: sample_id1};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
-      checkContacts(createResult1, properties1);
+      checkContacts(findResult1, properties1);
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Retrieving a specific contact by givenName");
     var options = {filterBy: ["givenName"],
                    filterOp: "equals",
                    filterValue: properties1.givenName[0]};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
-      checkContacts(findResult1, createResult1);
+      checkContacts(findResult1, properties1);
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Modifying contact2");
-    findResult1.impp = properties1.impp = (["phil impp"]);
+    findResult1.impp = properties1.impp = [{value: "phil impp"}];
     req = mozContacts.save(findResult1);
     req.onsuccess = function () {
       var req2 = mozContacts.find({});
       req2.onsuccess = function () {
         ok(req2.result.length == 1, "Found exactly 1 contact.");
         findResult1 = req2.result[0];
         ok(findResult1.id == sample_id1, "Same ID");
-        checkContacts(findResult1, createResult1);
+        checkContacts(findResult1, properties1);
         ok(findResult1.impp.length == 1, "Found exactly 1 IMS info.");
         next();
       }
       req2.onerror = onFailure;
     };
     req.onerror = onFailure;
   },
   function () {
@@ -597,54 +635,54 @@ var steps = [
     var options = {filterBy: ["name", "email"],
                    filterOp: "contains",
                    filterValue: properties1.name[0].substring(0,4)};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
-      checkContacts(findResult1, createResult1);
+      checkContacts(findResult1, properties1);
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching contacts by query");
     var options = {filterBy: ["nickname", "email"],
                    filterOp: "contains",
                    filterValue: properties1.nickname};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
-      checkContacts(findResult1, createResult1);
+      checkContacts(findResult1, properties1);
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching contacts with multiple indices");
     var options = {filterBy: ["nickname", "email", "name"],
                    filterOp: "equals",
                    filterValue: properties1.nickname};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id1, "Same ID");
-      checkContacts(findResult1, createResult1);
+      checkContacts(findResult1, properties1);
       next();
     };
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Modifying contact3");
-    findResult1.email = [{address: properties1.nickname}];
+    findResult1.email = [{value: properties1.nickname}];
     findResult1.nickname = "TEST";
     var newContact = new mozContact();
     newContact.init(findResult1);
     req = mozContacts.save(newContact);
     req.onsuccess = function () {
       var options = {filterBy: ["nickname", "email", "name"],
                      filterOp: "contains",
                      filterValue: properties1.nickname};
@@ -744,32 +782,32 @@ var steps = [
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching contacts by tel");
     var options = {filterBy: ["tel"],
                    filterOp: "contains",
-                   filterValue: properties2.tel[0].number.substring(0, 7)};
+                   filterValue: properties2.tel[0].value.substring(0, 7)};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id2, "Same ID");
       checkContacts(findResult1, createResult2);
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Searching contacts by email");
     var options = {filterBy: ["email"],
                    filterOp: "contains",
-                   filterValue: properties2.email[0].address.substring(0, 4)};
+                   filterValue: properties2.email[0].value.substring(0, 4)};
     req = mozContacts.find(options);
     req.onsuccess = function () {
       ok(req.result.length == 1, "Found exactly 1 contact.");
       findResult1 = req.result[0];
       ok(findResult1.id == sample_id2, "Same ID");
       checkContacts(findResult1, createResult2);
       next();
     }
@@ -883,22 +921,22 @@ var steps = [
       next();
     }
     req.onerror = onFailure;
   },
   function() {
     ok(true, "Testing clone contact2");
     var cloned = new mozContact(createResult1);
     ok(cloned.id != createResult1.id, "Cloned contact has new ID");
-    cloned.email = {address: "new email!"};
+    cloned.email = {value: "new email!"};
     cloned.givenName = "Tom";
     req = mozContacts.save(cloned);
     req.onsuccess = function () {
       ok(cloned.id, "The contact now has an ID.");
-      ok(cloned.email.address == "new email!", "Same Email");
+      ok(cloned.email.value == "new email!", "Same Email");
       ok(createResult1.email != cloned.email, "Clone has different email");
       ok(cloned.givenName == "Tom", "New Name");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Retrieving all contacts");
@@ -910,17 +948,17 @@ var steps = [
       ok(req.result.length == 2, "2 Entries.");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
     ok(true, "Search with redundant fields should only return 1 contact");
     createResult1 = new mozContact();
-    createResult1.init({name: "XXX", nickname: "XXX", email: [{address: "XXX"}], tel: {number: "XXX"}});
+    createResult1.init({name: "XXX", nickname: "XXX", email: [{value: "XXX"}], tel: {value: "XXX"}});
     req = mozContacts.save(createResult1);
     req.onsuccess = function() {
       var options = {filterBy: [],
                      filterOp: "equals",
                      filterValue: "XXX"};
       var req2 = mozContacts.find(options);
       req2.onsuccess = function() {
         ok(req2.result.length == 1, "1 Entry");
--- 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/interfaces/contacts/nsIDOMContactProperties.idl
+++ b/dom/interfaces/contacts/nsIDOMContactProperties.idl
@@ -13,58 +13,57 @@ interface nsIDOMContactAddress : nsISupp
   attribute DOMString type;
   attribute DOMString streetAddress;
   attribute DOMString locality;
   attribute DOMString region;
   attribute DOMString postalCode;
   attribute DOMString countryName;
 };
 
-[scriptable, uuid(82601b20-89e8-11e1-b0c4-0800200c9a66)]
-interface nsIDOMContactTelephone : nsISupports
+[scriptable, uuid(e2cb19c0-e4aa-11e1-9b23-0800200c9a66)]
+interface nsIDOMContactField : nsISupports
 {
-  attribute DOMString type;
-  attribute DOMString number;
+  attribute jsval type; // DOMString[] for primary/favorite (use:"PREF"), "home", "work", etc.
+  attribute DOMString value;
 };
 
-[scriptable, uuid(94811520-c11f-11e1-afa7-0800200c9a66)]
-interface nsIDOMContactEmail : nsISupports
+[scriptable, uuid(ed0ab260-e4aa-11e1-9b23-0800200c9a66)]
+interface nsIDOMContactTelField : nsIDOMContactField
 {
-  attribute DOMString type;
-  attribute DOMString address;
+  attribute DOMString carrier;
 };
 
 [scriptable, uuid(e31daea0-0cb6-11e1-be50-0800200c9a66)]
 interface nsIDOMContactFindOptions : nsISupports
 {
   attribute DOMString filterValue;  // e.g. "Tom"
   attribute DOMString filterOp;     // e.g. "contains"
   attribute jsval filterBy;         // DOMString[], e.g. ["givenName", "nickname"]
   attribute DOMString sortBy;       // "givenName" or "familyName"
   attribute DOMString sortOrder;    // e.g. "descending"
   attribute unsigned long filterLimit;
 };
 
-[scriptable, uuid(f5181640-89e8-11e1-b0c4-0800200c9a66)]
+[scriptable, uuid(f0ddb360-e4aa-11e1-9b23-0800200c9a66)]
 interface nsIDOMContactProperties : nsISupports
 {
   attribute jsval         name;               // DOMString[]
   attribute jsval         honorificPrefix;    // DOMString[]
   attribute jsval         givenName;          // DOMString[]
   attribute jsval         additionalName;     // DOMString[]
   attribute jsval         familyName;         // DOMString[]
   attribute jsval         honorificSuffix;    // DOMString[]
   attribute jsval         nickname;           // DOMString[]
-  attribute jsval         email;              // ContactEmail[]
+  attribute jsval         email;              // ContactField[]
   attribute jsval         photo;              // nsIDOMBlob[]
-  attribute jsval         url;                // DOMString[]
+  attribute jsval         url;                // ContactField[]
   attribute jsval         category;           // DOMString[]
   attribute jsval         adr;                // ContactAddress[]
-  attribute jsval         tel;                // ContactTelephone[]
+  attribute jsval         tel;                // ContactTelField[]
   attribute jsval         org;                // DOMString[]
   attribute jsval         jobTitle;           // DOMString[]
   attribute jsval         bday;               // Date
   attribute jsval         note;               // DOMString[]
-  attribute jsval         impp;               // DOMString[]
+  attribute jsval         impp;               // ContactField[]
   attribute jsval         anniversary;        // Date
   attribute jsval         sex;                // DOMString
   attribute jsval         genderIdentity;     // DOMString
 };
--- a/dom/interfaces/core/nsIInlineEventHandlers.idl
+++ b/dom/interfaces/core/nsIInlineEventHandlers.idl
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "domstubs.idl"
 
 %{ C++
 #include "jspubtd.h"
 %}
 
-[scriptable, uuid(5b3f9656-9d81-40e4-85ba-01f302177815)]
+[scriptable, uuid(22df6ed6-d094-4e45-97fc-a8eca11c390c)]
 interface nsIInlineEventHandlers : nsISupports
 {
   [implicit_jscontext] attribute jsval onabort;
   [implicit_jscontext] attribute jsval onblur;
   [implicit_jscontext] attribute jsval oncanplay;
   [implicit_jscontext] attribute jsval oncanplaythrough;
   [implicit_jscontext] attribute jsval onchange;
   [implicit_jscontext] attribute jsval onclick;
@@ -64,16 +64,17 @@ interface nsIInlineEventHandlers : nsISu
   [implicit_jscontext] attribute jsval onselect;
   [implicit_jscontext] attribute jsval onshow;
   [implicit_jscontext] attribute jsval onstalled;
   [implicit_jscontext] attribute jsval onsubmit;
   [implicit_jscontext] attribute jsval onsuspend;
   [implicit_jscontext] attribute jsval ontimeupdate;
   [implicit_jscontext] attribute jsval onvolumechange;
   [implicit_jscontext] attribute jsval onwaiting;
+  [implicit_jscontext] attribute jsval onwheel;
 
   /**
    * Non-HTML5 event attributes
    */
   [implicit_jscontext] attribute jsval oncopy;
   [implicit_jscontext] attribute jsval oncut;
   [implicit_jscontext] attribute jsval onpaste;
   [implicit_jscontext] attribute jsval onbeforescriptexecute;
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -5,31 +5,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "Blob.h"
 
 #include "nsIDOMFile.h"
 #include "nsIInputStream.h"
+#include "nsIIPCSerializableInputStream.h"
 #include "nsIRemoteBlob.h"
 #include "nsISeekableStream.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/unused.h"
-#include "mozilla/net/NeckoMessageUtils.h"
+#include "mozilla/ipc/InputStreamUtils.h"
 #include "nsDOMFile.h"
 #include "nsThreadUtils.h"
 
 #include "ContentChild.h"
 #include "ContentParent.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::dom::ipc;
+using namespace mozilla::ipc;
 
 namespace {
 
 class RemoteInputStream : public nsIInputStream,
                           public nsISeekableStream
 {
   mozilla::Monitor mMonitor;
   nsCOMPtr<nsIDOMBlob> mSourceBlob;
@@ -222,20 +224,28 @@ private:
     else {
       ReallyBlockAndWaitForStream();
     }
 
     return !!mSeekableStream;
   }
 };
 
+NS_IMPL_THREADSAFE_ADDREF(RemoteInputStream)
+NS_IMPL_THREADSAFE_RELEASE(RemoteInputStream)
+
+NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
+  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
+NS_INTERFACE_MAP_END
+
 template <ActorFlavorEnum ActorFlavor>
 class InputStreamActor : public BlobTraits<ActorFlavor>::StreamType
 {
-  typedef typename BlobTraits<ActorFlavor>::StreamType::InputStream InputStream;
   nsRefPtr<RemoteInputStream> mRemoteStream;
 
 public:
   InputStreamActor(RemoteInputStream* aRemoteStream)
   : mRemoteStream(aRemoteStream)
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(aRemoteStream);
@@ -244,22 +254,27 @@ public:
   InputStreamActor()
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
 private:
   // This method is only called by the IPDL message machinery.
   virtual bool
-  Recv__delete__(const InputStream& aStream) MOZ_OVERRIDE
+  Recv__delete__(const InputStreamParams& aParams) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(mRemoteStream);
 
-    mRemoteStream->SetStream(aStream);
+    nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aParams);
+    if (!stream) {
+      return false;
+    }
+
+    mRemoteStream->SetStream(stream);
     return true;
   }
 };
 
 template <ActorFlavorEnum ActorFlavor>
 inline
 already_AddRefed<nsIDOMBlob>
 GetBlobFromParams(const SlicedBlobConstructorParams& aParams)
@@ -600,24 +615,20 @@ public:
 
     nsRefPtr<StreamHelper> helper = new StreamHelper(mActor, this);
     return helper->GetStream(aStream);
   }
 
   virtual void*
   GetPBlob() MOZ_OVERRIDE
   {
-    return static_cast<typename ActorType::BaseType*>(mActor);
+    return static_cast<typename ActorType::ProtocolType*>(mActor);
   }
 };
 
-} // namespace ipc
-} // namespace dom
-} // namespace mozilla
-
 template <ActorFlavorEnum ActorFlavor>
 Blob<ActorFlavor>::Blob(nsIDOMBlob* aBlob)
 : mBlob(aBlob), mRemoteBlob(nullptr), mOwnsBlob(true), mBlobIsFile(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aBlob);
   aBlob->AddRef();
 
@@ -735,17 +746,17 @@ Blob<ActorFlavor>::SetMysteryBlobInfo(co
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
   MOZ_ASSERT(mRemoteBlob);
   MOZ_ASSERT(aLength);
 
   ToConcreteBlob(mBlob)->SetLazyData(aName, aContentType, aLength);
 
   FileBlobConstructorParams params(aName, aContentType, aLength);
-  return BaseType::SendResolveMystery(params);
+  return ProtocolType::SendResolveMystery(params);
 }
 
 template <ActorFlavorEnum ActorFlavor>
 bool
 Blob<ActorFlavor>::SetMysteryBlobInfo(const nsString& aContentType,
                                       PRUint64 aLength)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -754,17 +765,17 @@ Blob<ActorFlavor>::SetMysteryBlobInfo(co
   MOZ_ASSERT(aLength);
 
   nsString voidString;
   voidString.SetIsVoid(true);
 
   ToConcreteBlob(mBlob)->SetLazyData(voidString, aContentType, aLength);
 
   NormalBlobConstructorParams params(aContentType, aLength);
-  return BaseType::SendResolveMystery(params);
+  return ProtocolType::SendResolveMystery(params);
 }
 
 template <ActorFlavorEnum ActorFlavor>
 void
 Blob<ActorFlavor>::SetRemoteBlob(nsRefPtr<RemoteBlobType>& aRemoteBlob)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mBlob);
@@ -804,17 +815,17 @@ Blob<ActorFlavor>::NoteDyingRemoteBlob()
 
     return;
   }
 
   // Must do this before calling Send__delete__ or we'll crash there trying to
   // access a dangling pointer.
   mRemoteBlob = nullptr;
 
-  mozilla::unused << BaseType::Send__delete__(this);
+  mozilla::unused << ProtocolType::Send__delete__(this);
 }
 
 template <ActorFlavorEnum ActorFlavor>
 void
 Blob<ActorFlavor>::ActorDestroy(ActorDestroyReason aWhy)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
@@ -863,29 +874,77 @@ Blob<ActorFlavor>::RecvResolveMystery(co
 
     default:
       MOZ_NOT_REACHED("Unknown params!");
   }
 
   return true;
 }
 
-template <ActorFlavorEnum ActorFlavor>
+template <>
 bool
-Blob<ActorFlavor>::RecvPBlobStreamConstructor(StreamType* aActor)
+Blob<Parent>::RecvPBlobStreamConstructor(StreamType* aActor)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mBlob);
   MOZ_ASSERT(!mRemoteBlob);
 
   nsCOMPtr<nsIInputStream> stream;
   nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
   NS_ENSURE_SUCCESS(rv, false);
 
-  return aActor->Send__delete__(aActor, stream.get());
+  nsCOMPtr<nsIIPCSerializableInputStream> serializable =
+    do_QueryInterface(stream);
+  if (!serializable) {
+    MOZ_ASSERT(false, "Must be serializable!");
+    return false;
+  }
+
+  nsCOMPtr<nsIEventTarget> target =
+    do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(target, false);
+
+  nsRefPtr<BaseType::OpenStreamRunnable> runnable =
+    new BaseType::OpenStreamRunnable(this, aActor, stream, serializable,
+                                      target);
+
+  rv = target->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsRevocableEventPtr<BaseType::OpenStreamRunnable>* arrayMember =
+    mOpenStreamRunnables.AppendElement();
+  *arrayMember = runnable;
+  return true;
+}
+
+template <>
+bool
+Blob<Child>::RecvPBlobStreamConstructor(StreamType* aActor)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mBlob);
+  MOZ_ASSERT(!mRemoteBlob);
+
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = mBlob->GetInternalStream(getter_AddRefs(stream));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsCOMPtr<nsIIPCSerializableInputStream> serializable =
+    do_QueryInterface(stream);
+  if (!serializable) {
+    MOZ_ASSERT(false, "Must be serializable!");
+    return false;
+  }
+
+  InputStreamParams params;
+  serializable->Serialize(params);
+
+  MOZ_ASSERT(params.type() != InputStreamParams::T__None);
+
+  return aActor->Send__delete__(aActor, params);
 }
 
 template <ActorFlavorEnum ActorFlavor>
 typename Blob<ActorFlavor>::StreamType*
 Blob<ActorFlavor>::AllocPBlobStream()
 {
   MOZ_ASSERT(NS_IsMainThread());
   return new InputStreamActor<ActorFlavor>();
@@ -905,28 +964,137 @@ NS_IMPL_ADDREF_INHERITED(RemoteBlob<Acto
 
 template <ActorFlavorEnum ActorFlavor>
 NS_IMPL_RELEASE_INHERITED(RemoteBlob<ActorFlavor>, nsDOMFile)
 
 template <ActorFlavorEnum ActorFlavor>
 NS_IMPL_QUERY_INTERFACE_INHERITED1(RemoteBlob<ActorFlavor>, nsDOMFile,
                                                             nsIRemoteBlob)
 
-NS_IMPL_THREADSAFE_ADDREF(RemoteInputStream)
-NS_IMPL_THREADSAFE_RELEASE(RemoteInputStream)
+void
+BlobTraits<Parent>::BaseType::NoteRunnableCompleted(
+                    BlobTraits<Parent>::BaseType::OpenStreamRunnable* aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  for (PRUint32 index = 0; index < mOpenStreamRunnables.Length(); index++) {
+    nsRevocableEventPtr<BaseType::OpenStreamRunnable>& runnable =
+      mOpenStreamRunnables[index];
+
+    if (runnable.get() == aRunnable) {
+      runnable.Forget();
+      mOpenStreamRunnables.RemoveElementAt(index);
+      return;
+    }
+  }
+
+  MOZ_NOT_REACHED("Runnable not in our array!");
+}
+
+BlobTraits<Parent>::BaseType::
+OpenStreamRunnable::OpenStreamRunnable(
+                                   BlobTraits<Parent>::BaseType* aOwner,
+                                   BlobTraits<Parent>::StreamType* aActor,
+                                   nsIInputStream* aStream,
+                                   nsIIPCSerializableInputStream* aSerializable,
+                                   nsIEventTarget* aTarget)
+: mOwner(aOwner), mActor(aActor), mStream(aStream),
+  mSerializable(aSerializable), mTarget(aTarget), mRevoked(false),
+  mClosing(false)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aOwner);
+  MOZ_ASSERT(aActor);
+  MOZ_ASSERT(aStream);
+  MOZ_ASSERT(aSerializable);
+  MOZ_ASSERT(aTarget);
+}
+
+NS_IMETHODIMP
+BlobTraits<Parent>::BaseType::OpenStreamRunnable::Run()
+{
+  MOZ_ASSERT(mStream);
+
+  nsresult rv;
+
+  if (NS_IsMainThread()) {
+    MOZ_ASSERT(mTarget);
+    MOZ_ASSERT(!mClosing);
+
+    if (mRevoked) {
+      MOZ_ASSERT(!mOwner);
+      MOZ_ASSERT(!mActor);
+    }
+    else {
+      MOZ_ASSERT(mOwner);
+      MOZ_ASSERT(mActor);
+
+      nsCOMPtr<nsIIPCSerializableInputStream> serializable;
+      mSerializable.swap(serializable);
 
-NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
-  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
-NS_INTERFACE_MAP_END
+      InputStreamParams params;
+      serializable->Serialize(params);
+
+      MOZ_ASSERT(params.type() != InputStreamParams::T__None);
+
+      unused << mActor->Send__delete__(mActor, params);
+
+      mOwner->NoteRunnableCompleted(this);
+
+#ifdef DEBUG
+      mOwner = nullptr;
+      mActor = nullptr;
+#endif
+    }
+
+    mClosing = true;
+
+    nsCOMPtr<nsIEventTarget> target;
+    mTarget.swap(target);
+
+    rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return NS_OK;
+  }
 
-namespace mozilla {
-namespace dom {
-namespace ipc {
+  if (!mClosing) {
+    // To force the stream open we call Available(). We don't actually care how
+    // much data is available.
+    PRUint64 available;
+    if (NS_FAILED(mStream->Available(&available))) {
+      NS_WARNING("Available failed on this stream!");
+    }
+
+    rv = NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return NS_OK;
+  }
+
+  // Going to always release here.
+  nsCOMPtr<nsIInputStream> stream;
+  mStream.swap(stream);
+
+  rv = stream->Close();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+#ifdef DEBUG
+void
+BlobTraits<Parent>::BaseType::OpenStreamRunnable::Revoke()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mOwner = nullptr;
+  mActor = nullptr;
+  mRevoked = true;
+}
+#endif
 
 // Explicit instantiation of both classes.
 template class Blob<Parent>;
 template class Blob<Child>;
 
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/Blob.h
+++ b/dom/ipc/Blob.h
@@ -7,22 +7,26 @@
 #ifndef mozilla_dom_ipc_Blob_h
 #define mozilla_dom_ipc_Blob_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/PBlobChild.h"
 #include "mozilla/dom/PBlobParent.h"
 #include "mozilla/dom/PBlobStreamChild.h"
 #include "mozilla/dom/PBlobStreamParent.h"
-#include "mozilla/dom/PContentChild.h"
-#include "mozilla/dom/PContentParent.h"
+#include "mozilla/dom/PContent.h"
+
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
+#include "nsTArray.h"
+#include "nsThreadUtils.h"
 
 class nsIDOMBlob;
+class nsIIPCSerializableInputStream;
+class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 namespace ipc {
 
 enum ActorFlavorEnum
 {
   Parent = 0,
@@ -31,41 +35,116 @@ enum ActorFlavorEnum
 
 template <ActorFlavorEnum>
 struct BlobTraits
 { };
 
 template <>
 struct BlobTraits<Parent>
 {
-  typedef mozilla::dom::PBlobParent BaseType;
+  typedef mozilla::dom::PBlobParent ProtocolType;
   typedef mozilla::dom::PBlobStreamParent StreamType;
-  typedef mozilla::dom::PContentParent ManagerType;
+
+  // BaseType on the parent side is a bit more complicated than for the child
+  // side. In the case of nsIInputStreams backed by files we need to ensure that
+  // the files are actually opened and closed on a background thread before we
+  // can send their file handles across to the child. The child process could
+  // crash during this process so we need to make sure we cancel the intended
+  // response in such a case. We do that by holding an array of
+  // nsRevocableEventPtr. If the child crashes then this actor will be destroyed
+  // and the nsRevocableEventPtr destructor will cancel any stream events that
+  // are currently in flight.
+  class BaseType : public ProtocolType
+  {
+  protected:
+    BaseType()
+    { }
+
+    virtual ~BaseType()
+    { }
+
+    // Each instance of this class will be dispatched to the network stream
+    // thread pool to run the first time where it will open the file input
+    // stream. It will then dispatch itself back to the main thread to send the
+    // child process its response (assuming that the child has not crashed). The
+    // runnable will then dispatch itself to the thread pool again in order to
+    // close the file input stream.
+    class OpenStreamRunnable : public nsRunnable
+    {
+      friend class nsRevocableEventPtr<OpenStreamRunnable>;
+    public:
+      NS_DECL_NSIRUNNABLE
+
+      OpenStreamRunnable(BaseType* aOwner, StreamType* aActor,
+                         nsIInputStream* aStream,
+                         nsIIPCSerializableInputStream* aSerializable,
+                         nsIEventTarget* aTarget);
+
+    private:
+#ifdef DEBUG
+      void
+      Revoke();
+#else
+      void
+      Revoke()
+      {
+        mRevoked = true;
+      }
+#endif
+
+      // Only safe to access these two pointers if mRevoked is false!
+      BaseType* mOwner;
+      StreamType* mActor;
+
+      nsCOMPtr<nsIInputStream> mStream;
+      nsCOMPtr<nsIIPCSerializableInputStream> mSerializable;
+      nsCOMPtr<nsIEventTarget> mTarget;
+
+      bool mRevoked;
+      bool mClosing;
+    };
+
+    friend class OpenStreamRunnable;
+
+    void
+    NoteRunnableCompleted(OpenStreamRunnable* aRunnable);
+
+    nsTArray<nsRevocableEventPtr<OpenStreamRunnable> > mOpenStreamRunnables;
+  };
 };
 
 template <>
 struct BlobTraits<Child>
 {
-  typedef mozilla::dom::PBlobChild BaseType;
+  typedef mozilla::dom::PBlobChild ProtocolType;
   typedef mozilla::dom::PBlobStreamChild StreamType;
-  typedef mozilla::dom::PContentChild ManagerType;
+
+  class BaseType : public ProtocolType
+  {
+  protected:
+    BaseType()
+    { }
+
+    virtual ~BaseType()
+    { }
+  };
 };
 
 template <ActorFlavorEnum>
 class RemoteBlob;
 
 template <ActorFlavorEnum ActorFlavor>
 class Blob : public BlobTraits<ActorFlavor>::BaseType
 {
   friend class RemoteBlob<ActorFlavor>;
 
 public:
-  typedef typename BlobTraits<ActorFlavor>::BaseType BaseType;
+  typedef typename BlobTraits<ActorFlavor>::ProtocolType ProtocolType;
   typedef typename BlobTraits<ActorFlavor>::StreamType StreamType;
-  typedef typename BlobTraits<ActorFlavor>::ManagerType ManagerType;
+  typedef typename BlobTraits<ActorFlavor>::BaseType BaseType;
   typedef RemoteBlob<ActorFlavor> RemoteBlobType;
   typedef mozilla::ipc::IProtocolManager<
                       mozilla::ipc::RPCChannel::RPCListener>::ActorDestroyReason
           ActorDestroyReason;
   typedef mozilla::dom::BlobConstructorParams BlobConstructorParams;
 
 protected:
   nsIDOMBlob* mBlob;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -43,16 +43,17 @@
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsWeakReference.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsJSEnvironment.h"
 #include "SandboxHal.h"
 #include "nsDebugImpl.h"
+#include "nsLayoutStylesheetCache.h"
 
 #include "History.h"
 #include "nsDocShellCID.h"
 #include "nsNetUtil.h"
 
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "base/task.h"
@@ -903,21 +904,30 @@ ContentChild::RecvGarbageCollect()
 bool
 ContentChild::RecvCycleCollect()
 {
     nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC);
     nsJSContext::CycleCollectNow();
     return true;
 }
 
+static void
+PreloadSlowThings()
+{
+    // This fetches and creates all the built-in stylesheets.
+    nsLayoutStylesheetCache::UserContentSheet();
+}
+
 bool
 ContentChild::RecvAppInfo(const nsCString& version, const nsCString& buildID)
 {
     mAppInfo.version.Assign(version);
     mAppInfo.buildID.Assign(buildID);
+
+    PreloadSlowThings();
     return true;
 }
 
 bool
 ContentChild::RecvSetID(const PRUint64 &id)
 {
     if (mID != PRUint64(-1)) {
         NS_WARNING("Setting content child's ID twice?");
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -16,29 +16,30 @@
 #include "chrome/common/process_watcher.h"
 
 #include "CrashReporterParent.h"
 #include "History.h"
 #include "IDBFactory.h"
 #include "IndexedDBParent.h"
 #include "IndexedDatabaseManager.h"
 #include "mozIApplication.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Services.h"
-#include "mozilla/Util.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/StorageParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
 #include "mozilla/dom/sms/SmsParent.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/net/NeckoParent.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/Util.h"
 #include "mozilla/unused.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAppRunner.h"
 #include "nsAutoPtr.h"
 #include "nsCExternalHandlerService.h"
 #include "nsCOMPtr.h"
 #include "nsChromeRegistryChrome.h"
@@ -153,16 +154,103 @@ MemoryReportRequestParent::~MemoryReport
 
 nsDataHashtable<nsStringHashKey, ContentParent*>* ContentParent::gAppContentParents;
 nsTArray<ContentParent*>* ContentParent::gNonAppContentParents;
 nsTArray<ContentParent*>* ContentParent::gPrivateContent;
 
 // The first content child has ID 1, so the chrome process can have ID 0.
 static PRUint64 gContentChildID = 1;
 
+// Try to keep an app process always preallocated, to get
+// initialization off the critical path of app startup.
+static bool sKeepAppProcessPreallocated;
+static StaticRefPtr<ContentParent> sPreallocatedAppProcess;
+static CancelableTask* sPreallocateAppProcessTask;
+// This number is fairly arbitrary ... the intention is to put off
+// launching another app process until the last one has finished
+// loading its content, to reduce CPU/memory/IO contention.
+static int sPreallocateDelayMs;
+// We want the prelaunched process to know that it's for apps, but not
+// actually for any app in particular.  Use a magic manifest URL.
+// Can't be a static constant.
+#define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}")
+
+/*static*/ void
+ContentParent::PreallocateAppProcess()
+{
+    MOZ_ASSERT(!sPreallocatedAppProcess);
+
+    if (sPreallocateAppProcessTask) {
+        // We were called directly while a delayed task was scheduled.
+        sPreallocateAppProcessTask->Cancel();
+        sPreallocateAppProcessTask = nullptr;
+    }
+
+    sPreallocatedAppProcess =
+        new ContentParent(MAGIC_PREALLOCATED_APP_MANIFEST_URL);
+    sPreallocatedAppProcess->Init();
+}
+
+/*static*/ void
+ContentParent::DelayedPreallocateAppProcess()
+{
+    sPreallocateAppProcessTask = nullptr;
+    if (!sPreallocatedAppProcess) {
+        PreallocateAppProcess();
+    }
+}
+
+/*static*/ void
+ContentParent::ScheduleDelayedPreallocateAppProcess()
+{
+    if (!sKeepAppProcessPreallocated || sPreallocateAppProcessTask) {
+        return;
+    }
+    sPreallocateAppProcessTask =
+        NewRunnableFunction(DelayedPreallocateAppProcess);
+    MessageLoop::current()->PostDelayedTask(
+        FROM_HERE, sPreallocateAppProcessTask, sPreallocateDelayMs);
+}
+
+/*static*/ already_AddRefed<ContentParent>
+ContentParent::MaybeTakePreallocatedAppProcess()
+{
+    nsRefPtr<ContentParent> process = sPreallocatedAppProcess.get();
+    sPreallocatedAppProcess = nullptr;
+    ScheduleDelayedPreallocateAppProcess();
+    return process.forget();
+}
+
+/*static*/ void
+ContentParent::StartUp()
+{
+    if (XRE_GetProcessType() != GeckoProcessType_Default) {
+        return;
+    }
+
+    sKeepAppProcessPreallocated =
+        Preferences::GetBool("dom.ipc.processPrelauch.enabled", false);
+    if (sKeepAppProcessPreallocated) {
+        ClearOnShutdown(&sPreallocatedAppProcess);
+
+        sPreallocateDelayMs = Preferences::GetUint(
+            "dom.ipc.processPrelauch.delayMs", 1000);
+
+        MOZ_ASSERT(!sPreallocateAppProcessTask);
+        ScheduleDelayedPreallocateAppProcess();
+    }
+}
+
+/*static*/ void
+ContentParent::ShutDown()
+{
+    // No-op for now.  We rely on normal process shutdown and
+    // ClearOnShutdown() to clean up our state.
+}
+
 /*static*/ ContentParent*
 ContentParent::GetNewOrUsed()
 {
     if (!gNonAppContentParents)
         gNonAppContentParents = new nsTArray<ContentParent*>();
 
     PRInt32 maxContentProcesses = Preferences::GetInt("dom.ipc.processCount", 1);
     if (maxContentProcesses < 1)
@@ -220,20 +308,26 @@ ContentParent::CreateBrowser(mozIApplica
     // Send the local app ID to the new TabChild so it knows what app
     // it is.
     PRUint32 appId;
     if (NS_FAILED(appsService->GetAppLocalIdByManifestURL(manifestURL, &appId))) {
         NS_ERROR("Failed to get local app ID");
         return nullptr;
     }
 
-    ContentParent* p = gAppContentParents->Get(manifestURL);
+    nsRefPtr<ContentParent> p = gAppContentParents->Get(manifestURL);
     if (!p) {
-        p = new ContentParent(manifestURL);
-        p->Init();
+        p = MaybeTakePreallocatedAppProcess();
+        if (p) {
+            p->SetManifestFromPreallocated(manifestURL);
+        } else {
+            NS_WARNING("Unable to use pre-allocated app process");
+            p = new ContentParent(manifestURL);
+            p->Init();
+        }
         gAppContentParents->Put(manifestURL, p);
     }
 
     nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
     return static_cast<TabParent*>(
         // DeallocPBrowserParent() releases the ref we take here
         p->SendPBrowserConstructor(tp.forget().get(),
                                    /*chromeFlags*/0,
@@ -297,17 +391,26 @@ ContentParent::Init()
     // process.
     if (nsIPresShell::IsAccessibilityActive()) {
         unused << SendActivateA11y();
     }
 #endif
 }
 
 void
-ContentParent::ShutDown()
+ContentParent::SetManifestFromPreallocated(const nsAString& aAppManifestURL)
+{
+    MOZ_ASSERT(mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL);
+    // Clients should think of mAppManifestURL as const ... we're
+    // bending the rules here just for the preallocation hack.
+    const_cast<nsString&>(mAppManifestURL) = aAppManifestURL;
+}
+
+void
+ContentParent::ShutDownProcess()
 {
     if (mIsAlive) {
         // Close() can only be called once.  It kicks off the
         // destruction sequence.
         Close();
     }
     // NB: must MarkAsDead() here so that this isn't accidentally
     // returned from Get*() while in the midst of shutdown.
@@ -442,16 +545,20 @@ ContentParent::ActorDestroy(ActorDestroy
 #ifdef MOZ_WIDGET_GONK
         obs->RemoveObserver(static_cast<nsIObserver*>(this), NS_VOLUME_STATE_CHANGED);
 #endif
 #ifdef ACCESSIBILITY
         obs->RemoveObserver(static_cast<nsIObserver*>(this), "a11y-init-or-shutdown");
 #endif
     }
 
+    if (sPreallocatedAppProcess == this) {
+        sPreallocatedAppProcess = nullptr;
+    }
+
     mMessageManager->Disconnect();
 
     // clear the child memory reporters
     InfallibleTArray<MemoryReport> empty;
     SetChildMemoryReporters(empty);
 
     // remove the global remote preferences observers
     Preferences::RemoveObserver(this, "");
@@ -508,17 +615,17 @@ void
 ContentParent::NotifyTabDestroyed(PBrowserParent* aTab)
 {
     // There can be more than one PBrowser for a given app process
     // because of popup windows.  When the last one closes, shut
     // us down.
     if (IsForApp() && ManagedPBrowserParent().Length() == 1) {
         MessageLoop::current()->PostTask(
             FROM_HERE,
-            NewRunnableMethod(this, &ContentParent::ShutDown));
+            NewRunnableMethod(this, &ContentParent::ShutDownProcess));
     }
 }
 
 TestShellParent*
 ContentParent::CreateTestShell()
 {
   return static_cast<TestShellParent*>(SendPTestShellConstructor());
 }
@@ -681,17 +788,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 +809,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
@@ -53,16 +53,24 @@ class ContentParent : public PContentPar
 {
 private:
     typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
     typedef mozilla::ipc::TestShellParent TestShellParent;
     typedef mozilla::layers::PCompositorParent PCompositorParent;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
+    /**
+     * Start up the content-process machinery.  This might include
+     * scheduling pre-launch tasks.
+     */
+    static void StartUp();
+    /** Shut down the content-process machinery. */
+    static void ShutDown();
+
     static ContentParent* GetNewOrUsed();
 
     /**
      * Get or create a content process for the given app descriptor,
      * which may be null.  This function will assign processes to app
      * or non-app browsers by internal heuristics.
      *
      * Currently apps are given their own process, and browser tabs
@@ -107,39 +115,48 @@ protected:
     void OnChannelConnected(int32 pid);
     virtual void ActorDestroy(ActorDestroyReason why);
 
 private:
     static nsDataHashtable<nsStringHashKey, ContentParent*> *gAppContentParents;
     static nsTArray<ContentParent*>* gNonAppContentParents;
     static nsTArray<ContentParent*>* gPrivateContent;
 
+    static void PreallocateAppProcess();
+    static void DelayedPreallocateAppProcess();
+    static void ScheduleDelayedPreallocateAppProcess();
+    static already_AddRefed<ContentParent> MaybeTakePreallocatedAppProcess();
+
     // Hide the raw constructor methods since we don't want client code
     // using them.
     using PContentParent::SendPBrowserConstructor;
     using PContentParent::SendPTestShellConstructor;
 
     ContentParent(const nsAString& aAppManifestURL);
     virtual ~ContentParent();
 
     void Init();
 
+    // Transform a pre-allocated app process into a "real" app
+    // process, for the specified manifest URL.
+    void SetManifestFromPreallocated(const nsAString& aAppManifestURL);
+
     /**
      * Mark this ContentParent as dead for the purposes of Get*().
      * This method is idempotent.
      */
     void MarkAsDead();
 
     /**
      * Exit the subprocess and vamoose.  After this call IsAlive()
      * will return false and this ContentParent will not be returned
      * by the Get*() funtions.  However, the shutdown sequence itself
      * may be asynchronous.
      */
-    void ShutDown();
+    void ShutDownProcess();
 
     PCompositorParent* AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                         base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags,
                                           const bool& aIsBrowserElement,
                                           const AppId& aApp);
     virtual bool DeallocPBrowser(PBrowserParent* frame);
@@ -196,17 +213,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/PBlobStream.ipdl
+++ b/dom/ipc/PBlobStream.ipdl
@@ -1,23 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PBlob;
-
-include "mozilla/net/NeckoMessageUtils.h";
-
-using IPC::InputStream;
+include IPCSerializableParams;
 
 namespace mozilla {
 namespace dom {
 
 protocol PBlobStream
 {
   manager PBlob;
 
 both:
-  __delete__(InputStream stream);
+  __delete__(InputStreamParams params);
 };
 
 } // namespace dom
 } // namespace mozilla
--- 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/network/interfaces/nsIDOMMobileConnection.idl
+++ b/dom/network/interfaces/nsIDOMMobileConnection.idl
@@ -3,16 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
 interface nsIDOMDOMRequest;
 interface nsIDOMMozMobileConnectionInfo;
 interface nsIDOMMozMobileNetworkInfo;
+interface nsIDOMMozMobileCellInfo;
 
 [scriptable, builtinclass, uuid(e7309c47-9a2e-4e12-84ab-f8f39214eaba)]
 interface nsIDOMMozMobileConnection : nsIDOMEventTarget
 {
   /**
    * Indicates the state of the device's ICC card.
    *
    * Possible values: null, 'absent', 'pinRequired', 'pukRequired',
@@ -217,17 +218,17 @@ interface nsIDOMMozMobileConnection : ns
 
   /**
    * The 'ussdreceived' event is notified whenever a new USSD message is
    * received.
    */
   attribute nsIDOMEventListener onussdreceived;
 };
 
-[scriptable, uuid(6601c20e-337f-4286-8d6e-0990fc1c2372)]
+[scriptable, uuid(5ea0e4a9-4684-40da-9930-8ebb61d187f3)]
 interface nsIDOMMozMobileConnectionInfo : nsISupports
 {
   /**
    * State of the connection.
    *
    * Possible values: 'notSearching', 'searching', 'denied', 'registered'.
    * null if the state is unknown.
    */
@@ -271,16 +272,21 @@ interface nsIDOMMozMobileConnectionInfo 
   readonly attribute jsval signalStrength;
 
   /**
    * Signal strength, represented linearly as a number between 0 (weakest
    * signal) and 100 (full signal).
    */
   readonly attribute jsval relSignalStrength;
 
+  /**
+   * Cell location.
+   */
+  readonly attribute nsIDOMMozMobileCellInfo cell;
+
 };
 
 [scriptable, uuid(3bd866c7-98a5-4ef4-a464-c22d8cc6b992)]
 interface nsIDOMMozMobileNetworkInfo: nsISupports
 {
   /**
    * Short name of the network operator
    */
@@ -303,8 +309,22 @@ interface nsIDOMMozMobileNetworkInfo: ns
 
   /**
    * State of this network operator.
    *
    * Possible values: 'available', 'connected', 'forbidden', or null (unknown)
    */
   readonly attribute DOMString state;
 };
+
+[scriptable, uuid(aa546788-4f34-488b-8c3e-2786e02ab992)]
+interface nsIDOMMozMobileCellInfo: nsISupports
+{
+  /**
+   * Mobile Location Area Code (LAC) for GSM/WCDMA networks.
+   */
+  readonly attribute unsigned short gsmLocationAreaCode;
+
+  /**
+   * Mobile Cell ID for GSM/WCDMA networks.
+   */
+  readonly attribute unsigned long gsmCellId;
+};
--- a/dom/network/tests/marionette/test_mobile_voice_state.js
+++ b/dom/network/tests/marionette/test_mobile_voice_state.js
@@ -12,24 +12,54 @@ ok(connection instanceof MozMobileConnec
    "connection is instanceof " + connection.constructor);
 
 function setEmulatorVoiceState(state) {
   runEmulatorCmd("gsm voice " + state, function (result) {
     is(result[0], "OK");
   });
 }
 
+function setEmulatorGsmLocation(lac, cid) {
+  runEmulatorCmd("gsm location " + lac + " " + cid, function (result) {
+    is(result[0], "OK");
+  });
+}
+
 function testConnectionInfo() {
   let voice = connection.voice;
   is(voice.connected, true);
   is(voice.state, "registered");
   is(voice.emergencyCallsOnly, false);
   is(voice.roaming, false);
 
-  testUnregistered();
+  testCellLocation();
+}
+
+function testCellLocation() {
+  let voice = connection.voice;
+
+  // Emulator always reports valid lac/cid value because its AT command parser
+  // insists valid value for every complete response. See source file
+  // hardare/ril/reference-ril/at_tok.c, function at_tok_nexthexint().
+  ok(voice.cell, "location available");
+
+  // Initial LAC/CID. Android emulator initializes both value to -1.
+  is(voice.cell.gsmLocationAreaCode, 65535);
+  is(voice.cell.gsmCellId, 268435455);
+
+  connection.addEventListener("voicechange", function onvoicechange() {
+    connection.removeEventListener("voicechange", onvoicechange);
+
+    is(voice.cell.gsmLocationAreaCode, 100);
+    is(voice.cell.gsmCellId, 100);
+
+    testUnregistered();
+  });
+
+  setEmulatorGsmLocation(100, 100);
 }
 
 function testUnregistered() {
   setEmulatorVoiceState("unregistered");
 
   connection.addEventListener("voicechange", function onvoicechange() {
     connection.removeEventListener("voicechange", onvoicechange);
 
--- 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/plugins/ipc/PPluginModule.ipdl
+++ b/dom/plugins/ipc/PPluginModule.ipdl
@@ -9,17 +9,16 @@ include protocol PPluginScriptableObject
 include protocol PCrashReporter;
 
 include "npapi.h";
 include "mozilla/plugins/PluginMessageUtils.h";
 include "mozilla/dom/TabMessageUtils.h";
 
 using NPError;
 using NPNVariable;
-using base::FileDescriptor;
 using mozilla::dom::NativeThreadId;
 using mac_plugin_interposing::NSCursorInfo;
 using nsID;
 
 namespace mozilla {
 namespace plugins {
 
 rpc protocol PPluginModule
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -1845,20 +1845,20 @@ PluginModuleChild::AnswerNP_Initialize(c
 
     mAsyncDrawingAllowed = aFlags & kAllowAsyncDrawing;
 
 #ifdef OS_WIN
     SetEventHooks();
 #endif
 
 #ifdef MOZ_X11
-    // Send the parent a dup of our X socket, to act as a proxy
-    // reference for our X resources
+    // Send the parent our X socket to act as a proxy reference for our X
+    // resources.
     int xSocketFd = ConnectionNumber(DefaultXDisplay());
-    SendBackUpXResources(FileDescriptor(xSocketFd, false/*don't close*/));
+    SendBackUpXResources(FileDescriptor(xSocketFd));
 #endif
 
 #if defined(OS_LINUX)
     *_retval = mInitializeFunc(&sBrowserFuncs, &mFunctions);
     return true;
 #elif defined(OS_WIN) || defined(OS_MACOSX)
     *_retval = mInitializeFunc(&sBrowserFuncs);
     return true;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -684,19 +684,18 @@ PluginModuleParent::NPP_SetValue(NPP ins
 bool
 PluginModuleParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
 {
 #ifndef MOZ_X11
     NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
 #else
     NS_ABORT_IF_FALSE(0 > mPluginXSocketFdDup.get(),
                       "Already backed up X resources??");
-    int fd = aXSocketFd.fd; // Copy to discard |const| qualifier
     mPluginXSocketFdDup.forget();
-    mPluginXSocketFdDup.reset(fd);
+    mPluginXSocketFdDup.reset(aXSocketFd.PlatformHandle());
 #endif
     return true;
 }
 
 void
 PluginModuleParent::NPP_URLRedirectNotify(NPP instance, const char* url,
                                           int32_t status, void* notifyData)
 {
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -191,23 +191,25 @@ AudioManager::GetForceForUse(PRInt32 aUs
     // Dynamically resolved the ICS signature.
     *aForce = AudioSystem::getForceUse((audio_policy_force_use_t)aUsage);
   }
   return NS_OK;
 }
 
 void
 AudioManager::SetAudioRoute(int aRoutes) {
-  audio_io_handle_t handle = 0;
   if (static_cast<
       audio_io_handle_t (*)(AudioSystem::stream_type, uint32_t, uint32_t, uint32_t, AudioSystem::output_flags)
       >(AudioSystem::getOutput)) {
+    audio_io_handle_t handle = 0;
     handle = AudioSystem::getOutput((AudioSystem::stream_type)AudioSystem::SYSTEM);
+    String8 cmd;
+    cmd.appendFormat("routing=%d", GetRoutingMode(aRoutes));
+    AudioSystem::setParameters(handle, cmd);
   } else if (static_cast<
-             audio_io_handle_t (*)(audio_stream_type_t, uint32_t, uint32_t, uint32_t, audio_policy_output_flags_t)
-             >(AudioSystem::getOutput)) {
-    handle = AudioSystem::getOutput((audio_stream_type_t)AudioSystem::SYSTEM);
+             status_t (*)(audio_devices_t, audio_policy_dev_state_t, const char*)
+             >(AudioSystem::setDeviceConnectionState)) {
+    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADSET, 
+        GetRoutingMode(aRoutes) == AudioSystem::DEVICE_OUT_WIRED_HEADSET ? 
+        AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+        "");
   }
-  
-  String8 cmd;
-  cmd.appendFormat("routing=%d", GetRoutingMode(aRoutes));
-  AudioSystem::setParameters(handle, cmd);
 }
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -19,16 +19,17 @@
 
 #include "GonkGPSGeolocationProvider.h"
 #include "SystemWorkerManager.h"
 #include "mozilla/Preferences.h"
 #include "nsGeoPosition.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsINetworkManager.h"
 #include "nsIRadioInterfaceLayer.h"
+#include "nsIDOMMobileConnection.h"
 #include "nsThreadUtils.h"
 
 #ifdef AGPS_TYPE_INVALID
 #define AGPS_HAVE_DUAL_APN
 #endif
 
 #define DEBUG_GPS 0
 
@@ -366,21 +367,25 @@ GonkGPSGeolocationProvider::SetReference
 
   if (rilCtx) {
     nsCOMPtr<nsIICCRecords> icc;
     rilCtx->GetIcc(getter_AddRefs(icc));
     if (icc) {
       icc->GetMcc(&location.u.cellID.mcc);
       icc->GetMnc(&location.u.cellID.mnc);
     }
-    nsCOMPtr<nsICellLocation> cell;
-    rilCtx->GetCell(getter_AddRefs(cell));
-    if (cell) {
-      cell->GetLac(&location.u.cellID.lac);
-      cell->GetCid(&location.u.cellID.cid);
+    nsCOMPtr<nsIDOMMozMobileConnectionInfo> voice;
+    rilCtx->GetVoice(getter_AddRefs(voice));
+    if (voice) {
+      nsCOMPtr<nsIDOMMozMobileCellInfo> cell;
+      voice->GetCell(getter_AddRefs(cell));
+      if (cell) {
+        cell->GetGsmLocationAreaCode(&location.u.cellID.lac);
+        cell->GetGsmCellId(&location.u.cellID.cid);
+      }
     }
     if (mAGpsRilInterface) {
       mAGpsRilInterface->set_ref_location(&location, sizeof(location));
     }
   }
 }
 
 void
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -28,38 +28,35 @@ Cu.import("resource://gre/modules/ril_co
 const DEBUG = RIL.DEBUG_CONTENT_HELPER;
 
 const RILCONTENTHELPER_CID =
   Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}");
 const MOBILECONNECTIONINFO_CID =
   Components.ID("{a35cfd39-2d93-4489-ac7d-396475dacb27}");
 const MOBILENETWORKINFO_CID =
   Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
+const MOBILECELLINFO_CID =
+  Components.ID("{5e809018-68c0-4c54-af0b-2a9b8f748c45}");
 const VOICEMAILSTATUS_CID=
   Components.ID("{5467f2eb-e214-43ea-9b89-67711241ec8e}");
 
 const RIL_IPC_MSG_NAMES = [
   "RIL:CardStateChanged",
   "RIL:VoiceInfoChanged",
   "RIL:DataInfoChanged",
   "RIL:EnumerateCalls",
   "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";
@@ -84,16 +81,17 @@ MobileConnectionInfo.prototype = {
 
   // nsIDOMMozMobileConnectionInfo
 
   connected: false,
   state: null,
   emergencyCallsOnly: false,
   roaming: false,
   network: null,
+  cell: null,
   type: null,
   signalStrength: null,
   relSignalStrength: null
 };
 
 function MobileNetworkInfo() {}
 MobileNetworkInfo.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileNetworkInfo]),
@@ -109,16 +107,33 @@ MobileNetworkInfo.prototype = {
 
   shortName: null,
   longName: null,
   mcc: 0,
   mnc: 0,
   state: null
 };
 
+function MobileCellInfo() {}
+MobileCellInfo.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileCellInfo]),
+  classID:        MOBILECELLINFO_CID,
+  classInfo:      XPCOMUtils.generateCI({
+    classID:          MOBILECELLINFO_CID,
+    classDescription: "MobileCellInfo",
+    flags:            Ci.nsIClassInfo.DOM_OBJECT,
+    interfaces:       [Ci.nsIDOMMozMobileCellInfo]
+  }),
+
+  // nsIDOMMozMobileCellInfo
+
+  gsmLocationAreaCode: null,
+  gsmCellId: null
+};
+
 function VoicemailStatus() {}
 VoicemailStatus.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozVoicemailStatus]),
   classID:        VOICEMAILSTATUS_CID,
   classInfo:      XPCOMUtils.generateCI({
     classID:          VOICEMAILSTATUS_CID,
     classDescription: "VoicemailStatus",
     flags:            Ci.nsIClassInfo.DOM_OBJECT,
@@ -163,21 +178,34 @@ RILContentHelper.prototype = {
   classID:   RILCONTENTHELPER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
                                     classDescription: "RILContentHelper",
                                     interfaces: [Ci.nsIMobileConnectionProvider,
                                                  Ci.nsIRILContentHelper]}),
 
   updateConnectionInfo: function updateConnectionInfo(srcInfo, destInfo) {
     for (let key in srcInfo) {
-      if (key != "network") {
+      if ((key != "network") && (key != "cell")) {
         destInfo[key] = srcInfo[key];
       }
     }
 
+    let srcCell = srcInfo.cell;
+    if (!srcCell) {
+      destInfo.cell = null;
+    } else {
+      let cell = destInfo.cell;
+      if (!cell) {
+        cell = destInfo.cell = new MobileCellInfo();
+      }
+
+      cell.gsmLocationAreaCode = srcCell.gsmLocationAreaCode;
+      cell.gsmCellId = srcCell.gsmCellId;
+    }
+
     let srcNetwork = srcInfo.network;
     if (!srcNetwork) {
       destInfo.network= null;
       return;
     }
 
     let network = destInfo.network;
     if (!network) {
@@ -565,25 +593,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
@@ -146,31 +146,34 @@ function RadioInterfaceLayer() {
   this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
   this.worker.onerror = this.onerror.bind(this);
   this.worker.onmessage = this.onmessage.bind(this);
 
   this.rilContext = {
     radioState:     RIL.GECKO_RADIOSTATE_UNAVAILABLE,
     cardState:      RIL.GECKO_CARDSTATE_UNAVAILABLE,
     icc:            null,
-    cell:           null,
 
     // These objects implement the nsIDOMMozMobileConnectionInfo interface,
-    // although the actual implementation lives in the content process.
+    // although the actual implementation lives in the content process. So are
+    // the child attributes `network` and `cell`, which implement
+    // nsIDOMMozMobileNetworkInfo and nsIDOMMozMobileCellInfo respectively.
     voice:          {connected: false,
                      emergencyCallsOnly: false,
                      roaming: false,
                      network: null,
+                     cell: null,
                      type: null,
                      signalStrength: null,
                      relSignalStrength: null},
     data:           {connected: false,
                      emergencyCallsOnly: false,
                      roaming: false,
                      network: null,
+                     cell: null,
                      type: null,
                      signalStrength: null,
                      relSignalStrength: null},
   };
 
   // Read the 'ril.radio.disabled' setting in order to start with a known
   // value at boot time.
   gSettingsService.getLock().get("ril.radio.disabled", this);
@@ -393,41 +396,34 @@ 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];
           callback.receiveContactsList(message.contactType, message.contacts);
         }
         break;
       case "iccmbdn":
         ppmm.sendAsyncMessage("RIL:VoicemailNumberChanged", message);
         break;
-      case "celllocationchanged":
-        this.rilContext.cell = message;
-        break;
       case "ussdreceived":
         debug("ussdreceived " + JSON.stringify(message));
         this.handleUSSDReceived(message);
         break;
       case "sendussd":
         this.handleSendUSSD(message);
         break;
       case "cancelussd":
@@ -501,16 +497,23 @@ RadioInterfaceLayer.prototype = {
     // Make sure we also reset the operator and signal strength information
     // if we drop off the network.
     if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
       voiceInfo.network = null;
       voiceInfo.signalStrength = null;
       voiceInfo.relSignalStrength = null;
     }
 
+    let newCell = newInfo.cell;
+    if ((newCell.gsmLocationAreaCode < 0) || (newCell.gsmCellId < 0)) {
+      voiceInfo.cell = null;
+    } else {
+      voiceInfo.cell = newCell;
+    }
+
     if (!newInfo.batch) {
       ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
     }
   },
 
   updateDataConnection: function updateDataConnection(newInfo) {
     let dataInfo = this.rilContext.data;
     dataInfo.state = newInfo.state;
@@ -524,16 +527,23 @@ RadioInterfaceLayer.prototype = {
     // Make sure we also reset the operator and signal strength information
     // if we drop off the network.
     if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
       dataInfo.network = null;
       dataInfo.signalStrength = null;
       dataInfo.relSignalStrength = null;
     }
 
+    let newCell = newInfo.cell;
+    if ((newCell.gsmLocationAreaCode < 0) || (newCell.gsmCellId < 0)) {
+      dataInfo.cell = null;
+    } else {
+      dataInfo.cell = newCell;
+    }
+
     if (!newInfo.batch) {
       ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo);
     }
 
     if (!this.dataCallSettings["enabled"]) {
       return;
     }
 
@@ -941,26 +951,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 +1637,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/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -212,41 +212,25 @@ interface nsIICCRecords : nsISupports
   readonly attribute jsval adn;
 
   /**
    * Fixed Dialling Numbers
    */
   readonly attribute jsval fdn;
 };
 
-[scriptable, uuid(1b47459d-d0bc-4e91-8509-cc106054b9ee)]
-interface nsICellLocation : nsISupports
-{
-  /**
-   * Location Area Code
-   */
-  readonly attribute unsigned short lac;
-
-  /**
-   * Cell Identity
-   */
-  readonly attribute unsigned long cid;
-};
-
-[scriptable, uuid(a6f6977e-f4ee-42b4-ae79-798c8c47c360)]
+[scriptable, uuid(e6dc89f2-0d4e-46fc-902c-cfeeaee15e40)]
 interface nsIRilContext : nsISupports
 {
   readonly attribute DOMString radioState;
 
   readonly attribute DOMString cardState;
 
   readonly attribute nsIICCRecords icc;
 
-  readonly attribute nsICellLocation cell;
-
   readonly attribute nsIDOMMozMobileConnectionInfo voice;
 
   readonly attribute nsIDOMMozMobileConnectionInfo data;
 };
 
 [scriptable, uuid(8b649965-6687-46a8-88fa-a5495ce90735)]
 interface nsIRadioInterfaceLayer : nsISupports
 {
--- 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
@@ -619,21 +619,16 @@ let RIL = {
   aid: null,
 
   networkSelectionMode: null,
 
   voiceRegistrationState: {},
   dataRegistrationState: {},
 
   /**
-   * The cell location on a phone, such as LAC, CID.
-   */
-  cellLocation: {},
-
-  /**
    * List of strings identifying the network operator.
    */
   operator: null,
 
   /**
    * String containing the baseband version.
    */
   basebandVersion: null,
@@ -693,21 +688,23 @@ let RIL = {
 
   /**
    * Parse an integer from a string, falling back to a default value
    * if the the provided value is not a string or does not contain a valid
    * number.
    *
    * @param string
    *        String to be parsed.
-   * @param defaultValue
+   * @param defaultValue [optional]
    *        Default value to be used.
+   * @param radix [optional]
+   *        A number that represents the numeral system to be used. Default 10.
    */
-  parseInt: function RIL_parseInt(string, defaultValue) {
-    let number = parseInt(string, 10);
+  parseInt: function RIL_parseInt(string, defaultValue, radix) {
+    let number = parseInt(string, radix || 10);
     if (!isNaN(number)) {
       return number;
     }
     if (defaultValue === undefined) {
       defaultValue = null;
     }
     return defaultValue;
   },
@@ -728,16 +725,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 +785,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 +897,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 +966,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_*.
@@ -1912,30 +1976,34 @@ let RIL = {
         return;
       }
       this.cardState = GECKO_CARDSTATE_ABSENT;
       this.sendDOMMessage({rilMessageType: "cardstatechange",
                            cardState: this.cardState});
       return;
     }
 
-    let app = iccStatus.apps[iccStatus.gsmUmtsSubscriptionAppIndex];
+    // TODO: Bug 726098, change to use cdmaSubscriptionAppIndex when in CDMA.
+    let index = iccStatus.gsmUmtsSubscriptionAppIndex;
+    let app = iccStatus.apps[index];
     if (!app) {
       if (DEBUG) {
         debug("Subscription application is not present in iccStatus.");
       }
       if (this.cardState == GECKO_CARDSTATE_ABSENT) {
         return;
       }
       this.cardState = GECKO_CARDSTATE_ABSENT;
       this.operator = null;
       this.sendDOMMessage({rilMessageType: "cardstatechange",
                            cardState: this.cardState});
       return;
     }
+    // fetchICCRecords will need to read aid, so read aid here.
+    this.aid = app.aid;
 
     let newCardState;
     switch (app.app_state) {
       case CARD_APPSTATE_PIN:
         newCardState = GECKO_CARDSTATE_PIN_REQUIRED;
         break;
       case CARD_APPSTATE_PUK:
         newCardState = GECKO_CARDSTATE_PUK_REQUIRED;
@@ -1951,31 +2019,40 @@ let RIL = {
       default:
         newCardState = GECKO_CARDSTATE_NOT_READY;
     }
 
     if (this.cardState == newCardState) {
       return;
     }
 
-    // TODO: Bug 726098, change to use cdmaSubscriptionAppIndex when in CDMA.
-    // fetchICCRecords will need to read aid, so read aid here.
-    let index = iccStatus.gsmUmtsSubscriptionAppIndex;
-    this.aid = iccStatus.apps[index].aid;
-
     // This was moved down from CARD_APPSTATE_READY
     this.requestNetworkInfo();
     this.getSignalStrength();
-    this.fetchICCRecords();
+    if (newCardState == GECKO_CARDSTATE_READY) {
+      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
 
@@ -2181,54 +2258,50 @@ let RIL = {
       curState.emergencyCallsOnly =
         (regState >= NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS) &&
         (regState <= NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS);
       if (RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE) {
         curState.emergencyCallsOnly = !curState.connected;
       }
     }
 
+    if (!curState.cell) {
+      curState.cell = {};
+    }
+
+    // From TS 23.003, 0000 and 0xfffe are indicated that no valid LAI exists
+    // in MS. So we still need to report the '0000' as well.
+    let lac = RIL.parseInt(newState[1], -1, 16);
+    if (curState.cell.gsmLocationAreaCode !== lac) {
+      curState.cell.gsmLocationAreaCode = lac;
+      changed = true;
+    }
+
+    let cid = RIL.parseInt(newState[2], -1, 16);
+    if (curState.cell.gsmCellId !== cid) {
+      curState.cell.gsmCellId = cid;
+      changed = true;
+    }
+
     let radioTech = RIL.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN);
     if (curState.radioTech != radioTech) {
       changed = true;
       curState.radioTech = radioTech;
       curState.type = GECKO_RADIO_TECH[radioTech] || null;
     }
     return changed;
   },
 
   _processVoiceRegistrationState: function _processVoiceRegistrationState(state) {
     let rs = this.voiceRegistrationState;
     let stateChanged = this._processCREG(rs, state);
     if (stateChanged && rs.connected) {
       RIL.getSMSCAddress();
     }
 
-    let cell = this.cellLocation;
-    let cellChanged = false;
-
-    // From TS 23.003, 0000 and 0xfffe are indicated that no valid LAI exists
-    // in MS. So we still need to report the '0000' as well.
-    let lac = parseInt(state[1], 16);
-    if (cell.lac !== lac) {
-      cell.lac = lac;
-      cellChanged = true;
-    }
-
-    let cid = parseInt(state[2], 16);
-    if (cell.cid !== cid) {
-      cell.cid = cid;
-      cellChanged = true;
-    }
-
-    if (cellChanged) {
-      cell.rilMessageType = "celllocationchanged";
-      this.sendDOMMessage(cell);
-    }
-
     // TODO: This zombie code branch that will be raised from the dead once
     // we add explicit CDMA support everywhere (bug 726098).
     let cdma = false;
     if (cdma) {
       let baseStationId = RIL.parseInt(state[4]);
       let baseStationLatitude = RIL.parseInt(state[5]);
       let baseStationLongitude = RIL.parseInt(state[6]);
       if (!baseStationLatitude && !baseStationLongitude) {
@@ -2832,56 +2905,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 +3317,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/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -519,25 +519,26 @@ var interfaceNamesInGlobalScope =
     "HTMLLIElement",
     "SVGClipPathElement",
     "NavigatorGeolocation",
     "HTMLParagraphElement",
     "EventTarget",
     "File",
     "WebGLActiveInfo",
     "SVGGradientElement",
-    "ContactTelephone",
-    "ContactEmail",
+    "ContactTelField",
+    "ContactField",
     "SVGFitToViewBox",
     "SVGAElement",
     "NavigatorCamera",
     "CameraControl",
     "CameraCapabilities",
     "CameraManager",
-    "CSSSupportsRule"
+    "CSSSupportsRule",
+    "MozMobileCellInfo"
   ]
 
 for (var i in Components.interfaces) {
   var s = i.toString();
   var name = null;
   if (s.indexOf("nsIDOM") == 0) {
     name = s.substring("nsIDOM".length);
   } else if (s.indexOf("nsI") == 0) {
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -47,30 +47,27 @@
 #include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMHTMLObjectElement.h"
 #include "nsIDOMHTMLScriptElement.h"
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIDOMHTMLTableElement.h"
 #include "nsIDOMHTMLTableRowElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMRange.h"
-#include "nsIDocShell.h"
-#include "nsIDocShellTreeItem.h"
 #include "nsIDocument.h"
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsIEditorMailSupport.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsINameSpaceManager.h"
 #include "nsINode.h"
 #include "nsIParserUtils.h"
 #include "nsIPlaintextEditor.h"
-#include "nsIPrincipal.h"
 #include "nsISelection.h"
 #include "nsISupportsImpl.h"
 #include "nsISupportsPrimitives.h"
 #include "nsISupportsUtils.h"
 #include "nsITransferable.h"
 #include "nsIURI.h"
 #include "nsIVariant.h"
 #include "nsLinebreakConverter.h"
@@ -1166,45 +1163,16 @@ nsHTMLEditor::ParseCFHTML(nsCString & aC
                                                            nsLinebreakConverter::eLinebreakContent, 
                                                            oldLengthInChars, &newLengthInChars);
   // it's ok for context to be empty.  frag might be whole doc and contain all its context.
 
   // we're done!
   return NS_OK;
 }
 
-bool nsHTMLEditor::IsSafeToInsertData(nsIDOMDocument* aSourceDoc)
-{
-  // Try to determine whether we should use a sanitizing fragment sink
-  bool isSafe = false;
-
-  nsCOMPtr<nsIDocument> destdoc = GetDocument();
-  NS_ASSERTION(destdoc, "Where is our destination doc?");
-  nsCOMPtr<nsISupports> container = destdoc->GetContainer();
-  nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(container);
-  nsCOMPtr<nsIDocShellTreeItem> root;
-  if (dsti)
-    dsti->GetRootTreeItem(getter_AddRefs(root));
-  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(root);
-  PRUint32 appType;
-  if (docShell && NS_SUCCEEDED(docShell->GetAppType(&appType)))
-    isSafe = appType == nsIDocShell::APP_TYPE_EDITOR;
-  if (!isSafe && aSourceDoc) {
-    nsCOMPtr<nsIDocument> srcdoc = do_QueryInterface(aSourceDoc);
-    NS_ASSERTION(srcdoc, "Where is our source doc?");
-
-    nsIPrincipal* srcPrincipal = srcdoc->NodePrincipal();
-    nsIPrincipal* destPrincipal = destdoc->NodePrincipal();
-    NS_ASSERTION(srcPrincipal && destPrincipal, "How come we don't have a principal?");
-    srcPrincipal->Subsumes(destPrincipal, &isSafe);
-  }
-
-  return isSafe;
-}
-
 nsresult nsHTMLEditor::InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe,
                                     nsIDOMDocument *aSourceDoc,
                                     nsIDOMNode *aDestinationNode,
                                     PRInt32 aDestOffset,
                                     bool aDoDeleteSelection)
 {
   nsresult rv;
 
--- 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/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -529,20 +529,16 @@ protected:
     *                        (usually true, unless those characters
     *                        have already been added.)
     * @return aNodeInserted  The node spanning the insertion, if applicable.
     *                        If aAddCites is false, this will be null.
     */
   NS_IMETHOD InsertAsPlaintextQuotation(const nsAString & aQuotedText,
                                         bool aAddCites,
                                         nsIDOMNode **aNodeInserted);
-  // Return true if the data is safe to insert as the source and destination
-  // principals match, or we are in a editor context where this doesn't matter.
-  // Otherwise, the data must be sanitized first.
-  bool IsSafeToInsertData(nsIDOMDocument* aSourceDoc);
 
   nsresult InsertObject(const char* aType, nsISupports* aObject, bool aIsSafe,
                         nsIDOMDocument *aSourceDoc,
                         nsIDOMNode *aDestinationNode,
                         PRInt32 aDestOffset,
                         bool aDoDeleteSelection);
 
   // factored methods for handling insertion of data from transferables (drag&drop or clipboard)
--- 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/libeditor/text/nsPlaintextDataTransfer.cpp
+++ b/editor/libeditor/text/nsPlaintextDataTransfer.cpp
@@ -23,16 +23,19 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMUIEvent.h"
 #include "nsIDocument.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
+#include "nsIDocShell.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIPrincipal.h"
 #include "nsIFormControl.h"
 #include "nsIPlaintextEditor.h"
 #include "nsISelection.h"
 #include "nsISupportsPrimitives.h"
 #include "nsITransferable.h"
 #include "nsIVariant.h"
 #include "nsLiteralString.h"
 #include "nsPlaintextEditor.h"
@@ -168,19 +171,31 @@ nsresult nsPlaintextEditor::InsertFromDr
 
   nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
   nsresult rv = dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
   NS_ASSERTION(dragSession, "No drag session");
 
+  nsCOMPtr<nsIDOMNode> sourceNode;
+  dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
+
+  nsCOMPtr<nsIDOMDocument> srcdomdoc;
+  if (sourceNode) {
+    sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
+    NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
+  }
+
   nsDragEvent* dragEventInternal = static_cast<nsDragEvent *>(aDropEvent->GetInternalNSEvent());
   if (nsContentUtils::CheckForSubFrameDrop(dragSession, dragEventInternal)) {
-    return NS_OK;
+    // Don't allow drags from subframe documents with different origins than
+    // the drop destination.
+    if (srcdomdoc && !IsSafeToInsertData(srcdomdoc))
+      return NS_OK;
   }
 
   // Current doc is destination
   nsCOMPtr<nsIDOMDocument> destdomdoc = GetDOMDocument();
   NS_ENSURE_TRUE(destdomdoc, NS_ERROR_NOT_INITIALIZED);
 
   PRUint32 numItems = 0;
   rv = dataTransfer->GetMozItemCount(&numItems);
@@ -208,25 +223,16 @@ nsresult nsPlaintextEditor::InsertFromDr
 
   nsCOMPtr<nsISelection> selection;
   rv = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
 
   bool isCollapsed = selection->Collapsed();
 
-  nsCOMPtr<nsIDOMNode> sourceNode;
-  dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
-
-  nsCOMPtr<nsIDOMDocument> srcdomdoc;
-  if (sourceNode) {
-    sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
-    NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
-  }
-
   // Only the nsHTMLEditor::FindUserSelectAllNode returns a node.
   nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
   if (userSelectNode)
   {
     // The drop is happening over a "-moz-user-select: all"
     // subtree so make sure the content we insert goes before
     // the root of the subtree.
     //
@@ -414,8 +420,38 @@ NS_IMETHODIMP nsPlaintextEditor::CanPast
                                                &dataLen);
   if (NS_SUCCEEDED(rv) && data)
     *aCanPaste = true;
   else
     *aCanPaste = false;
   
   return NS_OK;
 }
+
+bool nsPlaintextEditor::IsSafeToInsertData(nsIDOMDocument* aSourceDoc)
+{
+  // Try to determine whether we should use a sanitizing fragment sink
+  bool isSafe = false;
+
+  nsCOMPtr<nsIDocument> destdoc = GetDocument();
+  NS_ASSERTION(destdoc, "Where is our destination doc?");
+  nsCOMPtr<nsISupports> container = destdoc->GetContainer();
+  nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(container);
+  nsCOMPtr<nsIDocShellTreeItem> root;
+  if (dsti)
+    dsti->GetRootTreeItem(getter_AddRefs(root));
+  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(root);
+  PRUint32 appType;
+  if (docShell && NS_SUCCEEDED(docShell->GetAppType(&appType)))
+    isSafe = appType == nsIDocShell::APP_TYPE_EDITOR;
+  if (!isSafe && aSourceDoc) {
+    nsCOMPtr<nsIDocument> srcdoc = do_QueryInterface(aSourceDoc);
+    NS_ASSERTION(srcdoc, "Where is our source doc?");
+
+    nsIPrincipal* srcPrincipal = srcdoc->NodePrincipal();
+    nsIPrincipal* destPrincipal = destdoc->NodePrincipal();
+    NS_ASSERTION(srcPrincipal && destPrincipal, "How come we don't have a principal?");
+    srcPrincipal->Subsumes(destPrincipal, &isSafe);
+  }
+
+  return isSafe;
+}
+
--- a/editor/libeditor/text/nsPlaintextEditor.h
+++ b/editor/libeditor/text/nsPlaintextEditor.h
@@ -149,16 +149,21 @@ public:
   /**
    * Extends the selection for given deletion operation
    * If done, also update aAction to what's actually left to do after the
    * extension.
    */
   nsresult ExtendSelectionForDelete(nsISelection* aSelection,
                                     nsIEditor::EDirection *aAction);
 
+  // Return true if the data is safe to insert as the source and destination
+  // principals match, or we are in a editor context where this doesn't matter.
+  // Otherwise, the data must be sanitized first.
+  bool IsSafeToInsertData(nsIDOMDocument* aSourceDoc);
+
   static void GetDefaultEditorPrefs(PRInt32 &aNewLineHandling,
                                     PRInt32 &aCaretStyle);
 
 protected:
 
   NS_IMETHOD  InitRules();
   void        BeginEditorInit();
   nsresult    EndEditorInit();
--- 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);
-