Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Thu, 16 Aug 2012 14:04:20 -0700
changeset 107101 d1b17b12a472efd78831ef9f6b9f331c96c438b0
parent 107100 599a761c17fe37433d1177c445bbd99c49f4f0df (current diff)
parent 102934 57e59b2e017e9ed8ab2389b23a675431dbe83d1f (diff)
child 107102 f6c3f006b57a8136dd40d4e4b530c630300d1c0b
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone17.0a1
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);