Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Thu, 09 Aug 2012 13:41:13 -0700
changeset 112952 52fdeb6d8d6dc6947dc4712f0781fd17beba65d1
parent 112951 c0195737650c31a80a473456c58fe6774c717a79 (current diff)
parent 107405 4770bca010461123a3bfde393bdebd1884dc3fcf (diff)
child 112953 b07af1efa3dddb495ac1927830f9d0cb746ee886
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
browser/base/content/test/test_contextmenu.html
browser/components/nsBrowserGlue.js
browser/themes/winstripe/browser.css
caps/src/nsPrincipal.cpp
content/base/public/DirectionalityUtils.h
content/base/public/nsIDocument.h
content/base/public/nsINode.h
content/base/src/DirectionalityUtils.cpp
content/base/src/Makefile.in
content/base/src/nsContentSink.h
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsFrameLoader.cpp
content/base/src/nsGenericElement.cpp
content/base/src/nsGkAtomList.h
content/base/src/nsNodeInfoManager.cpp
content/base/test/Makefile.in
content/base/test/test_bug562169-1.html
content/base/test/test_bug562169-2.html
content/canvas/test/test_canvas.html
content/events/src/nsDOMSimpleGestureEvent.cpp
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/document/src/ImageDocument.cpp
content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp
content/xslt/src/xpath/txNodeSet.cpp
content/xslt/src/xpath/txXPathTreeWalker.h
content/xslt/src/xslt/txFormatNumberFunctionCall.cpp
content/xul/templates/src/nsRuleNetwork.cpp
content/xul/templates/src/nsRuleNetwork.h
content/xul/templates/src/nsXULTemplateQueryProcessorStorage.cpp
docshell/base/nsDocShell.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMNavigationTiming.cpp
dom/base/nsDOMNavigationTiming.h
dom/base/nsDOMWindowUtils.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/Makefile.in
dom/ipc/PBrowser.ipdl
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/plugins/base/nsPluginNativeWindowGtk2.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
dom/src/geolocation/nsGeolocation.cpp
dom/src/geolocation/nsGeolocation.h
dom/src/notification/nsDesktopNotification.cpp
dom/src/notification/nsDesktopNotification.h
editor/libeditor/html/nsHTMLCSSUtils.cpp
editor/libeditor/html/nsHTMLEditor.cpp
gfx/layers/basic/BasicThebesLayer.h
gfx/src/nsColor.cpp
gfx/thebes/gfxWindowsPlatform.cpp
image/decoders/nsPNGDecoder.cpp
image/src/RasterImage.cpp
image/src/imgLoader.cpp
image/src/imgLoader.h
js/src/Makefile.in
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/js.msg
js/src/jsatom.cpp
js/src/jsatom.h
js/src/jsgc.cpp
js/src/jshash.cpp
js/src/jshash.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsproxy.cpp
js/src/jsreflect.cpp
js/src/jsscope.cpp
js/src/jsscript.h
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/methodjit/PolyIC.cpp
js/src/vm/String.h
js/xpconnect/src/XPCMaps.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/crashtests/crashtests.list
layout/base/nsBidi.cpp
layout/base/nsBidi.h
layout/base/nsCSSRendering.cpp
layout/base/nsCSSRendering.h
layout/base/nsCSSRenderingBorders.cpp
layout/base/nsCSSRenderingBorders.h
layout/base/nsFrameManager.cpp
layout/base/nsPresShell.cpp
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsFileControlFrame.cpp
layout/forms/nsFileControlFrame.h
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsHTMLButtonControlFrame.h
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsBlockReflowContext.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsFirstLetterFrame.cpp
layout/generic/nsFirstLetterFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsFrameSetFrame.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIFrame.h
layout/generic/nsImageFrame.cpp
layout/generic/nsImageFrame.h
layout/generic/nsInlineFrame.cpp
layout/generic/nsInlineFrame.h
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLContainerFrame.h
layout/mathml/nsMathMLTokenFrame.h
layout/mathml/nsMathMLmactionFrame.h
layout/mathml/nsMathMLmfracFrame.h
layout/mathml/nsMathMLmmultiscriptsFrame.h
layout/mathml/nsMathMLmoFrame.h
layout/mathml/nsMathMLmpaddedFrame.h
layout/mathml/nsMathMLmspaceFrame.h
layout/mathml/nsMathMLmsubFrame.h
layout/mathml/nsMathMLmsubsupFrame.h
layout/mathml/nsMathMLmsupFrame.h
layout/mathml/nsMathMLmtableFrame.h
layout/mathml/nsMathMLmunderoverFrame.h
layout/reftests/bidi/562169-1-ref.html
layout/reftests/bidi/562169-1.html
layout/reftests/bidi/562169-1a.html
layout/reftests/bidi/562169-2-ref.html
layout/reftests/bidi/562169-2.html
layout/reftests/bidi/562169-2a.html
layout/reftests/bidi/562169-3-ref.html
layout/reftests/bidi/562169-3.html
layout/reftests/bidi/562169-3a.html
layout/reftests/bidi/562169-4-ref.html
layout/reftests/bidi/562169-4.html
layout/style/nsCSSParser.cpp
layout/style/nsCSSPseudoClasses.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableColGroupFrame.h
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableOuterFrame.h
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowFrame.h
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
layout/xul/base/src/nsGroupBoxFrame.cpp
mobile/android/chrome/content/browser.js
mobile/xul/chrome/content/WebappsUI.js
modules/libpref/src/init/all.js
netwerk/cache/nsCacheEntryDescriptor.cpp
netwerk/cache/nsDiskCacheStreams.cpp
netwerk/cache/nsDiskCacheStreams.h
netwerk/dns/nsHostResolver.cpp
netwerk/protocol/http/nsHttpAuthCache.cpp
netwerk/protocol/http/nsHttpAuthCache.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/socket/nsSOCKSIOLayer.cpp
netwerk/streamconv/converters/mozTXTToHTMLConv.cpp
netwerk/test/TestProtocols.cpp
netwerk/test/TestSocketIO.cpp
rdf/base/src/nsRDFService.cpp
security/manager/ssl/src/nsCRLManager.cpp
security/manager/ssl/src/nsNSSCertHelper.cpp
security/manager/ssl/src/nsNSSComponent.cpp
security/manager/ssl/src/nsNSSIOLayer.cpp
security/manager/ssl/src/nsPKCS12Blob.cpp
testing/mochitest/ssltunnel/ssltunnel.cpp
toolkit/components/alerts/mac/nsAlertsService.h
toolkit/components/alerts/mac/nsAlertsService.mm
toolkit/components/alerts/nsAlertsService.cpp
toolkit/components/downloads/nsDownloadManager.cpp
toolkit/components/telemetry/TelemetryPing.js
toolkit/crashreporter/nsExceptionHandler.cpp
widget/nsGUIEvent.h
widget/qt/nsWindow.cpp
widget/xremoteclient/XRemoteClient.cpp
xpcom/base/nsDebugImpl.cpp
xpcom/base/nsMemoryImpl.cpp
xpcom/base/nsTraceRefcntImpl.cpp
xpcom/build/nsXPCOM.h
xpcom/build/nsXPCOMPrivate.h
xpcom/ds/nsCRT.h
xpcom/ds/nsSupportsArray.cpp
xpcom/ds/nsSupportsArray.h
xpcom/glue/nsMemory.cpp
xpcom/glue/nsMemory.h
xpcom/glue/nsTArray-inl.h
xpcom/glue/pldhash.cpp
xpcom/glue/standalone/nsXPCOMGlue.cpp
xpcom/io/nsLocalFileUnix.cpp
xpcom/io/nsLocalFileUnix.h
xpcom/io/nsLocalFileWin.cpp
xpcom/string/public/nsTSubstring.h
xpcom/string/src/nsTSubstring.cpp
xpcom/stub/nsXPComStub.cpp
xpcom/tests/TestTArray.cpp
--- a/b2g/components/AlertsService.js
+++ b/b2g/components/AlertsService.js
@@ -10,17 +10,17 @@ Cu.import("resource://gre/modules/Servic
 
 // -----------------------------------------------------------------------
 // Alerts Service
 // -----------------------------------------------------------------------
 
 function AlertsService() { }
 
 AlertsService.prototype = {
-  classID: Components.ID("{5dce03b2-8faa-4b6e-9242-6ddb0411750c}"),
+  classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]),
 
   showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName) {
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName);
   }
 };
 
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -2,18 +2,18 @@
 category agent-style-sheets browser-content-stylesheet chrome://browser/content/content.css
 
 # CameraContent.js
 component {eff4231b-abce-4f7f-a40a-d646e8fde3ce} CameraContent.js
 contract @mozilla.org/b2g-camera-content;1 {eff4231b-abce-4f7f-a40a-d646e8fde3ce}
 category JavaScript-navigator-property mozCamera @mozilla.org/b2g-camera-content;1
 
 # AlertsService.js
-component {5dce03b2-8faa-4b6e-9242-6ddb0411750c} AlertsService.js
-contract @mozilla.org/alerts-service;1 {5dce03b2-8faa-4b6e-9242-6ddb0411750c}
+component {fe33c107-82a4-41d6-8c64-5353267e04c9} AlertsService.js
+contract @mozilla.org/system-alerts-service;1 {fe33c107-82a4-41d6-8c64-5353267e04c9}
 
 # ContentPermissionPrompt.js
 component {8c719f03-afe0-4aac-91ff-6c215895d467} ContentPermissionPrompt.js
 contract @mozilla.org/content-permission/prompt;1 {8c719f03-afe0-4aac-91ff-6c215895d467}
 
 #ifdef MOZ_UPDATER
 # UpdatePrompt.js
 component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js
--- a/b2g/components/ContentPermissionPrompt.js
+++ b/b2g/components/ContentPermissionPrompt.js
@@ -10,17 +10,17 @@ const Cc = Components.classes;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 function ContentPermissionPrompt() {}
 
 ContentPermissionPrompt.prototype = {
 
   handleExistingPermission: function handleExistingPermission(request) {
-    let result = Services.perms.testExactPermission(request.uri, request.type);
+    let result = Services.perms.testExactPermissionFromPrincipal(request.principal, request.type);
     if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
       request.allow();
       return true;
     }
     if (result == Ci.nsIPermissionManager.DENY_ACTION) {
       request.cancel();
       return true;
     }
@@ -51,17 +51,17 @@ ContentPermissionPrompt.prototype = {
 
       request.cancel();
     });
 
     let details = {
       "type": "permission-prompt",
       "permission": request.type,
       "id": requestId,
-      "url": request.uri.spec
+      "url": request.principal.URI.spec
     };
     let event = content.document.createEvent("CustomEvent");
     event.initCustomEvent("mozChromeEvent", true, true, details);
     content.dispatchEvent(event);
   },
 
   classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"),
 
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -226,17 +226,17 @@ var gPluginHandler = {
                "PFSWindow", "chrome,centerscreen,resizable=yes",
                {plugins: missingPluginsArray, browser: gBrowser.selectedBrowser});
   },
 
   // Callback for user clicking on a disabled plugin
   managePlugins: function (aEvent) {
     BrowserOpenAddonsMgr("addons://list/plugin");
   },
- 
+
   // Callback for user clicking on the link in a click-to-play plugin
   // (where the plugin has an update)
   openPluginUpdatePage: function (aEvent) {
     openURL(Services.urlFormatter.formatURLPref("plugins.update.url"));
   },
 
 #ifdef MOZ_CRASHREPORTER
   // Callback for user clicking "submit a report" link
@@ -274,19 +274,18 @@ var gPluginHandler = {
       if (overlay)
         overlay.style.visibility = "hidden";
       return;
     }
 
     // The overlay is null if the XBL binding is not attached (element is display:none).
     if (overlay) {
       overlay.addEventListener("click", function(aEvent) {
-        // Have to check that the target is a XULElement and not the link
-        // to update the plugin
-        if (aEvent.target instanceof XULElement && 
+        // Have to check that the target is not the link to update the plugin
+        if (!(aEvent.originalTarget instanceof HTMLAnchorElement) &&
             aEvent.button == 0 && aEvent.isTrusted)
           gPluginHandler.activateSinglePlugin(aEvent.target.ownerDocument.defaultView.top, aPlugin);
       }, true);
     }
 
     if (!browser._clickToPlayDoorhangerShown)
       gPluginHandler._showClickToPlayNotification(browser);
   },
--- a/browser/base/content/browser-thumbnails.js
+++ b/browser/base/content/browser-thumbnails.js
@@ -21,21 +21,16 @@ let gBrowserThumbnails = {
   _sslDiskCacheEnabled: null,
 
   /**
    * Map of capture() timeouts assigned to their browsers.
    */
   _timeouts: null,
 
   /**
-   * Cache for the PageThumbs module.
-   */
-  _pageThumbs: null,
-
-  /**
    * List of tab events we want to listen for.
    */
   _tabEvents: ["TabClose", "TabSelect"],
 
   init: function Thumbnails_init() {
     try {
       if (Services.prefs.getBoolPref("browser.pagethumbnails.capturing_disabled"))
         return;
@@ -47,19 +42,16 @@ let gBrowserThumbnails = {
     this._sslDiskCacheEnabled =
       Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
 
     this._tabEvents.forEach(function (aEvent) {
       gBrowser.tabContainer.addEventListener(aEvent, this, false);
     }, this);
 
     this._timeouts = new WeakMap();
-
-    XPCOMUtils.defineLazyModuleGetter(this, "_pageThumbs",
-      "resource:///modules/PageThumbs.jsm", "PageThumbs");
   },
 
   uninit: function Thumbnails_uninit() {
     gBrowser.removeTabsProgressListener(this);
     Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
 
     this._tabEvents.forEach(function (aEvent) {
       gBrowser.tabContainer.removeEventListener(aEvent, this, false);
@@ -95,17 +87,17 @@ let gBrowserThumbnails = {
                                                    aRequest, aStateFlags, aStatus) {
     if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
         aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)
       this._delayedCapture(aBrowser);
   },
 
   _capture: function Thumbnails_capture(aBrowser) {
     if (this._shouldCapture(aBrowser))
-      this._pageThumbs.captureAndStore(aBrowser);
+      PageThumbs.captureAndStore(aBrowser);
   },
 
   _delayedCapture: function Thumbnails_delayedCapture(aBrowser) {
     if (this._timeouts.has(aBrowser))
       clearTimeout(this._timeouts.get(aBrowser));
     else
       aBrowser.addEventListener("scroll", this, true);
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -135,16 +135,19 @@ XPCOMUtils.defineLazyGetter(this, "Tilt"
 });
 
 XPCOMUtils.defineLazyGetter(this, "Social", function() {
   let tmp = {};
   Cu.import("resource:///modules/Social.jsm", tmp);
   return tmp.Social;
 });
 
+XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
+  "resource:///modules/PageThumbs.jsm");
+
 #ifdef MOZ_SAFE_BROWSING
 XPCOMUtils.defineLazyGetter(this, "SafeBrowsing", function() {
   let tmp = {};
   Cu.import("resource://gre/modules/SafeBrowsing.jsm", tmp);
   return tmp.SafeBrowsing;
 });
 #endif
 
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3402,17 +3402,30 @@
         // We must not set text/x-moz-url or text/plain data here,
         // otherwise trying to deatch the tab by dropping it on the desktop
         // may result in an "internet shortcut"
         dt.mozSetDataAt("text/x-moz-text-internal", spec, 0);
 
         // Set the cursor to an arrow during tab drags.
         dt.mozCursor = "default";
 
-        let canvas = tabPreviews.capture(tab, false);
+        // Create a canvas to which we capture the current tab.
+        let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+        canvas.mozOpaque = true;
+
+        // We want drag images to be about 1/6th of the available screen width.
+        const widthFactor = 0.1739; // 1:5.75 inverse
+        canvas.width = Math.ceil(screen.availWidth * widthFactor);
+
+        // Maintain a 16:9 aspect ratio for drag images.
+        const aspectRatio = 0.5625; // 16:9 inverse
+        canvas.height = Math.round(canvas.width * aspectRatio);
+
+        let browser = tab.linkedBrowser;
+        PageThumbs.captureToCanvas(browser.contentWindow, canvas);
         dt.setDragImage(canvas, 0, 0);
 
         // _dragOffsetX/Y give the coordinates that the mouse should be
         // positioned relative to the corner of the new window created upon
         // dragend such that the mouse appears to have the same position
         // relative to the corner of the dragged tab.
         function clientX(ele) ele.getBoundingClientRect().left;
         let tabOffsetX = clientX(tab) -
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -141,18 +141,17 @@ function test3() {
 
   new TabOpenListener("about:addons", test4, prepareTest5);
 
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 3, Found plugin in page");
   var manageLink = gTestBrowser.contentDocument.getAnonymousElementByAttribute(pluginNode, "class", "managePluginsLink");
   ok(manageLink, "Test 3, found 'manage' link in plugin-problem binding");
 
-  EventUtils.synthesizeMouse(manageLink,
-                             5, 5, {}, gTestBrowser.contentWindow);
+  EventUtils.synthesizeMouseAtCenter(manageLink, {}, gTestBrowser.contentWindow);
 }
 
 function test4(tab, win) {
   is(win.wrappedJSObject.gViewController.currentViewId, "addons://list/plugin", "Test 4, Should have displayed the plugins pane");
   gBrowser.removeTab(tab);
 }
 
 function prepareTest5() {
@@ -232,17 +231,17 @@ function test9a() {
 
   var plugin2 = doc.getElementById("test2");
   var rect = doc.getAnonymousElementByAttribute(plugin2, "class", "mainBox").getBoundingClientRect();
   ok(rect.width == 200, "Test 9a, Plugin with id=" + plugin2.id + " overlay rect should have 200px width before being clicked");
   ok(rect.height == 200, "Test 9a, Plugin with id=" + plugin2.id + " overlay rect should have 200px height before being clicked");
   var objLoadingContent = plugin2.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 9a, Plugin with id=" + plugin2.id + " should not be activated");
 
-  EventUtils.synthesizeMouse(plugin1, 100, 100, { });
+  EventUtils.synthesizeMouseAtCenter(plugin1, {}, gTestBrowser.contentWindow);
   var objLoadingContent = plugin1.QueryInterface(Ci.nsIObjectLoadingContent);
   var condition = function() objLoadingContent.activated;
   waitForCondition(condition, test9b, "Test 9a, Waited too long for plugin to activate");
 }
 
 // Tests that activating one click-to-play plugin will activate only that plugin (part 2/3)
 function test9b() {
   var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
@@ -261,17 +260,17 @@ function test9b() {
 
   var plugin2 = doc.getElementById("test2");
   var pluginRect2 = doc.getAnonymousElementByAttribute(plugin2, "class", "mainBox").getBoundingClientRect();
   ok(pluginRect2.width != 0, "Test 9b, Plugin with id=" + plugin2.id + " should not have click-to-play overlay with zero width");
   ok(pluginRect2.height != 0, "Test 9b, Plugin with id=" + plugin2.id + " should not have click-to-play overlay with zero height");
   var objLoadingContent = plugin2.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 9b, Plugin with id=" + plugin2.id + " should not be activated");
 
-  EventUtils.synthesizeMouse(plugin2, 100, 100, { });
+  EventUtils.synthesizeMouseAtCenter(plugin2, {}, gTestBrowser.contentWindow);
   var objLoadingContent = plugin2.QueryInterface(Ci.nsIObjectLoadingContent);
   var condition = function() objLoadingContent.activated;
   waitForCondition(condition, test9c, "Test 9b, Waited too long for plugin to activate");
 }
 
 //
 // Tests that activating one click-to-play plugin will activate only that plugin (part 3/3)
 function test9c() {
@@ -477,17 +476,17 @@ function test16a() {
 
 // 2/4
 function test16b() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 16b, Should have a click-to-play notification");
   var plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[0];
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 16b, Plugin should not be activated");
-  EventUtils.synthesizeMouse(plugin, 100, 100, { });
+  EventUtils.synthesizeMouseAtCenter(plugin, {}, gTestBrowser.contentWindow);
   var condition = function() objLoadingContent.activated;
   waitForCondition(condition, test16c, "Test 16b, Waited too long for plugin to activate");
 }
 
 // 3/4
 function test16c() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(!popupNotification, "Test 16c, Should not have a click-to-play notification");
@@ -585,20 +584,28 @@ function test18a() {
     if (event.type == "TabOpen") {
       gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
       this.tab = event.originalTarget;
       ok(event.target.label == this.url, "Test 18a, Update link should open up the plugin check page");
       gBrowser.removeTab(this.tab);
       test18b();
     }
   };
-  EventUtils.synthesizeMouse(updateLink, 5, 5, {}, gTestBrowser.contentWindow);
+  EventUtils.synthesizeMouseAtCenter(updateLink, {}, gTestBrowser.contentWindow);
 }
 
 function test18b() {
+  // clicking the update link should not activate the plugin
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(!objLoadingContent.activated, "Test 18b, Plugin should not be activated");
+  var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
+  ok(overlay.style.visibility != "hidden", "Test 18b, Plugin overlay should exist, not be hidden");
+
   unregisterFakeBlocklistService();
   registerFakeBlocklistService(Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
   prepareTest(test18c, gTestRoot + "plugin_test.html");
 }
 
 // Tests a vulnerable plugin with no update
 function test18c() {
   var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
@@ -611,10 +618,76 @@ function test18c() {
   ok(overlay.style.visibility != "hidden", "Test 18c, Plugin overlay should exist, not be hidden");
   var updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
   ok(updateLink.style.display != "block", "Test 18c, Plugin should not have an update link");
 
   unregisterFakeBlocklistService();
   var plugin = get_test_plugin();
   plugin.clicktoplay = false;
 
+  prepareTest(test19a, gTestRoot + "plugin_test.html");
+}
+
+// Tests that clicking the icon of the overlay activates the plugin
+function test19a() {
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(!objLoadingContent.activated, "Test 19a, Plugin should not be activated");
+
+  var icon = doc.getAnonymousElementByAttribute(plugin, "class", "icon");
+  EventUtils.synthesizeMouseAtCenter(icon, {}, gTestBrowser.contentWindow);
+  var condition = function() objLoadingContent.activated;
+  waitForCondition(condition, test19b, "Test 19a, Waited too long for plugin to activate");
+}
+
+function test19b() {
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(objLoadingContent.activated, "Test 19b, Plugin should be activated");
+
+  prepareTest(test19c, gTestRoot + "plugin_test.html");
+}
+
+// Tests that clicking the text of the overlay activates the plugin
+function test19c() {
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(!objLoadingContent.activated, "Test 19c, Plugin should not be activated");
+
+  var text = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
+  EventUtils.synthesizeMouseAtCenter(text, {}, gTestBrowser.contentWindow);
+  var condition = function() objLoadingContent.activated;
+  waitForCondition(condition, test19d, "Test 19c, Waited too long for plugin to activate");
+}
+
+function test19d() {
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(objLoadingContent.activated, "Test 19d, Plugin should be activated");
+
+  prepareTest(test19e, gTestRoot + "plugin_test.html");
+}
+
+// Tests that clicking the box of the overlay activates the plugin
+// (just to be thorough)
+function test19e() {
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(!objLoadingContent.activated, "Test 19e, Plugin should not be activated");
+
+  EventUtils.synthesizeMouse(plugin, 50, 50, {}, gTestBrowser.contentWindow);
+  var condition = function() objLoadingContent.activated;
+  waitForCondition(condition, test19f, "Test 19e, Waited too long for plugin to activate");
+}
+
+function test19f() {
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(objLoadingContent.activated, "Test 19f, Plugin should be activated");
+
   finishTest();
 }
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -13,19 +13,17 @@ Browser context menu tests.
 <div id="content">
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Login Manager: multiple login autocomplete. **/
 
-netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
+SpecialPowers.wrap(Components).utils.import("resource://gre/modules/InlineSpellChecker.jsm", window);
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 function openContextMenuFor(element, shiftkey, shouldWaitForFocus) {
     // Context menu should be closed before we open it again.
     is(SpecialPowers.wrap(contextMenu).state, "closed", "checking if popup is closed");
 
@@ -724,33 +722,33 @@ function runTest(testNum) {
                          ].concat(inspectItems));
         closeContextMenu();
         selectText(selecttext); // Select text prior to opening context menu.
         openContextMenuFor(selecttext); // Invoke context menu for next test.
         return;
 
     case 24:
         // Context menu for selected text
-        if (Services.appinfo.OS == "Darwin") {
+        if (SpecialPowers.Services.appinfo.OS == "Darwin") {
           // This test is only enabled on Mac due to bug 736399.
           checkContextMenu(["context-copy",                        true,
                             "context-selectall",                   true,
                             "---",                                 null,
                             "context-searchselect",                true,
                             "context-viewpartialsource-selection", true
                            ].concat(inspectItems));
         }
         closeContextMenu();
         selectText(selecttextlink); // Select text prior to opening context menu.
         openContextMenuFor(selecttextlink); // Invoke context menu for next test.
         return;
 
     case 25:
         // Context menu for selected text which matches valid URL pattern
-        if (Services.appinfo.OS == "Darwin") {
+        if (SpecialPowers.Services.appinfo.OS == "Darwin") {
           // This test is only enabled on Mac due to bug 736399.
           checkContextMenu(["context-openlinkincurrent",           true,
                             "context-openlinkintab",               true,
                             "context-openlink",                    true,
                             "---",                                 null,
                             "context-bookmarklink",                true,
                             "context-savelink",                    true,
                             "context-copy",                        true,
@@ -785,18 +783,17 @@ function runTest(testNum) {
 
 var testNum = 1;
 var subwindow, chromeWin, contextMenu, lastElement;
 var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
     iframe, video_in_iframe, image_in_iframe, textarea, contenteditable,
     inputspell, pagemenu, dom_full_screen, plainTextItems, audio_in_video;
 
 function startTest() {
-    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-    chromeWin = subwindow
+    chromeWin = SpecialPowers.wrap(subwindow)
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIDOMWindow)
                     .QueryInterface(Ci.nsIDOMChromeWindow);
     contextMenu = chromeWin.document.getElementById("contentAreaContextMenu");
--- a/browser/base/content/test/test_offlineNotification.html
+++ b/browser/base/content/test/test_offlineNotification.html
@@ -21,36 +21,36 @@ https://bugzilla.mozilla.org/show_bug.cg
 <iframe id="eventsTestFrame" src="offlineEvent.html"></iframe>
 
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
+const Cc = SpecialPowers.wrap(Components).classes;
 
 var numFinished = 0;
 
 window.addEventListener("message", function(event) {
     is(event.data, "success", "Child was successfully cached.");
 
     if (++numFinished == 3) {
       // Clean up after ourself
-      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-      var pm = Components.classes["@mozilla.org/permissionmanager;1"].
+      var pm = Cc["@mozilla.org/permissionmanager;1"].
                getService(Components.interfaces.nsIPermissionManager);
-      var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+      var ioService = Cc["@mozilla.org/network/io-service;1"]
                         .getService(Components.interfaces.nsIIOService);
       var uri1 = ioService.newURI(frames.testFrame.location, null, null);
       var uri2 = ioService.newURI(frames.testFrame3.location, null, null);
 
-      var principal1 = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+      var principal1 = Cc["@mozilla.org/scriptsecuritymanager;1"]
                         .getService(Components.interfaces.nsIScriptSecurityManager)
                         .getNoAppCodebasePrincipal(uri1);
-      var principal2 = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+      var principal2 = Cc["@mozilla.org/scriptsecuritymanager;1"]
                         .getService(Components.interfaces.nsIScriptSecurityManager)
                         .getNoAppCodebasePrincipal(uri2);
 
       pm.removeFromPrincipal(principal1, "offline-app");
       pm.removeFromPrincipal(principal2, "offline-app");
 
       SimpleTest.finish();
     }
@@ -103,26 +103,25 @@ function testEventHandling() {
 }
 
 function loaded() {
   testEventHandling();
 
   // Click the notification bar's "Allow" button.  This should kick
   // off updates, which will eventually lead to getting messages from
   // the children.
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
+  var wm = SpecialPowers.wrap(Components).classes["@mozilla.org/appshell/window-mediator;1"].
            getService(Components.interfaces.nsIWindowMediator);
   var win = wm.getMostRecentWindow("navigator:browser");
   var notificationBox = win.gBrowser.getNotificationBox();
 
   var notification = notificationBox.getNotificationWithValue("offline-app-requested-mochi.test");
   notification.childNodes[0].click();
 
-  notification = notificationBox.getNotificationWithValue("offline-app-requested-example.com");
+  notification = SpecialPowers.wrap(notificationBox).getNotificationWithValue("offline-app-requested-example.com");
   notification.childNodes[0].click();
 }
 
 </script>
 </pre>
 </body>
 </html>
 
--- a/browser/base/content/test/test_offline_gzip.html
+++ b/browser/base/content/test/test_offline_gzip.html
@@ -27,25 +27,23 @@ cache, it can be fetched from the cache 
 var cacheCount = 0;
 var intervalID = 0;
 
 window.addEventListener("message", handleMessageEvents, false);
 SimpleTest.waitForExplicitFinish();
 
 function finishTest() {
   // Clean up after ourselves.
-  netscape.security.PrivilegeManager
-          .enablePrivilege("UniversalXPConnect");
-  var pm = Components.classes["@mozilla.org/permissionmanager;1"].
+  var Cc = SpecialPowers.wrap(Components).classes;
+  var pm = Cc["@mozilla.org/permissionmanager;1"].
            getService(Components.interfaces.nsIPermissionManager);
 
-  var uri = Components.classes["@mozilla.org/network/io-service;1"]
-              .getService(Components.interfaces.nsIIOService)
+  var uri = Cc["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService)
               .newURI(window.frames[0].location, null, null);
-  var principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+  var principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
                    .getService(Components.interfaces.nsIScriptSecurityManager)
                    .getNoAppCodebasePrincipal(uri);
 
   pm.removeFromPrincipal(principal, "offline-app");
 
   window.removeEventListener("message", handleMessageEvents, false);
 
   SimpleTest.finish();  
@@ -65,18 +63,16 @@ function handleMessageEvents(event) {
       // in the case of bug 501422.
       frames.testFrame.window.location.reload();
       // Use setInterval to repeatedly call a function which
       // checks that one of two things has occurred:  either
       // the offline cache is udpated (which means our iframe
       // successfully reloaded), or the string "error" appears
       // in the iframe, as in the case of bug 501422.
       intervalID = setInterval(function() {
-        netscape.security.PrivilegeManager
-                .enablePrivilege("UniversalXPConnect");
         // Sometimes document.body may not exist, and trying to access
         // it will throw an exception, so handle this case.
         try {
           var bodyInnerHTML = frames.testFrame.document.body.innerHTML;
         }
         catch (e) {
           var bodyInnerHTML = "";
         }
@@ -98,18 +94,17 @@ function handleMessageEvents(event) {
       ok(false, "cacheCount not 1 or 2");
   }
 }
 
 function loaded() {
   // Click the notification bar's "Allow" button.  This should kick
   // off updates, which will eventually lead to getting messages from
   // the iframe.
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
+  var wm = SpecialPowers.wrap(Components).classes["@mozilla.org/appshell/window-mediator;1"].
            getService(Components.interfaces.nsIWindowMediator);
   var win = wm.getMostRecentWindow("navigator:browser");
   var notificationBox = win.gBrowser.getNotificationBox();
 
   var notification = notificationBox
     .getNotificationWithValue("offline-app-requested-mochi.test");
   notification.childNodes[0].click();
 }
--- a/browser/components/feeds/test/test_bug589543.html
+++ b/browser/components/feeds/test/test_bug589543.html
@@ -15,18 +15,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 589543 **/
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(function() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var doc = $("testFrame").contentDocument;
+  var doc = SpecialPowers.wrap($("testFrame").contentDocument);
   var daddy = doc.getElementById("feedSubscribeLine");
   var popup = doc.getAnonymousElementByAttribute(daddy, "anonid", "handlersMenuPopup");
   isnot(popup, null, "Feed preview should have a handlers popup");
 });
 addLoadEvent(SimpleTest.finish);
 
 </script>
 </pre>
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1555,23 +1555,24 @@ ContentPermissionPrompt.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt]),
 
   prompt: function CPP_prompt(request) {
 
     if (request.type != "geolocation") {
         return;
     }
 
-    var requestingURI = request.uri;
+    var requestingPrincipal = request.principal;
+    var requestingURI = requestingPrincipal.URI;
 
     // Ignore requests from non-nsIStandardURLs
     if (!(requestingURI instanceof Ci.nsIStandardURL))
       return;
 
-    var result = Services.perms.testExactPermission(requestingURI, "geo");
+    var result = Services.perms.testExactPermissionFromPrincipal(requestingPrincipal, "geo");
 
     if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
       request.allow();
       return;
     }
 
     if (result == Ci.nsIPermissionManager.DENY_ACTION) {
       request.cancel();
@@ -1614,25 +1615,25 @@ ContentPermissionPrompt.prototype = {
                                                    [requestingURI.host], 1);
 
       // Don't offer to "always/never share" in PB mode
       if (("gPrivateBrowsingUI" in chromeWin) && !chromeWin.gPrivateBrowsingUI.privateWindow) {
         secondaryActions.push({
           label: browserBundle.GetStringFromName("geolocation.alwaysShareLocation"),
           accessKey: browserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
           callback: function () {
-            Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
+            Services.perms.addFromPrincipal(requestingPrincipal, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
             request.allow();
           }
         });
         secondaryActions.push({
           label: browserBundle.GetStringFromName("geolocation.neverShareLocation"),
           accessKey: browserBundle.GetStringFromName("geolocation.neverShareLocation.accesskey"),
           callback: function () {
-            Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.DENY_ACTION);
+            Services.perms.addFromPrincipal(requestingPrincipal, "geo", Ci.nsIPermissionManager.DENY_ACTION);
             request.cancel();
           }
         });
       }
     }
 
     var browser = chromeWin.gBrowser.getBrowserForDocument(requestingWindow.document);
 
--- a/browser/components/thumbnails/PageThumbs.jsm
+++ b/browser/components/thumbnails/PageThumbs.jsm
@@ -111,43 +111,51 @@ let PageThumbs = {
    *                  captured. The first argument will be the data stream
    *                  containing the image data.
    */
   capture: function PageThumbs_capture(aWindow, aCallback) {
     if (!this._prefEnabled()) {
       return;
     }
 
-    let telemetryCaptureTime = new Date();
-    let [sw, sh, scale] = this._determineCropSize(aWindow);
+    let canvas = this._createCanvas();
+    this.captureToCanvas(aWindow, canvas);
 
-    let canvas = this._createCanvas();
-    let ctx = canvas.getContext("2d");
+    // Fetch the canvas data on the next event loop tick so that we allow
+    // some event processing in between drawing to the canvas and encoding
+    // its data. We want to block the UI as short as possible. See bug 744100.
+    Services.tm.currentThread.dispatch(function () {
+      canvas.mozFetchAsStream(aCallback, this.contentType);
+    }.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
+  },
+
+  /**
+   * Captures a thumbnail from a given window and draws it to the given canvas.
+   * @param aWindow The DOM window to capture a thumbnail from.
+   * @param aCanvas The canvas to draw to.
+   */
+  captureToCanvas: function PageThumbs_captureToCanvas(aWindow, aCanvas) {
+    let telemetryCaptureTime = new Date();
+    let [sw, sh, scale] = this._determineCropSize(aWindow, aCanvas);
+    let ctx = aCanvas.getContext("2d");
 
     // Scale the canvas accordingly.
     ctx.scale(scale, scale);
 
     try {
       // Draw the window contents to the canvas.
       ctx.drawWindow(aWindow, 0, 0, sw, sh, THUMBNAIL_BG_COLOR,
                      ctx.DRAWWINDOW_DO_NOT_FLUSH);
     } catch (e) {
       // We couldn't draw to the canvas for some reason.
     }
 
     let telemetry = Services.telemetry;
     telemetry.getHistogramById("FX_THUMBNAILS_CAPTURE_TIME_MS")
       .add(new Date() - telemetryCaptureTime);
-
-    // Fetch the canvas data on the next event loop tick so that we allow
-    // some event processing in between drawing to the canvas and encoding
-    // its data. We want to block the UI as short as possible. See bug 744100.
-    Services.tm.currentThread.dispatch(function () {
-      canvas.mozFetchAsStream(aCallback, this.contentType);
-    }.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
   },
 
   /**
    * Captures a thumbnail for the given browser and stores it to the cache.
    * @param aBrowser The browser to capture a thumbnail for.
    * @param aCallback The function to be called when finished (optional).
    */
   captureAndStore: function PageThumbs_captureAndStore(aBrowser, aCallback) {
@@ -188,23 +196,24 @@ let PageThumbs = {
 
       PageThumbsStorage.write(url, aInputStream, finish);
     });
   },
 
   /**
    * Determines the crop size for a given content window.
    * @param aWindow The content window.
+   * @param aCanvas The target canvas.
    * @return An array containing width, height and scale.
    */
-  _determineCropSize: function PageThumbs_determineCropSize(aWindow) {
+  _determineCropSize: function PageThumbs_determineCropSize(aWindow, aCanvas) {
     let sw = aWindow.innerWidth;
     let sh = aWindow.innerHeight;
 
-    let [thumbnailWidth, thumbnailHeight] = this._getThumbnailSize();
+    let {width: thumbnailWidth, height: thumbnailHeight} = aCanvas;
     let scale = Math.max(thumbnailWidth / sw, thumbnailHeight / sh);
     let scaledWidth = sw * scale;
     let scaledHeight = sh * scale;
 
     if (scaledHeight > thumbnailHeight)
       sh -= Math.floor(Math.abs(scaledHeight - thumbnailHeight) * scale);
 
     if (scaledWidth > thumbnailWidth)
--- a/browser/components/thumbnails/test/head.js
+++ b/browser/components/thumbnails/test/head.js
@@ -6,18 +6,16 @@ Cu.import("resource:///modules/PageThumb
 let PageThumbs = tmp.PageThumbs;
 let PageThumbsStorage = tmp.PageThumbsStorage;
 
 registerCleanupFunction(function () {
   while (gBrowser.tabs.length > 1)
     gBrowser.removeTab(gBrowser.tabs[1]);
 });
 
-let cachedXULDocument;
-
 /**
  * Provide the default test function to start our test runner.
  */
 function test() {
   TestRunner.run();
 }
 
 /**
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -46,25 +46,26 @@ let DebuggerController = {
   _startupDebugger: function DC__startupDebugger() {
     if (this._isInitialized) {
       return;
     }
     this._isInitialized = true;
     window.removeEventListener("DOMContentLoaded", this._startupDebugger, true);
 
     DebuggerView.initializePanes();
-    DebuggerView.initializeEditor();
-    DebuggerView.StackFrames.initialize();
-    DebuggerView.Breakpoints.initialize();
-    DebuggerView.Properties.initialize();
-    DebuggerView.Scripts.initialize();
-    DebuggerView.showCloseButton(!this._isRemoteDebugger && !this._isChromeDebugger);
+    DebuggerView.initializeEditor(function() {
+      DebuggerView.Scripts.initialize();
+      DebuggerView.StackFrames.initialize();
+      DebuggerView.Breakpoints.initialize();
+      DebuggerView.Properties.initialize();
+      DebuggerView.showCloseButton(!this._isRemoteDebugger && !this._isChromeDebugger);
 
-    this.dispatchEvent("Debugger:Loaded");
-    this._connect();
+      this.dispatchEvent("Debugger:Loaded");
+      this._connect();
+    }.bind(this));
   },
 
   /**
    * Destroys the debugger view, disconnects the debugger client and cleans up
    * any active listeners.
    */
   _shutdownDebugger: function DC__shutdownDebugger() {
     if (this._isDestroyed) {
@@ -929,17 +930,17 @@ SourceScripts.prototype = {
     for each (let script in this.activeThread.cachedScripts) {
       this._addScript(script, false);
     }
     DebuggerView.Scripts.commitScripts();
     DebuggerController.Breakpoints.updatePaneBreakpoints();
 
     // Select the preferred script if one exists, the first entry otherwise.
     let preferredScriptUrl = DebuggerView.Scripts.preferredScriptUrl;
-    if (preferredScriptUrl) {
+    if (preferredScriptUrl && DebuggerView.Scripts.contains(preferredScriptUrl)) {
       DebuggerView.Scripts.selectScript(preferredScriptUrl);
     } else {
       DebuggerView.Scripts.selectIndex(0);
     }
   },
 
   /**
    * Handler for the thread client's scriptscleared notification.
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -27,30 +27,36 @@ let DebuggerView = {
     stackframes.setAttribute("width", Prefs.stackframesWidth);
 
     let variables = document.getElementById("variables");
     variables.setAttribute("width", Prefs.variablesWidth);
   },
 
   /**
    * Initializes the SourceEditor instance.
+   *
+   * @param function aCallback
+   *        Called after the editor finishes initializing.
    */
-  initializeEditor: function DV_initializeEditor() {
+  initializeEditor: function DV_initializeEditor(aCallback) {
     let placeholder = document.getElementById("editor");
 
     let config = {
       mode: SourceEditor.MODES.JAVASCRIPT,
       showLineNumbers: true,
       readOnly: true,
       showAnnotationRuler: true,
       showOverviewRuler: true,
     };
 
     this.editor = new SourceEditor();
-    this.editor.init(placeholder, config, this._onEditorLoad.bind(this));
+    this.editor.init(placeholder, config, function() {
+      this._onEditorLoad();
+      aCallback();
+    }.bind(this));
   },
 
   /**
    * Removes the displayed panes and saves any necessary state.
    */
   destroyPanes: function DV_destroyPanes() {
     let stackframes = document.getElementById("stackframes+breakpoints");
     Prefs.stackframesWidth = stackframes.getAttribute("width");
@@ -469,17 +475,17 @@ ScriptsView.prototype = {
     scripts.setAttribute("label", this._preferredScript.label);
     scripts.setAttribute("tooltiptext", this._preferredScript.value);
 
     // If we're not searching for a file anymore, unhide all the scripts.
     if (!file) {
       for (let i = 0, l = scripts.itemCount; i < l; i++) {
         scripts.getItemAtIndex(i).hidden = false;
       }
-    } else {
+    } else if (this._prevSearchedFile !== file) {
       let found = false;
 
       for (let i = 0, l = scripts.itemCount; i < l; i++) {
         let item = scripts.getItemAtIndex(i);
         let target = item.label.toLowerCase();
 
         // Search is not case sensitive, and is tied to the label not the url.
         if (target.match(file)) {
@@ -497,25 +503,28 @@ ScriptsView.prototype = {
           item.hidden = true;
         }
       }
       if (!found) {
         scripts.setAttribute("label", L10N.getStr("noMatchingScriptsText"));
         scripts.removeAttribute("tooltiptext");
       }
     }
-    if (line > -1) {
+    if (this._prevSearchedLine !== line && line > -1) {
       editor.setCaretPosition(line - 1);
     }
-    if (token.length) {
+    if (this._prevSearchedToken !== token && token.length > 0) {
       let offset = editor.find(token, { ignoreCase: true });
       if (offset > -1) {
         editor.setSelection(offset, offset + token.length)
       }
     }
+    this._prevSearchedFile = file;
+    this._prevSearchedLine = line;
+    this._prevSearchedToken = token;
   },
 
   /**
    * The keyup listener for the scripts search box.
    */
   _onScriptsKeyUp: function DVS__onScriptsKeyUp(e) {
     if (e.keyCode === e.DOM_VK_ESCAPE) {
       DebuggerView.editor.focus();
--- a/browser/devtools/debugger/test/Makefile.in
+++ b/browser/devtools/debugger/test/Makefile.in
@@ -39,16 +39,17 @@ MOCHITEST_BROWSER_TESTS = \
 	browser_dbg_panesize.js \
 	browser_dbg_panesize-inner.js \
 	browser_dbg_stack-01.js \
 	browser_dbg_stack-02.js \
 	browser_dbg_stack-03.js \
 	browser_dbg_stack-04.js \
 	browser_dbg_stack-05.js \
 	browser_dbg_location-changes.js \
+	browser_dbg_location-changes-new.js \
 	browser_dbg_location-changes-blank.js \
 	browser_dbg_script-switching.js \
 	browser_dbg_scripts-sorting.js \
 	browser_dbg_scripts-searching-01.js \
 	browser_dbg_scripts-searching-02.js \
 	browser_dbg_pause-resume.js \
 	browser_dbg_update-editor-mode.js \
 	$(warning browser_dbg_select-line.js temporarily disabled due to oranges, see bug 726609) \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_location-changes-new.js
@@ -0,0 +1,91 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Make sure that changing the tab location URL to a page with other scripts works.
+ */
+
+var gPane = null;
+var gTab = null;
+var gDebuggee = null;
+var gDebugger = null;
+
+function test()
+{
+  debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gPane = aPane;
+    gDebugger = gPane.contentWindow;
+
+    testSimpleCall();
+  });
+}
+
+function testSimpleCall() {
+  gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
+    Services.tm.currentThread.dispatch({
+      run: function() {
+        var frames = gDebugger.DebuggerView.StackFrames._frames,
+            childNodes = frames.childNodes;
+
+        is(gDebugger.DebuggerController.activeThread.state, "paused",
+          "Should only be getting stack frames while paused.");
+
+        is(frames.querySelectorAll(".dbg-stackframe").length, 1,
+          "Should have only one frame.");
+
+        is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
+          "All children should be frames.");
+
+        isnot(gDebugger.DebuggerView.Scripts.selected, null,
+          "There should be a selected script.");
+        isnot(gDebugger.editor.getText().length, 0,
+          "The source editor should have some text displayed.");
+
+        testLocationChange();
+      }
+    }, 0);
+  });
+
+  gDebuggee.simpleCall();
+}
+
+function testLocationChange()
+{
+  gDebugger.DebuggerController.activeThread.resume(function() {
+    gDebugger.DebuggerController.client.addOneTimeListener("tabNavigated", function(aEvent, aPacket) {
+      ok(true, "tabNavigated event was fired.");
+      gDebugger.DebuggerController.client.addOneTimeListener("tabAttached", function(aEvent, aPacket) {
+        ok(true, "Successfully reattached to the tab again.");
+
+        // Wait for the initial resume...
+        gDebugger.gClient.addOneTimeListener("resumed", function() {
+          isnot(gDebugger.DebuggerView.Scripts.selected, null,
+            "There should be a selected script.");
+          isnot(gDebugger.editor.getText().length, 0,
+            "The source editor should have some text displayed.");
+
+          let menulist = gDebugger.DebuggerView.Scripts._scripts;
+          let noScripts = gDebugger.L10N.getStr("noScriptsText");
+          isnot(menulist.getAttribute("label"), noScripts,
+            "The menulist should not display a notice that there are no scripts availalble.");
+          isnot(menulist.getAttribute("tooltiptext"), "",
+            "The menulist should have a tooltip text attributed.");
+
+          closeDebuggerAndFinish();
+        });
+      });
+    });
+    content.location = EXAMPLE_URL + "browser_dbg_iframes.html";
+  });
+}
+
+registerCleanupFunction(function() {
+  removeTab(gTab);
+  gPane = null;
+  gTab = null;
+  gDebuggee = null;
+  gDebugger = null;
+});
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js
@@ -186,16 +186,21 @@ function testScriptSearching() {
 
 function clear() {
   gSearchBox.focus();
   gSearchBox.value = "";
 }
 
 function write(text) {
   clear();
+  append(text);
+}
+
+function append(text) {
+  gSearchBox.focus();
 
   for (let i = 0; i < text.length; i++) {
     EventUtils.sendChar(text[i]);
   }
   info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
 }
 
 registerCleanupFunction(function() {
--- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-02.js
@@ -91,72 +91,117 @@ function secondSearch() {
     info("Current script url:\n" + aEvent.detail.url + "\n");
     info("Debugger editor text:\n" + gEditor.getText() + "\n");
 
     let url = aEvent.detail.url;
     if (url.indexOf("-02.js") != -1) {
       window.removeEventListener(aEvent.type, _onEvent);
 
       executeSoon(function() {
+        append("#" + token);
+
         info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
         ok(gEditor.getCaretPosition().line == 5 &&
            gEditor.getCaretPosition().col == 8 + token.length,
           "The editor didn't jump to the correct line. (2)");
         is(gScripts.visibleItemsCount, 1,
           "Not all the correct scripts are shown after the search. (2)");
 
+        waitForFirstScript();
+      });
+    }
+  });
+  gScripts.selectIndex(1);
+}
+
+function waitForFirstScript() {
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    info("Current script url:\n" + aEvent.detail.url + "\n");
+    info("Debugger editor text:\n" + gEditor.getText() + "\n");
+
+    let url = aEvent.detail.url;
+    if (url.indexOf("-01.js") != -1) {
+      window.removeEventListener(aEvent.type, _onEvent);
+
+      executeSoon(function() {
+        thirdSearch();
+      });
+    }
+  });
+  gScripts.selectIndex(0);
+}
+
+function thirdSearch() {
+  let token = "deb";
+
+  window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) {
+    info("Current script url:\n" + aEvent.detail.url + "\n");
+    info("Debugger editor text:\n" + gEditor.getText() + "\n");
+
+    let url = aEvent.detail.url;
+    if (url.indexOf("-02.js") != -1) {
+      window.removeEventListener(aEvent.type, _onEvent);
+
+      executeSoon(function() {
+        info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
+        ok(gEditor.getCaretPosition().line == 5 &&
+           gEditor.getCaretPosition().col == 8 + token.length,
+          "The editor didn't jump to the correct line. (3)");
+        is(gScripts.visibleItemsCount, 1,
+          "Not all the correct scripts are shown after the search. (3)");
+
         finalCheck(0, "ugger;", token);
       });
     }
   });
   write(".*-02\.js#" + token);
 }
 
 function finalCheck(i, string, token) {
   info("Searchbox value: " + gSearchBox.value);
 
   ok(gEditor.getCaretPosition().line == 5 &&
      gEditor.getCaretPosition().col == 8 + token.length + i,
-    "The editor didn't remain at the correct token. (3)");
+    "The editor didn't remain at the correct token. (4)");
 
   if (string[i]) {
     EventUtils.sendChar(string[i]);
     finalCheck(i + 1, string, token);
     return;
   }
 
   clear();
   ok(gEditor.getCaretPosition().line == 5 &&
      gEditor.getCaretPosition().col == 8 + token.length + i,
-    "The editor didn't remain at the correct token. (4)");
+    "The editor didn't remain at the correct token. (5)");
 
   executeSoon(function() {
     let noMatchingScripts = gDebugger.L10N.getStr("noMatchingScriptsText");
 
     is(gScripts.visibleItemsCount, 2,
       "Not all the scripts are shown after the searchbox was emptied.");
     is(gMenulist.selectedIndex, 1,
       "The menulist should have retained its selected index after the searchbox was emptied.");
 
     write("BOGUS");
     ok(gEditor.getCaretPosition().line == 5 &&
        gEditor.getCaretPosition().col == 8 + token.length + i,
-      "The editor didn't remain at the correct token. (5)");
+      "The editor didn't remain at the correct token. (6)");
 
     is(gMenulist.getAttribute("label"), noMatchingScripts,
       "The menulist should display a notice that no scripts match the searched token.");
     is(gScripts.visibleItemsCount, 0,
       "No scripts should be displayed in the menulist after a bogus search.");
     is(gMenulist.selectedIndex, 1,
       "The menulist should retain its selected index after a bogus search.");
 
     clear();
     ok(gEditor.getCaretPosition().line == 5 &&
        gEditor.getCaretPosition().col == 8 + token.length + i,
-      "The editor didn't remain at the correct token. (6)");
+      "The editor didn't remain at the correct token. (7)");
 
     isnot(gMenulist.getAttribute("label"), noMatchingScripts,
       "The menulist should not display a notice after the searchbox was emptied.");
     is(gScripts.visibleItemsCount, 2,
       "Not all the scripts are shown after the searchbox was emptied.");
     is(gMenulist.selectedIndex, 1,
       "The menulist should have retained its selected index after the searchbox was emptied of a bogus search.");
 
@@ -166,16 +211,21 @@ function finalCheck(i, string, token) {
 
 function clear() {
   gSearchBox.focus();
   gSearchBox.value = "";
 }
 
 function write(text) {
   clear();
+  append(text);
+}
+
+function append(text) {
+  gSearchBox.focus();
 
   for (let i = 0; i < text.length; i++) {
     EventUtils.sendChar(text[i]);
   }
   info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
 }
 
 registerCleanupFunction(function() {
--- a/browser/devtools/shared/DeveloperToolbar.jsm
+++ b/browser/devtools/shared/DeveloperToolbar.jsm
@@ -545,45 +545,51 @@ function DT_resetErrorsCount(aTab)
 function OutputPanel(aChromeDoc, aInput, aLoadCallback)
 {
   this._input = aInput;
   this._toolbar = aChromeDoc.getElementById("developer-toolbar");
 
   this._loadCallback = aLoadCallback;
 
   /*
-  <panel id="gcli-output"
+  <tooltip id="gcli-output"
          noautofocus="true"
          noautohide="true"
          class="gcli-panel">
     <html:iframe xmlns:html="http://www.w3.org/1999/xhtml"
                  id="gcli-output-frame"
                  src="chrome://browser/content/devtools/gclioutput.xhtml"
                  flex="1"/>
-  </panel>
+  </tooltip>
   */
-  this._panel = aChromeDoc.createElement("panel");
+
+  // TODO: Switch back from tooltip to panel when metacity focus issue is fixed:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
+  this._panel = aChromeDoc.createElement("tooltip");
+
   this._panel.id = "gcli-output";
   this._panel.classList.add("gcli-panel");
-  this._panel.setAttribute("noautofocus", "true");
-  this._panel.setAttribute("noautohide", "true");
   this._toolbar.parentElement.insertBefore(this._panel, this._toolbar);
 
   this._frame = aChromeDoc.createElementNS(NS_XHTML, "iframe");
   this._frame.id = "gcli-output-frame";
   this._frame.setAttribute("src", "chrome://browser/content/devtools/gclioutput.xhtml");
   this._frame.setAttribute("flex", "1");
   this._panel.appendChild(this._frame);
 
   this.displayedOutput = undefined;
 
   this._onload = this._onload.bind(this);
   this._frame.addEventListener("load", this._onload, true);
 
   this.loaded = false;
+  this.canHide = false;
+
+  this._onpopuphiding = this._onpopuphiding.bind(this);
+  this._panel.addEventListener("popuphiding", this._onpopuphiding, true);
 }
 
 /**
  * Wire up the element from the iframe, and inform the _loadCallback.
  */
 OutputPanel.prototype._onload = function OP_onload()
 {
   this._frame.removeEventListener("load", this._onload, true);
@@ -602,27 +608,41 @@ OutputPanel.prototype._onload = function
   this.loaded = true;
   if (this._loadCallback) {
     this._loadCallback();
     delete this._loadCallback;
   }
 };
 
 /**
+ * Prevent the popup from hiding if it is not permitted via this.canHide.
+ */
+OutputPanel.prototype._onpopuphiding = function OP_onpopuphiding(aEvent)
+{
+  // TODO: When we switch back from tooltip to panel we can remove this hack:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
+  if (!this.canHide) {
+    aEvent.preventDefault();
+  }
+};
+
+/**
  * Display the OutputPanel.
  */
 OutputPanel.prototype.show = function OP_show()
 {
   // This is nasty, but displaying the panel causes it to re-flow, which can
   // change the size it should be, so we need to resize the iframe after the
   // panel has displayed
   this._panel.ownerDocument.defaultView.setTimeout(function() {
     this._resize();
   }.bind(this), 0);
 
+  this.canHide = false;
+
   this._panel.openPopup(this._input, "before_start", 0, 0, false, false, null);
   this._resize();
 
   this._input.focus();
 };
 
 /**
  * Internal helper to set the height of the output panel to fit the available
@@ -672,53 +692,59 @@ OutputPanel.prototype.update = function 
   }
 };
 
 /**
  * Detach listeners from the currently displayed Output.
  */
 OutputPanel.prototype.remove = function OP_remove()
 {
+  this.canHide = true;
   this._panel.hidePopup();
 
   if (this.displayedOutput) {
     this.displayedOutput.onChange.remove(this.update, this);
     this.displayedOutput.onClose.remove(this.remove, this);
     delete this.displayedOutput;
   }
 };
 
 /**
  * Detach listeners from the currently displayed Output.
  */
 OutputPanel.prototype.destroy = function OP_destroy()
 {
   this.remove();
 
+  this._panel.removeEventListener("popuphiding", this._onpopuphiding, true);
+
   this._panel.removeChild(this._frame);
   this._toolbar.parentElement.removeChild(this._panel);
 
   delete this._input;
   delete this._toolbar;
+  delete this._onload;
+  delete this._onpopuphiding;
   delete this._panel;
   delete this._frame;
   delete this._content;
   delete this._div;
   delete this.document;
 };
 
 /**
  * Called by GCLI to indicate that we should show or hide one either the
  * tooltip panel or the output panel.
  */
 OutputPanel.prototype._visibilityChanged = function OP_visibilityChanged(aEvent)
 {
   if (aEvent.outputVisible === true) {
     // this.show is called by _outputChanged
   } else {
+    this.canHide = true;
     this._panel.hidePopup();
   }
 };
 
 
 /**
  * Panel to handle tooltips.
  * @param aChromeDoc document from which we can pull the parts we need.
@@ -729,42 +755,49 @@ function TooltipPanel(aChromeDoc, aInput
 {
   this._input = aInput;
   this._toolbar = aChromeDoc.getElementById("developer-toolbar");
   this._dimensions = { start: 0, end: 0 };
 
   this._onload = this._onload.bind(this);
   this._loadCallback = aLoadCallback;
   /*
-  <panel id="gcli-tooltip"
+  <tooltip id="gcli-tooltip"
          type="arrow"
          noautofocus="true"
          noautohide="true"
          class="gcli-panel">
     <html:iframe xmlns:html="http://www.w3.org/1999/xhtml"
                  id="gcli-tooltip-frame"
                  src="chrome://browser/content/devtools/gclitooltip.xhtml"
                  flex="1"/>
-  </panel>
+  </tooltip>
   */
-  this._panel = aChromeDoc.createElement("panel");
+
+  // TODO: Switch back from tooltip to panel when metacity focus issue is fixed:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
+  this._panel = aChromeDoc.createElement("tooltip");
+
   this._panel.id = "gcli-tooltip";
   this._panel.classList.add("gcli-panel");
-  this._panel.setAttribute("noautofocus", "true");
-  this._panel.setAttribute("noautohide", "true");
   this._toolbar.parentElement.insertBefore(this._panel, this._toolbar);
 
   this._frame = aChromeDoc.createElementNS(NS_XHTML, "iframe");
   this._frame.id = "gcli-tooltip-frame";
   this._frame.setAttribute("src", "chrome://browser/content/devtools/gclitooltip.xhtml");
   this._frame.setAttribute("flex", "1");
   this._panel.appendChild(this._frame);
 
   this._frame.addEventListener("load", this._onload, true);
+
   this.loaded = false;
+  this.canHide = false;
+
+  this._onpopuphiding = this._onpopuphiding.bind(this);
+  this._panel.addEventListener("popuphiding", this._onpopuphiding, true);
 }
 
 /**
  * Wire up the element from the iframe, and inform the _loadCallback.
  */
 TooltipPanel.prototype._onload = function TP_onload()
 {
   this._frame.removeEventListener("load", this._onload, true);
@@ -781,32 +814,46 @@ TooltipPanel.prototype._onload = functio
 
   if (this._loadCallback) {
     this._loadCallback();
     delete this._loadCallback;
   }
 };
 
 /**
+ * Prevent the popup from hiding if it is not permitted via this.canHide.
+ */
+TooltipPanel.prototype._onpopuphiding = function TP_onpopuphiding(aEvent)
+{
+  // TODO: When we switch back from tooltip to panel we can remove this hack:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=780102
+  if (!this.canHide) {
+    aEvent.preventDefault();
+  }
+};
+
+/**
  * Display the TooltipPanel.
  */
 TooltipPanel.prototype.show = function TP_show(aDimensions)
 {
   if (!aDimensions) {
     aDimensions = { start: 0, end: 0 };
   }
   this._dimensions = aDimensions;
 
   // This is nasty, but displaying the panel causes it to re-flow, which can
   // change the size it should be, so we need to resize the iframe after the
   // panel has displayed
   this._panel.ownerDocument.defaultView.setTimeout(function() {
     this._resize();
   }.bind(this), 0);
 
+  this.canHide = false;
+
   this._resize();
   this._panel.openPopup(this._input, "before_start", aDimensions.start * 10, 0, false, false, null);
   this._input.focus();
 };
 
 /**
  * One option is to spend lots of time taking an average width of characters
  * in the current font, dynamically, and weighting for the frequency of use of
@@ -840,33 +887,37 @@ TooltipPanel.prototype._resize = functio
   this._frame.height = this.document.body.scrollHeight;
 };
 
 /**
  * Hide the TooltipPanel.
  */
 TooltipPanel.prototype.remove = function TP_remove()
 {
+  this.canHide = true;
   this._panel.hidePopup();
 };
 
 /**
  * Hide the TooltipPanel.
  */
 TooltipPanel.prototype.destroy = function TP_destroy()
 {
   this.remove();
 
+  this._panel.removeEventListener("popuphiding", this._onpopuphiding, true);
+
   this._panel.removeChild(this._frame);
   this._toolbar.parentElement.removeChild(this._panel);
 
   delete this._connector;
   delete this._dimensions;
   delete this._input;
   delete this._onload;
+  delete this._onpopuphiding;
   delete this._panel;
   delete this._frame;
   delete this._toolbar;
   delete this._content;
   delete this.document;
   delete this.hintElement;
 };
 
@@ -874,11 +925,12 @@ TooltipPanel.prototype.destroy = functio
  * Called by GCLI to indicate that we should show or hide one either the
  * tooltip panel or the output panel.
  */
 TooltipPanel.prototype._visibilityChanged = function TP_visibilityChanged(aEvent)
 {
   if (aEvent.tooltipVisible === true) {
     this.show(aEvent.dimensions);
   } else {
+    this.canHide = true;
     this._panel.hidePopup();
   }
 };
--- a/browser/modules/webappsUI.jsm
+++ b/browser/modules/webappsUI.jsm
@@ -13,35 +13,40 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Webapps.jsm");
 Cu.import("resource://gre/modules/WebappsInstaller.jsm");
 Cu.import("resource://gre/modules/WebappOSUtils.jsm");
 
 let webappsUI = {
   init: function webappsUI_init() {
     Services.obs.addObserver(this, "webapps-ask-install", false);
     Services.obs.addObserver(this, "webapps-launch", false);
+    Services.obs.addObserver(this, "webapps-uninstall", false);
   },
   
   uninit: function webappsUI_uninit() {
     Services.obs.removeObserver(this, "webapps-ask-install");
     Services.obs.removeObserver(this, "webapps-launch");
+    Services.obs.removeObserver(this, "webapps-uninstall");
   },
 
   observe: function webappsUI_observe(aSubject, aTopic, aData) {
     let data = JSON.parse(aData);
 
     switch(aTopic) {
       case "webapps-ask-install":
         let [chromeWin, browser] = this._getBrowserForId(data.oid);
         if (chromeWin)
           this.doInstall(data, browser, chromeWin);
         break;
       case "webapps-launch":
         WebappOSUtils.launch(data);
         break;
+      case "webapps-uninstall":
+        WebappOSUtils.uninstall(data);
+        break;
     }
   },
 
   openURL: function(aUrl, aOrigin) {
     let browserEnumerator = Services.wm.getEnumerator("navigator:browser");  
     let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 
     // Check each browser instance for our URL
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -3306,16 +3306,17 @@ stack[anonid=browserStack][responsivemod
 /* Error counter */
 
 #developer-toolbar-webconsole[error-count]:before {
   color: #FDF3DE;
   min-width: 16px;
   text-shadow: none;
   background-image: -moz-linear-gradient(top, #B4211B, #8A1915);
   border-radius: 1px;
+  -moz-margin-end: 5px;
 }
 
 
 /* social toolbar button */
 .social-statusarea-container {
   -moz-appearance: none;
   margin: 2px; /* make sure we have the correct platform spacing*/
   padding: 1px;
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -13,18 +13,18 @@ import sys
 import tempfile
 import time
 
 from automation import Automation
 from devicemanager import DeviceManager, NetworkTools
 from mozprocess import ProcessHandlerMixin
 
 
-class LogcatProc(ProcessHandlerMixin):
-    """Process handler for logcat which puts all output in a Queue.
+class StdOutProc(ProcessHandlerMixin):
+    """Process handler for b2g which puts all output in a Queue.
     """
 
     def __init__(self, cmd, queue, **kwargs):
         self.queue = queue
         kwargs.setdefault('processOutputLine', []).append(self.handle_output)
         ProcessHandlerMixin.__init__(self, cmd, **kwargs)
 
     def handle_output(self, line):
@@ -71,16 +71,30 @@ class B2GRemoteAutomation(Automation):
         # so no copying of os.environ
         if env is None:
             env = {}
 
         # We always hide the results table in B2G; it's much slower if we don't.
         env['MOZ_HIDE_RESULTS_TABLE'] = '1'
         return env
 
+    def waitForNet(self): 
+        active = False
+        time_out = 0
+        while not active and time_out < 40:
+            data = self._devicemanager.runCmd(['shell', '/system/bin/netcfg']).stdout.readlines()
+            data.pop(0)
+            for line in data:
+                if (re.search(r'UP\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3}', line)):
+                    active = True
+                    break
+            time_out += 1
+            time.sleep(1)
+        return active
+
     def checkForCrashes(self, directory, symbolsPath):
         # XXX: This will have to be updated after crash reporting on b2g
         # is in place.
         dumpDir = tempfile.mkdtemp()
         self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
         automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
         try:
           shutil.rmtree(dumpDir)
@@ -155,17 +169,21 @@ class B2GRemoteAutomation(Automation):
         if self._is_emulator:
             self.marionette.emulator.wait_for_port()
 
     def rebootDevice(self):
         # find device's current status and serial number
         serial, status = self.getDeviceStatus()
 
         # reboot!
-        self._devicemanager.checkCmd(['reboot'])
+        self._devicemanager.runCmd(['shell', '/system/bin/reboot'])
+
+        # The above command can return while adb still thinks the device is
+        # connected, so wait a little bit for it to disconnect from adb.
+        time.sleep(10)
 
         # wait for device to come back to previous status
         print 'waiting for device to come back online after reboot'
         start = time.time()
         rserial, rstatus = self.getDeviceStatus(serial)
         while rstatus != 'device':
             if time.time() - start > 120:
                 # device hasn't come back online in 2 minutes, something's wrong
@@ -178,39 +196,46 @@ class B2GRemoteAutomation(Automation):
         # On a desktop or fennec run, the Process method invokes a gecko
         # process in which to run mochitests.  For B2G, we simply
         # reboot the device (which was configured with a test profile
         # already), wait for B2G to start up, and then navigate to the
         # test url using Marionette.  There doesn't seem to be any way
         # to pass env variables into the B2G process, but this doesn't 
         # seem to matter.
 
-        instance = self.B2GInstance(self._devicemanager)
-
         # reboot device so it starts up with the mochitest profile
         # XXX:  We could potentially use 'stop b2g' + 'start b2g' to achieve
         # a similar effect; will see which is more stable while attempting
         # to bring up the continuous integration.
-        if self._is_emulator:
-            self.restartB2G()
-        else:
+        if not self._is_emulator:
             self.rebootDevice()
+            time.sleep(5)
+            #wait for wlan to come up 
+            if not self.waitForNet():
+                raise Exception("network did not come up, please configure the network" + 
+                                " prior to running before running the automation framework")
 
-        # Infrequently, gecko comes up before networking does, so wait a little
-        # bit to give the network time to become available.
-        # XXX:  need a more robust mechanism for this
-        time.sleep(40)
+        # stop b2g
+        self._devicemanager.runCmd(['shell', 'stop', 'b2g'])
+        time.sleep(5)
+
+        # relaunch b2g inside b2g instance
+        instance = self.B2GInstance(self._devicemanager)
+
+        time.sleep(5)
 
         # Set up port forwarding again for Marionette, since any that
         # existed previously got wiped out by the reboot.
         if not self._is_emulator:
             self._devicemanager.checkCmd(['forward',
                                           'tcp:%s' % self.marionette.port,
                                           'tcp:%s' % self.marionette.port])
 
+        time.sleep(5)
+
         # start a marionette session
         session = self.marionette.start_session()
         if 'b2g' not in session:
             raise Exception("bad session value %s returned by start_session" % session)
 
         # 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.
@@ -223,46 +248,49 @@ class B2GRemoteAutomation(Automation):
     class B2GInstance(object):
         """Represents a B2G instance running on a device, and exposes
            some process-like methods/properties that are expected by the
            automation.
         """
 
         def __init__(self, dm):
             self.dm = dm
-            self.logcat_proc = None
+            self.stdout_proc = None
             self.queue = Queue.Queue()
 
-            # Launch logcat in a separate thread, and dump all output lines
+            # Launch b2g in a separate thread, and dump all output lines
             # into a queue.  The lines in this queue are
             # retrieved and returned by accessing the stdout property of
             # this class.
             cmd = [self.dm.adbPath]
             if self.dm.deviceSerial:
                 cmd.extend(['-s', self.dm.deviceSerial])
-            cmd.append('logcat')
-            proc = threading.Thread(target=self._save_logcat_proc, args=(cmd, self.queue))
+            cmd.append('shell')
+            cmd.append('/system/bin/b2g.sh')
+            proc = threading.Thread(target=self._save_stdout_proc, args=(cmd, self.queue))
             proc.daemon = True
             proc.start()
 
-        def _save_logcat_proc(self, cmd, queue):
-            self.logcat_proc = LogcatProc(cmd, queue)
-            self.logcat_proc.run()
-            self.logcat_proc.waitForFinish()
-            self.logcat_proc = None
+        def _save_stdout_proc(self, cmd, queue):
+            self.stdout_proc = StdOutProc(cmd, queue)
+            self.stdout_proc.run()
+            if hasattr(self.stdout_proc, 'processOutput'):
+                self.stdout_proc.processOutput()
+            self.stdout_proc.waitForFinish(timeout=10)
+            self.stdout_proc = None
 
         @property
         def pid(self):
             # a dummy value to make the automation happy
             return 0
 
         @property
         def stdout(self):
             # Return any lines in the queue used by the
-            # logcat process handler.
+            # b2g process handler.
             lines = []
             while True:
                 try:
                     lines.append(self.queue.get_nowait())
                 except Queue.Empty:
                     break
             return '\n'.join(lines)
 
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -16,17 +16,17 @@ struct JSPrincipals;
 
 interface nsIURI;
 interface nsIContentSecurityPolicy;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 [ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
 
-[scriptable, uuid(8a74b011-667d-4cfa-b2a2-b27582ba5f38)]
+[scriptable, uuid(6df7d16d-5b26-42a1-b1f7-069d46c37aa8)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Values of capabilities for each principal. Order is
      * significant: if an operation is performed on a set
      * of capabilities, the minimum is computed.
      */
     const short ENABLE_DENIED                = 1;
@@ -225,23 +225,23 @@ interface nsIPrincipal : nsISerializable
      * The extendedOrigin is intended to be an opaque identifier. It is
      * currently "human-readable" but no callers should assume it will stay
      * as is and it might be crypto-hashed at some point.
      */
     readonly attribute AUTF8String extendedOrigin;
 
     const short APP_STATUS_NOT_INSTALLED = 0;
     const short APP_STATUS_INSTALLED     = 1;
-    const short APP_STATUS_TRUSTED       = 2;
+    const short APP_STATUS_PRIVILEGED    = 2;
     const short APP_STATUS_CERTIFIED     = 3;
 
     /**
      * Shows the status of the app.
      * Can be: APP_STATUS_NOT_INSTALLED, APP_STATUS_INSTALLED,
-     *         APP_STATUS_TRUSTED or APP_STATUS_CERTIFIED.
+     *         APP_STATUS_PRIVILEGED or APP_STATUS_CERTIFIED.
      */
     readonly attribute unsigned short appStatus;
 
     /**
      * Returns the app id the principal is in, or returns
      * nsIScriptSecurityManager::NO_APP_ID if this principal isn't part of an
      * app.
      */
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -1038,17 +1038,17 @@ nsPrincipal::InitFromPersistent(const ch
     mTrusted = aTrusted;
   }
 
   //-- Save the preference name
   mPrefName = aPrefName;
 
   const char* ordinalBegin = PL_strpbrk(aPrefName, "1234567890");
   if (ordinalBegin) {
-    PRIntn n = atoi(ordinalBegin);
+    int n = atoi(ordinalBegin);
     if (sCapabilitiesOrdinal <= n) {
       sCapabilitiesOrdinal = n + 1;
     }
   }
 
   //-- Store the capabilities
   rv = NS_OK;
   if (aGrantedList) {
@@ -1117,17 +1117,17 @@ nsPrincipal::Read(nsIObjectInputStream* 
 
   rv = NS_ReadOptionalCString(aStream, mPrefName);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   const char* ordinalBegin = PL_strpbrk(mPrefName.get(), "1234567890");
   if (ordinalBegin) {
-    PRIntn n = atoi(ordinalBegin);
+    int n = atoi(ordinalBegin);
     if (sCapabilitiesOrdinal <= n) {
       sCapabilitiesOrdinal = n + 1;
     }
   }
 
   bool haveCert;
   rv = aStream->ReadBoolean(&haveCert);
   if (NS_FAILED(rv)) {
deleted file mode 100644
--- a/content/base/public/DirectionalityUtils.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef DirectionalityUtils_h___
-#define DirectionalityUtils_h___
-
-class nsIContent;
-class nsIDocument;
-class nsINode;
-
-namespace mozilla {
-namespace dom {
-class Element;
-} // namespace dom
-} // namespace mozilla
-
-namespace mozilla {
-
-namespace directionality {
-
-enum Directionality {
-  eDir_NotSet = 0,
-  eDir_RTL    = 1,
-  eDir_LTR    = 2
-};
-
-void SetDirectionality(mozilla::dom::Element* aElement, Directionality aDir,
-                       bool aNotify = true);
-
-/**
- * Set the directionality of an element according to the algorithm defined at
- * http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality,
- * not including elements with auto direction.
- *
- * @return the directionality that the element was set to
- */
-Directionality RecomputeDirectionality(mozilla::dom::Element* aElement,
-                                       bool aNotify = true);
-
-/**
- * Set the directionality of any descendants of a node that do not themselves
- * have a dir attribute.
- * For performance reasons we walk down the descendant tree in the rare case
- * of setting the dir attribute, rather than walking up the ancestor tree in
- * the much more common case of getting the element's directionality.
- */
-void SetDirectionalityOnDescendants(mozilla::dom::Element* aElement, 
-                                    Directionality aDir,
-                                    bool aNotify = true);
-
-} // end namespace directionality
-
-} // end namespace mozilla
-
-#endif /* DirectionalityUtils_h___ */
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Element_h__
 #define mozilla_dom_Element_h__
 
 #include "mozilla/dom/FragmentOrElement.h" // for base class
 #include "nsChangeHint.h"                  // for enum
 #include "nsEventStates.h"                 // for member
-#include "mozilla/dom/DirectionalityUtils.h"
 
 class nsEventStateManager;
 class nsFocusManager;
 class nsGlobalWindow;
 class nsICSSDeclaration;
 class nsISMILAttr;
 
 // Element-specific flags
@@ -212,28 +211,16 @@ public:
 
   /**
    * Returns an atom holding the name of the "class" attribute on this
    * content node (if applicable).  Returns null if there is no
    * "class" attribute for this type of content node.
    */
   virtual nsIAtom *GetClassAttributeName() const = 0;
 
-  inline mozilla::directionality::Directionality GetDirectionality() const {
-    if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
-      return mozilla::directionality::eDir_RTL;
-    }
-
-    if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
-      return mozilla::directionality::eDir_LTR;
-    }
-
-    return mozilla::directionality::eDir_NotSet;
-  }
-
 protected:
   /**
    * Method to get the _intrinsic_ content state of this element.  This is the
    * state that is independent of the element's presentation.  To get the full
    * content state, use State().  See nsEventStates.h for
    * the possible bits that could be set here.
    */
   virtual nsEventStates IntrinsicState() const;
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -43,17 +43,16 @@ nsReferencedElement.h \
 nsTreeSanitizer.h \
 nsXMLNameSpaceMap.h \
 nsIXFormsUtilityService.h \
 $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom mozilla
 
 EXPORTS_mozilla/dom = \
-		DirectionalityUtils.h \
 		Element.h \
 		FragmentOrElement.h \
 		FromParser.h \
 		$(NULL)
 
 EXPORTS_mozilla = \
 		CORSMode.h \
 		$(NULL)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -18,17 +18,16 @@
 #include "nsILoadContext.h"              // for member (in nsCOMPtr)
 #include "nsILoadGroup.h"                // for member (in nsCOMPtr)
 #include "nsINode.h"                     // for base class
 #include "nsIScriptGlobalObject.h"       // for member (in nsCOMPtr)
 #include "nsIStructuredCloneContainer.h" // for member (in nsCOMPtr)
 #include "nsPIDOMWindow.h"               // for use in inline functions
 #include "nsPropertyTable.h"             // for member
 #include "nsTHashtable.h"                // for member
-#include "mozilla/dom/DirectionalityUtils.h"
 
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
 class nsCSSStyleSheet;
 class nsDOMNavigationTiming;
 class nsEventStates;
 class nsFrameLoader;
@@ -393,20 +392,16 @@ public:
    * callers are expected to take action as needed if they want this
    * change to actually change anything immediately.
    * @see nsBidiUtils.h
    */
   void SetBidiOptions(PRUint32 aBidiOptions)
   {
     mBidiOptions = aBidiOptions;
   }
-
-  inline mozilla::directionality::Directionality GetDocumentDirectionality() {
-    return mDirectionality;
-  }
   
   /**
    * Access HTTP header data (this may also get set from other
    * sources, like HTML META tags).
    */
   virtual void GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const = 0;
   virtual void SetHeaderData(nsIAtom* aheaderField, const nsAString& aData) = 0;
 
@@ -1853,19 +1848,16 @@ protected:
   // If mIsStaticDocument is true, mOriginalDocument points to the original
   // document.
   nsCOMPtr<nsIDocument> mOriginalDocument;
 
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
-  // The root directionality of this document.
-  mozilla::directionality::Directionality mDirectionality;
-
   nsCString mContentLanguage;
 private:
   nsCString mContentType;
 protected:
 
   // The document's security info
   nsCOMPtr<nsISupports> mSecurityInfo;
 
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -140,26 +140,18 @@ enum {
   NODE_HAS_ACCESSKEY           = 0x00020000U,
 
   // Set if the node is handling a click.
   NODE_HANDLING_CLICK          = 0x00040000U,
 
   // Set if the node has had :hover selectors matched against it
   NODE_HAS_RELEVANT_HOVER_RULES = 0x00080000U,
 
-  // Set if the node has right-to-left directionality
-  NODE_HAS_DIRECTION_RTL        = 0x00100000U,
-
-  // Set if the node has left-to-right directionality
-  NODE_HAS_DIRECTION_LTR        = 0x00200000U,
-
-  NODE_ALL_DIRECTION_FLAGS      = NODE_HAS_DIRECTION_LTR | NODE_HAS_DIRECTION_RTL,
-
   // Remaining bits are node type specific.
-  NODE_TYPE_SPECIFIC_BITS_OFFSET =        22
+  NODE_TYPE_SPECIFIC_BITS_OFFSET =        20
 };
 
 /**
  * Class used to detect unexpected mutations. To use the class create an
  * nsMutationGuard on the stack before unexpected mutations could occur.
  * You can then at any time call Mutated to check if any unexpected mutations
  * have occurred.
  *
@@ -1282,18 +1274,16 @@ private:
     // Set if element has pointer locked
     ElementHasPointerLock,
     // Set if the node may have DOMMutationObserver attached to it.
     NodeMayHaveDOMMutationObserver,
     // Set if node is Content
     NodeIsContent,
     // Set if the node has animations or transitions
     ElementHasAnimations,
-    // Set if node has a dir attribute with a valid value (ltr or rtl)
-    NodeHasValidDirAttribute,
     // Guard value
     BooleanFlagCount
   };
 
   void SetBoolFlag(BooleanFlag name, bool value) {
     PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags));
     mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name);
   }
@@ -1351,19 +1341,16 @@ public:
   void SetMayHaveDOMMutationObserver()
     { SetBoolFlag(NodeMayHaveDOMMutationObserver, true); }
   bool HasListenerManager() { return HasFlag(NODE_HAS_LISTENERMANAGER); }
   bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
   void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
   void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
   bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
   void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
-  void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
-  void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
-  bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
 protected:
   void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
   void SetInDocument() { SetBoolFlag(IsInDocument); }
   void SetNodeIsContent() { SetBoolFlag(NodeIsContent); }
   void ClearInDocument() { ClearBoolFlag(IsInDocument); }
   void SetIsElement() { SetBoolFlag(NodeIsElement); }
   void SetHasID() { SetBoolFlag(ElementHasID); }
   void ClearHasID() { ClearBoolFlag(ElementHasID); }
deleted file mode 100644
--- a/content/base/src/DirectionalityUtils.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 sw=2 et tw=78: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/DirectionalityUtils.h"
-#include "nsINode.h"
-#include "nsIContent.h"
-#include "nsIDocument.h"
-#include "mozilla/dom/Element.h"
-#include "nsIDOMNodeFilter.h"
-#include "nsTreeWalker.h"
-#include "nsIDOMHTMLDocument.h"
-
-
-namespace mozilla {
-
-namespace directionality {
-
-typedef mozilla::dom::Element Element;
-
-void
-SetDirectionality(Element* aElement, Directionality aDir, bool aNotify)
-{
-  aElement->UnsetFlags(NODE_ALL_DIRECTION_FLAGS);
-  switch (aDir) {
-    case eDir_RTL:
-      aElement->SetFlags(NODE_HAS_DIRECTION_RTL);
-      break;
-    case eDir_LTR:
-      aElement->SetFlags(NODE_HAS_DIRECTION_LTR);
-      break;
-    default:
-      break;
-  }
-
-  aElement->UpdateState(aNotify);
-}
-
-Directionality
-RecomputeDirectionality(Element* aElement, bool aNotify)
-{
-  Directionality dir = eDir_LTR;
-
-  if (aElement->HasValidDir()) {
-    dir = aElement->GetDirectionality();
-  } else {
-    Element* parent = aElement->GetElementParent();
-    if (parent) {
-      // If the element doesn't have an explicit dir attribute with a valid
-      // value, the directionality is the same as the parent element (but
-      // don't propagate the parent directionality if it isn't set yet).
-      Directionality parentDir = parent->GetDirectionality();
-      if (parentDir != eDir_NotSet) {
-        dir = parentDir;
-      }
-    } else {
-      // If there is no parent element, the directionality is the same as the
-      // document direction.
-      Directionality documentDir =
-        aElement->OwnerDoc()->GetDocumentDirectionality();
-      if (documentDir != eDir_NotSet) {
-        dir = documentDir;
-      }
-    }
-    
-    SetDirectionality(aElement, dir, aNotify);
-  }
-  return dir;
-}
-
-void
-SetDirectionalityOnDescendants(Element* aElement, Directionality aDir,
-                               bool aNotify)
-{
-  for (nsIContent* child = aElement->GetFirstChild(); child; ) {
-    if (!child->IsElement()) {
-      child = child->GetNextNode(aElement);
-      continue;
-    }
-
-    Element* element = child->AsElement();
-    if (element->HasValidDir()) {
-      child = child->GetNextNonChildNode(aElement);
-      continue;
-    }
-    SetDirectionality(element, aDir, aNotify);
-    child = child->GetNextNode(aElement);
-  }
-}
-
-} // end namespace directionality
-
-} // end namespace mozilla
-
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -48,17 +48,16 @@ EXPORTS_NAMESPACES = mozilla/dom
 EXPORTS_mozilla/dom = \
   Link.h \
   $(NULL)
 
 LOCAL_INCLUDES = \
 		$(NULL)
 
 CPPSRCS		= \
-		DirectionalityUtils.cpp \
 		nsAtomListUtils.cpp \
 		nsAttrAndChildArray.cpp \
 		nsAttrValue.cpp \
 		nsAttrValueOrString.cpp \
 		nsCCUncollectableMarker.cpp \
 		nsChannelPolicy.cpp \
 		nsCommentNode.cpp \
 		nsContentAreaDragDrop.cpp \
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -48,17 +48,17 @@ class Loader;
 #ifdef DEBUG
 
 extern PRLogModuleInfo* gContentSinkLogModuleInfo;
 
 #define SINK_TRACE_CALLS              0x1
 #define SINK_TRACE_REFLOW             0x2
 #define SINK_ALWAYS_REFLOW            0x4
 
-#define SINK_LOG_TEST(_lm, _bit) (PRIntn((_lm)->level) & (_bit))
+#define SINK_LOG_TEST(_lm, _bit) (int((_lm)->level) & (_bit))
 
 #define SINK_TRACE(_lm, _bit, _args) \
   PR_BEGIN_MACRO                     \
     if (SINK_LOG_TEST(_lm, _bit)) {  \
       PR_LogPrint _args;             \
     }                                \
   PR_END_MACRO
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -86,17 +86,16 @@
 // for radio group stuff
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIFormControl.h"
 
 #include "nsXMLEventsManager.h"
 
 #include "nsBidiUtils.h"
-#include "mozilla/dom/DirectionalityUtils.h"
 
 #include "nsIDOMUserDataHandler.h"
 #include "nsIDOMXPathEvaluator.h"
 #include "nsIXPathEvaluatorInternal.h"
 #include "nsIParserService.h"
 #include "nsContentCreatorFunctions.h"
 
 #include "nsIScriptContext.h"
@@ -166,17 +165,16 @@
 
 #include "mozilla/Preferences.h"
 
 #include "imgILoader.h"
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
-using namespace mozilla::directionality;
 
 typedef nsTArray<Link*> LinkArray;
 
 // Reference to the document which requested DOM full-screen mode.
 nsWeakPtr nsDocument::sFullScreenDoc = nullptr;
 
 // Reference to the root document of the branch containing the document
 // which requested DOM full-screen mode.
@@ -1507,18 +1505,17 @@ nsIDocument::nsIDocument()
     mRemovedFromDocShell(false),
     // mAllowDNSPrefetch starts true, so that we can always reliably && it
     // with various values that might disable it.  Since we never prefetch
     // unless we get a window, and in that case the docshell value will get
     // &&-ed in, this is safe.
     mAllowDNSPrefetch(true),
     mIsBeingUsedAsImage(false),
     mHasLinksToUpdate(false),
-    mPartID(0),
-    mDirectionality(eDir_LTR)
+    mPartID(0)
 {
   SetInDocument();
 }
 
 // NOTE! nsDocument::operator new() zeroes out all members, so don't
 // bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
@@ -5581,25 +5578,16 @@ nsDocument::SetDir(const nsAString& aDir
         if (shell) {
           nsPresContext *context = shell->GetPresContext();
           NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
           context->SetBidi(options, true);
         } else {
           // No presentation; just set it on ourselves
           SetBidiOptions(options);
         }
-        Directionality dir = elt->mValue == IBMBIDI_TEXTDIRECTION_RTL ?
-                               eDir_RTL : eDir_LTR;
-        SetDocumentDirectionality(dir);
-        // Set the directionality of the root element and its descendants, if any
-        Element* rootElement = GetRootElement();
-        if (rootElement) {
-          SetDirectionality(rootElement, dir, true);
-          SetDirectionalityOnDescendants(rootElement, dir);
-        }
       }
 
       break;
     }
   }
 
   return NS_OK;
 }
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1043,22 +1043,16 @@ protected:
   void DestroyElementMaps();
 
   // Refreshes the hrefs of all the links in the document.
   void RefreshLinkHrefs();
 
   nsIContent* GetFirstBaseNodeWithHref();
   nsresult SetFirstBaseNodeWithHref(nsIContent *node);
 
-  inline void
-  SetDocumentDirectionality(mozilla::directionality::Directionality aDir)
-  {
-    mDirectionality = aDir;
-  }
-
   // Get the first <title> element with the given IsNodeOfType type, or
   // return null if there isn't one
   nsIContent* GetTitleContent(PRUint32 aNodeType);
   // Find the first "title" element in the given IsNodeOfType type and
   // append the concatenation of its text node children to aTitle. Do
   // nothing if there is no such element.
   void GetTitleFromElement(PRUint32 aNodeType, nsAString& aTitle);
 
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -8,16 +8,17 @@
  * Class for managing loading of a subframe (creation of the docshell,
  * handling of loads in it, recursion-checking).
  */
 
 #include "base/basictypes.h"
 
 #include "prenv.h"
 
+#include "mozIApplication.h"
 #include "nsIDOMHTMLIFrameElement.h"
 #include "nsIDOMHTMLFrameElement.h"
 #include "nsIDOMMozBrowserFrame.h"
 #include "nsIDOMWindow.h"
 #include "nsIPresShell.h"
 #include "nsIContent.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
@@ -26,16 +27,17 @@
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebProgress.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocShellLoadInfo.h"
+#include "nsIDOMApplicationRegistry.h"
 #include "nsIBaseWindow.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsIJSContextStack.h"
 #include "nsUnicharUtils.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollable.h"
@@ -1968,64 +1970,60 @@ nsFrameLoader::TryRemoteBrowser()
   nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
   if (!window) {
     return false;
   }
   if (NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
     return false;
   }
 
-  PRUint32 appId = 0;
   bool isBrowserElement = false;
-
+  nsCOMPtr<mozIApplication> app;
   if (OwnerIsBrowserFrame()) {
     isBrowserElement = true;
 
     if (mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozapp)) {
       nsAutoString manifest;
       mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, manifest);
 
       nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
       if (!appsService) {
         NS_ERROR("Apps Service is not available!");
         return false;
       }
 
-      appsService->GetAppLocalIdByManifestURL(manifest, &appId);
-
-      // If the frame is actually an app, we should not mark it as a browser.
-      if (appId != nsIScriptSecurityManager::NO_APP_ID) {
+      nsCOMPtr<mozIDOMApplication> domApp;
+      appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp));
+      // If the frame is actually an app, we should not mark it as a
+      // browser.  This is to identify the data store: since <app>s
+      // and <browser>s-within-<app>s have different stores, we want
+      // to ensure the <app> uses its store, not the one for its
+      // <browser>s.
+      app = do_QueryInterface(domApp);
+      if (app) {
         isBrowserElement = false;
       }
     }
   }
 
-  // If our owner has no app manifest URL, then this is equivalent to
-  // ContentParent::GetNewOrUsed().
-  nsAutoString appManifest;
-  GetOwnerAppManifestURL(appManifest);
-  ContentParent* parent = ContentParent::GetForApp(appManifest);
-
-  NS_ASSERTION(parent->IsAlive(), "Process parent should be alive; something is very wrong!");
-  mRemoteBrowser = parent->CreateTab(chromeFlags, isBrowserElement, appId);
-  if (mRemoteBrowser) {
+  if ((mRemoteBrowser = ContentParent::CreateBrowser(app, isBrowserElement))) {
     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
     mRemoteBrowser->SetOwnerElement(element);
 
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
     parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
     nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem);
     nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
     NS_ABORT_IF_FALSE(rootChromeWin, "How did we not get a chrome window here?");
 
     nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
     rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
     mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
-    
-    mChildHost = parent;
+
+    mChildHost = static_cast<ContentParent*>(mRemoteBrowser->Manager());
   }
   return true;
 }
 
 mozilla::dom::PBrowserParent*
 nsFrameLoader::GetRemoteBrowser()
 {
   return mRemoteBrowser;
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -46,17 +46,16 @@
 #include "nsDOMTokenList.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsDOMError.h"
 #include "nsDOMString.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsMutationEvent.h"
 #include "nsNodeUtils.h"
-#include "mozilla/dom/DirectionalityUtils.h"
 #include "nsDocument.h"
 #include "nsAttrValueOrString.h"
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif /* MOZ_XUL */
 #include "nsFrameManager.h"
 #include "nsFrameSelection.h"
 #ifdef DEBUG
@@ -124,17 +123,16 @@
 #include "mozilla/Telemetry.h"
 
 #include "mozilla/CORSMode.h"
 
 #include "nsStyledElement.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
-using namespace mozilla::directionality;
 
 nsEventStates
 Element::IntrinsicState() const
 {
   return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
                         NS_EVENT_STATE_MOZ_READONLY;
 }
 
@@ -1355,23 +1353,16 @@ nsGenericElement::BindToTree(nsIDocument
                NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES |
                // And the restyle bits
                ELEMENT_ALL_RESTYLE_FLAGS);
   } else {
     // If we're not in the doc, update our subtree pointer.
     SetSubtreeRootPointer(aParent->SubtreeRoot());
   }
 
-  // This has to be here, rather than in nsGenericHTMLElement::BindToTree, 
-  //  because it has to happen after updating the parent pointer, but before
-  //  recursively binding the kids.
-  if (IsHTML()) {
-    RecomputeDirectionality(this, false);
-  }
-
   // If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
   // that also need to be told that they are moving.
   nsresult rv;
   if (hadForceXBL) {
     nsBindingManager* bmgr = OwnerDoc()->BindingManager();
 
     // First check if we have a binding...
     nsXBLBinding* contBinding =
@@ -1547,23 +1538,16 @@ nsGenericElement::UnbindFromTree(bool aD
 #endif
   {
     nsDOMSlots *slots = GetExistingDOMSlots();
     if (slots) {
       slots->mBindingParent = nullptr;
     }
   }
 
-  // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree, 
-  //  because it has to happen after unsetting the parent pointer, but before
-  //  recursively unbinding the kids.
-  if (IsHTML()) {
-    RecomputeDirectionality(this, false);
-  }
-
   if (aDeep) {
     // Do the kids. Don't call GetChildCount() here since that'll force
     // XUL to generate template children, which there is no need for since
     // all we're going to do is unbind them anyway.
     PRUint32 i, n = mAttrsAndChildren.ChildCount();
 
     for (i = 0; i < n; ++i) {
       // Note that we pass false for aNullParent here, since we don't want
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -265,17 +265,16 @@ GK_ATOM(details, "details")
 GK_ATOM(deviceAspectRatio, "device-aspect-ratio")
 GK_ATOM(deviceHeight, "device-height")
 GK_ATOM(deviceWidth, "device-width")
 GK_ATOM(dfn, "dfn")
 GK_ATOM(dialog, "dialog")
 GK_ATOM(difference, "difference")
 GK_ATOM(digit, "digit")
 GK_ATOM(dir, "dir")
-GK_ATOM(directionality, "directionality")
 GK_ATOM(disableOutputEscaping, "disable-output-escaping")
 GK_ATOM(disabled, "disabled")
 GK_ATOM(display, "display")
 GK_ATOM(distinct, "distinct")
 GK_ATOM(div, "div")
 GK_ATOM(dl, "dl")
 GK_ATOM(doctypePublic, "doctype-public")
 GK_ATOM(doctypeSystem, "doctype-system")
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -49,17 +49,17 @@ nsNodeInfoManager::GetNodeInfoInnerHashV
     // the moment because node->mName->hash() is not the same as
     // HashString(*(node->mNameString)).  See bug 732815.
     return HashString(nsDependentAtomString(node->mName));
   }
   return HashString(*(node->mNameString));
 }
 
 
-PRIntn
+int
 nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
 {
   NS_ASSERTION(key1 && key2, "Null key passed to NodeInfoInnerKeyCompare!");
 
   const nsINodeInfo::nsNodeInfoInner *node1 =
     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key1);
   const nsINodeInfo::nsNodeInfoInner *node2 =
     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key2);
@@ -178,18 +178,18 @@ nsNodeInfoManager::Init(nsIDocument *aDo
     PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
            ("NODEINFOMANAGER %p Init document=%p", this, aDocument));
 #endif
 
   return NS_OK;
 }
 
 // static
-PRIntn
-nsNodeInfoManager::DropNodeInfoDocument(PLHashEntry *he, PRIntn hashIndex, void *arg)
+int
+nsNodeInfoManager::DropNodeInfoDocument(PLHashEntry *he, int hashIndex, void *arg)
 {
   static_cast<nsINodeInfo*>(he->value)->mDocument = nullptr;
   return HT_ENUMERATE_NEXT;
 }
 
 void
 nsNodeInfoManager::DropDocumentReference()
 {
--- a/content/base/src/nsNodeInfoManager.h
+++ b/content/base/src/nsNodeInfoManager.h
@@ -111,19 +111,19 @@ protected:
                                         const nsAString& );
 
   /**
    * Sets the principal of the document this nodeinfo manager belongs to.
    */
   void SetDocumentPrincipal(nsIPrincipal *aPrincipal);
 
 private:
-  static PRIntn NodeInfoInnerKeyCompare(const void *key1, const void *key2);
+  static int NodeInfoInnerKeyCompare(const void *key1, const void *key2);
   static PLHashNumber GetNodeInfoInnerHashValue(const void *key);
-  static PRIntn DropNodeInfoDocument(PLHashEntry *he, PRIntn hashIndex,
+  static int DropNodeInfoDocument(PLHashEntry *he, int hashIndex,
                                      void *arg);
 
   PLHashTable *mNodeInfoHash;
   nsIDocument *mDocument; // WEAK
   PRUint32 mNonDocumentNodeInfos;
   nsIPrincipal *mPrincipal; // STRONG, but not nsCOMPtr to avoid include hell
                             // while inlining DocumentPrincipal().  Never null
                             // after Init() succeeds.
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -376,18 +376,16 @@ MOCHITEST_FILES_B = \
 		file_csp_redirects_page.sjs \
 		file_csp_redirects_main.html \
 		file_csp_redirects_resource.sjs \
 		test_bug346485.html \
 		test_bug560780.html \
 		test_bug562652.html \
 		test_bug562137.html \
 		file_bug562137.txt \
-		test_bug562169-1.html \
-		test_bug562169-2.html \
 		test_bug548193.html \
 		file_bug548193.sjs \
 		test_html_colors_quirks.html \
 		test_html_colors_standards.html \
 		test_bug300992.html \
 		test_websocket_hello.html \
 		file_websocket_hello_wsh.py \
 		test_websocket_basic.html \
--- a/content/base/test/test_bug345339.html
+++ b/content/base/test/test_bug345339.html
@@ -27,25 +27,24 @@ function afterLoad() {
     var iframeDoc = $("testframe").contentDocument;
 
     /* change all the form controls */
     iframeDoc.getElementById("select").selectedIndex = 1;
     iframeDoc.getElementById("radio2").checked = true;
     iframeDoc.getElementById("password").value = "123456";
     iframeDoc.getElementById("hidden").value = "gecko";
 
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var file = Components.classes["@mozilla.org/file/directory_service;1"]
+    var file = SpecialPowers.wrap(Components).classes["@mozilla.org/file/directory_service;1"]
              .getService(Components.interfaces.nsIProperties)
              .get("TmpD", Components.interfaces.nsILocalFile);
     file.append("345339_test.file");
     file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
     filePath = file.path;
 
-    iframeDoc.getElementById("file").value = filePath;
+    SpecialPowers.wrap(iframeDoc).getElementById("file").value = filePath;
 
     /* Reload the page */
     $("testframe").setAttribute("onload", "afterReload()");
     iframeDoc.location.reload();
 }
 
 addLoadEvent(afterLoad);
 
@@ -57,18 +56,17 @@ function afterReload() {
     is(iframeDoc.getElementById("radio1").checked, false,
        "radio button #1 value preserved");
     is(iframeDoc.getElementById("radio2").checked, true,
        "radio button #2 value preserved");
     isnot(iframeDoc.getElementById("password").value, "123456",
        "password field value forgotten");
     is(iframeDoc.getElementById("hidden").value, "gecko",
        "hidden field value preserved");
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    is(iframeDoc.getElementById("file").value, filePath,
+    is(SpecialPowers.wrap(iframeDoc).getElementById("file").value, filePath,
        "file field value preserved");
 
     SimpleTest.finish();
 }
 </script>
 </pre>
 </body>
 </html>
--- a/content/base/test/test_bug372964.html
+++ b/content/base/test/test_bug372964.html
@@ -26,19 +26,20 @@ var eventHandlerCallCount = 0;
 function eventHandler(evt) {
   ++eventHandlerCallCount;
   is(evt.type, expectedEventType, "Wrong event type");
   is(evt.isTrusted, shouldBeTrusted, "Wrong .isTrusted");
 }
 
 function test(trusted, type, removeAddedListener, removeSetListener, allowUntrusted) {
   if (trusted) {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    var x1 = SpecialPowers.wrap(new XMLHttpRequest());
+  } else {
+    x1 = new XMLHttpRequest();
   }
-  var x1 = new XMLHttpRequest();
 
   var handlerCount = 0;
   if (trusted || allowUntrusted || allowUntrusted == undefined) {
     ++handlerCount;
   }
 
   if (allowUntrusted == undefined) {
     // Test .addEventListener with 3 parameters.
--- a/content/base/test/test_bug380418.html
+++ b/content/base/test/test_bug380418.html
@@ -17,24 +17,23 @@
 
 	SimpleTest.waitForExplicitFinish();
 	
 	var request = new XMLHttpRequest();
 	request.open("GET", window.location.href, false);
 	request.send(null);
 	
 	// Try reading headers in privileged context
-	netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-	is(request.getResponseHeader("Set-Cookie"), "test", "Reading Set-Cookie response header in privileged context");
-	is(request.getResponseHeader("Set-Cookie2"), "test2", "Reading Set-Cookie2 response header in privileged context");
-	is(request.getResponseHeader("X-Dummy"), "test", "Reading X-Dummy response header in privileged context");
+	is(SpecialPowers.wrap(request).getResponseHeader("Set-Cookie"), "test", "Reading Set-Cookie response header in privileged context");
+	is(SpecialPowers.wrap(request).getResponseHeader("Set-Cookie2"), "test2", "Reading Set-Cookie2 response header in privileged context");
+	is(SpecialPowers.wrap(request).getResponseHeader("X-Dummy"), "test", "Reading X-Dummy response header in privileged context");
 	
-	ok(/\bSet-Cookie:/i.test(request.getAllResponseHeaders()), "Looking for Set-Cookie in all response headers in privileged context");
-	ok(/\bSet-Cookie2:/i.test(request.getAllResponseHeaders()), "Looking for Set-Cookie2 in all response headers in privileged context");
-	ok(/\bX-Dummy:/i.test(request.getAllResponseHeaders()), "Looking for X-Dummy in all response headers in privileged context");
+	ok(/\bSet-Cookie:/i.test(SpecialPowers.wrap(request).getAllResponseHeaders()), "Looking for Set-Cookie in all response headers in privileged context");
+	ok(/\bSet-Cookie2:/i.test(SpecialPowers.wrap(request).getAllResponseHeaders()), "Looking for Set-Cookie2 in all response headers in privileged context");
+	ok(/\bX-Dummy:/i.test(SpecialPowers.wrap(request).getAllResponseHeaders()), "Looking for X-Dummy in all response headers in privileged context");
 	
 	// Try reading headers in unprivileged context
 	setTimeout(function() {
 	  is(request.getResponseHeader("Set-Cookie"), null, "Reading Set-Cookie response header in unprivileged context");
 	  is(request.getResponseHeader("Set-Cookie2"), null, "Reading Set-Cookie2 response header in unprivileged context");
 	  is(request.getResponseHeader("X-Dummy"), "test", "Reading X-Dummy response header in unprivileged context");
 	  
 	  ok(!/\bSet-Cookie:/i.test(request.getAllResponseHeaders()), "Looking for Set-Cookie in all response headers in unprivileged context");
--- a/content/base/test/test_bug422537.html
+++ b/content/base/test/test_bug422537.html
@@ -14,38 +14,40 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 422537 **/
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-var isupports_string = Components.classes["@mozilla.org/supports-string;1"]
-                                 .createInstance(Components.interfaces.nsISupportsString);
+var isupports_string = SpecialPowers.wrap(Components)
+                                    .classes["@mozilla.org/supports-string;1"]
+                                    .createInstance(Components.interfaces.nsISupportsString);
 isupports_string.data = "foo";
 
 const url = "http://mochi.test:8888";
 var body = [
   document,
   "foo",
   isupports_string
 ];
 
 for each (var i in body) {
   var xhr = new XMLHttpRequest();
   xhr.open("POST", url, true);
-  xhr.send(i);
-  var chan = SpecialPowers.unwrap(SpecialPowers.wrap(xhr).channel);
-  if (!(chan instanceof Components.interfaces.nsIUploadChannel))
+  if (i == isupports_string)
+    SpecialPowers.wrap(xhr).send(i);
+  else
+    xhr.send(i);
+  var chan = SpecialPowers.wrap(xhr).channel;
+  if (!SpecialPowers.call_Instanceof(chan, Components.interfaces.nsIUploadChannel))
     throw "Must be an upload channel";
   var stream = chan.uploadStream;
-  if (!stream || !(stream instanceof Components.interfaces.nsISeekableStream))
+  if (!stream || !SpecialPowers.call_Instanceof(stream, Components.interfaces.nsISeekableStream))
     throw "Stream must be seekable";
   // the following is a no-op, but should not throw an exception
   stream.seek(Components.interfaces.nsISeekableStream.NS_SEEK_CUR, 0);
 }
 
 ok(true, "xhr is seekable");
 
 </script>
deleted file mode 100644
--- a/content/base/test/test_bug562169-1.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=562169
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 562169</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
-<p id="display"></p>
-<div id="content" style="display: none">
- <div dir="rtl" id="z"></div>  
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 562169 **/
-/** Test that adding an child to an element with dir="rtl" makes the
-      child have rtl directionality, and removing the child makes it
-     go back to ltr directionality **/
-
-function checkSelector(element, expectedDir, expectedChild)
-{
-    ok(element.querySelector(":dir("+expectedDir+")") == expectedChild,
-       "direction should be " + expectedDir);
-}
-
-var x = document.createElement("div");
-var y = document.createElement("div");
-x.appendChild(y);
-checkSelector(x, "ltr", y);
-$(z).appendChild(x);
-checkSelector(x, "rtl", y);
-$(z).removeChild(x);
-checkSelector(x, "ltr", y);
-
-</script>
-</pre>
-</body>
-</html>
deleted file mode 100644
--- a/content/base/test/test_bug562169-2.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=562169
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 562169</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 562169 **/
-/** Test that a newly created element has ltr directionality **/
-
-ok(document.createElement("div").mozMatchesSelector(":dir(ltr)"),
-   "Element should be ltr on creation");
-
-</script>
-</pre>
-</body>
-</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/727547.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<canvas></canvas>
+<script>
+var canvas = document.body.firstChild,
+    gl = canvas.getContext("experimental-webgl");
+gl.texImage2D(0, 0, 0, 0, 0, { width: 10, height: 10, data: 7 });
+</script>
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/780392-1.html
@@ -0,0 +1,10 @@
+<!doctype HTML>
+<html>
+<body>
+<canvas id="c" width="10000" height="10000"></canvas>
+<script>
+var ctx = document.getElementById("c").getContext("2d");
+ctx.fillText("Hello world!", 50, 50);
+</script>
+</body>
+</html>
--- a/content/canvas/crashtests/crashtests.list
+++ b/content/canvas/crashtests/crashtests.list
@@ -1,13 +1,15 @@
 load 360293-1.html
 load 421715-1.html
 load 553938-1.html
 load 647480.html
+load 727547.html
 load 0px-size-font-667225.html
 load texImage2D.html
 load 729116.html
 load 745699-1.html
 load 746813-1.html
 # this test crashes in a bunch places still
 #load 745818-large-source.html
 load 743499-negative-size.html
 load 767337-1.html
+load 780392-1.html
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -1,79 +1,76 @@
 <!DOCTYPE HTML>
 <title>Canvas Tests</title>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <script>
 
 SimpleTest.waitForExplicitFinish();
+const Cc = SpecialPowers.wrap(Components).classes;
+const Cr = SpecialPowers.wrap(Components).results;
 
 function IsD2DEnabled() {
     var enabled = false;
 
     try {
-        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-        enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled;
+        enabled = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled;
     } catch(e) {}
     
     return enabled;
 }
 
 function IsLinux() {
     return navigator.platform.indexOf("Linux") == 0;
 }
 
 function IsMacOSX10_5orOlder() {
     var is105orOlder = false;
 
     if (navigator.platform.indexOf("Mac") == 0) {
-        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-        var version = Components.classes["@mozilla.org/system-info;1"]
-                            .getService(Components.interfaces.nsIPropertyBag2)
-                            .getProperty("version");
+        var version = Cc["@mozilla.org/system-info;1"]
+                        .getService(Components.interfaces.nsIPropertyBag2)
+                        .getProperty("version");
         // the next line is correct: Mac OS 10.6 corresponds to Darwin version 10 !
         // Mac OS 10.5 would be Darwin version 9. the |version| string we've got here
         // is the Darwin version.
         is105orOlder = (parseFloat(version) < 10.0);
     }
     return is105orOlder;
 }
 
 
 function IsAzureEnabled() {
   var enabled = false;
 
   try {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
+    var backend = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
     enabled = (backend != "none");
   } catch (e) { }
 
   return enabled;
 }
 
 function IsAzureSkia() {
   var enabled = false;
   
   try {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
+    var backend = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
     enabled = (backend == "skia");
   } catch (e) { }
 
   return enabled;
 }
 
 function IsAzureCairo() {
   var enabled = false;
   
   try {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
+    var backend = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
     enabled = (backend == "cairo");
   } catch (e) { }
 
   return enabled;
 }
 
 </script>
 <!-- Includes all the tests in the content/canvas/tests except for test_bug397524.html -->
@@ -121,17 +118,18 @@ ok(ctx.canvas === canvas, "ctx.canvas ==
 <!-- [[[ test_2d.clearRect.basic.html ]]] -->
 
 <p>Canvas test: 2d.clearRect.basic</p>
 <canvas id="c3" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 function isPixel(ctx, x,y, r,g,b,a, d) {
 	var pos = x + "," + y;
 	var colour = r + "," + g + "," + b + "," + a;
-    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pixel = SpecialPowers.unwrap(SpecialPowers.wrap(ctx)
+                                                  .getImageData(x, y, 1, 1));
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
     ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
@@ -19799,19 +19797,18 @@ function test_bug397524() {
 
 <!-- [[[ test_bug405982.html ]]] -->
 
 <p>Canvas test: toDataURL.png</p>
 <canvas id="c614" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 function test_bug405982() {
 
-var canvas = document.getElementById('c614');
-var ctx = canvas.getContext('2d');
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var canvas = SpecialPowers.wrap(document.getElementById('c614'));
+var ctx = canvas.getContext('2d');
 
 var _threw = false;
 try {
   var data = canvas.toDataURL('image/png', 'quality=100');
 }
 catch (e) {
   _threw = true;
 }
@@ -21118,17 +21115,16 @@ ctx667.fillStyle = 'rgba(12, 16, 244, 0.
 ctx667.fillRect(75, 0, 25, 25);
 var img = new Image();
 deferTest();
 img.onload = wrapFunction(function ()
 {
     ctx667.drawImage(img, 0, 25);
     // (The alpha values do not really survive float->int conversion, so just
     // do approximate comparisons)
-    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     isPixel(ctx667, 12,40, 1,3,254,255, 0);
     isPixel(ctx667, 37,40, 8,252,248,191, 2);
     isPixel(ctx667, 62,40, 6,10,250,127, 4);
     isPixel(ctx667, 87,40, 12,16,244,63, 8);
 });
 img.src = canvas667.toDataURL();
 
 
@@ -21245,17 +21241,16 @@ ctx672.fillRect(0, 40, 100, 10);
 var data = canvas672.toDataURL();
 ctx672.fillStyle = '#f00';
 ctx672.fillRect(0, 0, 100, 50);
 var img = new Image();
 deferTest();
 img.onload = wrapFunction(function ()
 {
     ctx672.drawImage(img, 0, 0);
-    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     isPixel(ctx672, 12,20, 255,255,0,255, 0);
     isPixel(ctx672, 50,20, 0,255,255,255, 0);
     isPixel(ctx672, 87,20, 0,0,255,255, 0);
     isPixel(ctx672, 50,45, 255,255,255,255, 0);
 });
 img.src = data;
 
 
--- a/content/events/public/nsEventStates.h
+++ b/content/events/public/nsEventStates.h
@@ -243,20 +243,16 @@ private:
 // Content is in the sub-suboptimal region.
 #define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(39)
 // Handler for click to play plugin (vulnerable w/update)
 #define NS_EVENT_STATE_VULNERABLE_UPDATABLE NS_DEFINE_EVENT_STATE_MACRO(40)
 // Handler for click to play plugin (vulnerable w/no update)
 #define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
 // Platform does not support plugin content (some mobile platforms)
 #define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42)
-// Element is ltr (for :dir pseudo-class)
-#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(43)
-// Element is rtl (for :dir pseudo-class)
-#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(44)
 
 /**
  * NOTE: do not go over 63 without updating nsEventStates::InternalType!
  */
 
 #define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS |     \
                             NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER |   \
                             NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
--- a/content/events/src/nsDOMSimpleGestureEvent.cpp
+++ b/content/events/src/nsDOMSimpleGestureEvent.cpp
@@ -45,17 +45,17 @@ nsDOMSimpleGestureEvent::GetDirection(PR
 {
   NS_ENSURE_ARG_POINTER(aDirection);
   *aDirection = static_cast<nsSimpleGestureEvent*>(mEvent)->direction;
   return NS_OK;
 }
 
 /* readonly attribute float delta; */
 NS_IMETHODIMP
-nsDOMSimpleGestureEvent::GetDelta(PRFloat64 *aDelta)
+nsDOMSimpleGestureEvent::GetDelta(double *aDelta)
 {
   NS_ENSURE_ARG_POINTER(aDelta);
   *aDelta = static_cast<nsSimpleGestureEvent*>(mEvent)->delta;
   return NS_OK;
 }
 
 /* readonly attribute unsigned long clickCount; */
 NS_IMETHODIMP
@@ -78,17 +78,17 @@ nsDOMSimpleGestureEvent::InitSimpleGestu
                                                 PRInt32 aClientY,
                                                 bool aCtrlKeyArg,
                                                 bool aAltKeyArg,
                                                 bool aShiftKeyArg,
                                                 bool aMetaKeyArg,
                                                 PRUint16 aButton,
                                                 nsIDOMEventTarget* aRelatedTarget,
                                                 PRUint32 aDirectionArg,
-                                                PRFloat64 aDeltaArg,
+                                                double aDeltaArg,
                                                 PRUint32 aClickCountArg)
 {
   nsresult rv = nsDOMMouseEvent::InitMouseEvent(aTypeArg,
                                                 aCanBubbleArg,
                                                 aCancelableArg,
                                                 aViewArg,
                                                 aDetailArg,
                                                 aScreenX, 
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -48,17 +48,16 @@
 #include "nsScriptLoader.h"
 #include "nsRuleData.h"
 
 #include "nsPresState.h"
 #include "nsILayoutHistoryState.h"
 
 #include "nsHTMLParts.h"
 #include "nsContentUtils.h"
-#include "mozilla/dom/DirectionalityUtils.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsGkAtoms.h"
 #include "nsEventStateManager.h"
 #include "nsIDOMEvent.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsITextControlFrame.h"
 #include "nsIForm.h"
@@ -92,17 +91,16 @@
 #include "HTMLPropertiesCollection.h"
 #include "nsVariant.h"
 #include "nsDOMSettableTokenList.h"
 #include "nsThreadUtils.h"
 #include "nsTextFragment.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
-using namespace mozilla::directionality;
 
 class nsINodeInfo;
 class nsIDOMNodeList;
 class nsRuleWalker;
 
 // XXX todo: add in missing out-of-memory checks
 
 //----------------------------------------------------------------------
@@ -1684,34 +1682,16 @@ nsGenericHTMLElement::UpdateEditableStat
   if (value != eInherit) {
     DoSetEditableFlag(!!value, aNotify);
     return;
   }
 
   nsStyledElement::UpdateEditableState(aNotify);
 }
 
-nsEventStates
-nsGenericHTMLElement::IntrinsicState() const
-{
-  nsEventStates state = nsGenericHTMLElementBase::IntrinsicState();
-
-  if (GetDirectionality() == eDir_RTL) {
-    state |= NS_EVENT_STATE_RTL;
-    state &= ~NS_EVENT_STATE_LTR;
-  } else { // at least for HTML, directionality is exclusively LTR or RTL
-    NS_ASSERTION(GetDirectionality() == eDir_LTR,
-                 "HTML element's directionality must be either RTL or LTR");
-    state |= NS_EVENT_STATE_LTR;
-    state &= ~NS_EVENT_STATE_RTL;
-  }
-
-  return state;
-}
-
 nsresult
 nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                  nsIContent* aBindingParent,
                                  bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElementBase::BindToTree(aDocument, aParent,
                                                      aBindingParent,
                                                      aCompileEventHandlers);
@@ -1904,30 +1884,16 @@ nsGenericHTMLElement::AfterSetAttr(PRInt
       NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
         "Expected string value for script body");
       nsresult rv = AddScriptEventListener(aName, aValue->GetStringValue());
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aNotify && aName == nsGkAtoms::spellcheck) {
       SyncEditorsOnSubtree(this);
     }
-    else if (aName == nsGkAtoms::dir) {
-      Directionality dir;
-      if (aValue &&
-          (aValue->Equals(nsGkAtoms::ltr, eIgnoreCase) ||
-           aValue->Equals(nsGkAtoms::rtl, eIgnoreCase))) {
-        SetHasValidDir();
-        dir = aValue->Equals(nsGkAtoms::rtl, eIgnoreCase) ? eDir_RTL : eDir_LTR;
-        SetDirectionality(this, dir, aNotify);
-      } else {
-        ClearHasValidDir();
-        dir = RecomputeDirectionality(this, aNotify);
-      }
-      SetDirectionalityOnDescendants(this, dir, aNotify);
-    }
   }
 
   return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
                                                 aValue, aNotify);
 }
 
 nsEventListenerManager*
 nsGenericHTMLElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -44,18 +44,16 @@ typedef nsMappedAttributeElement nsGener
 class nsGenericHTMLElement : public nsGenericHTMLElementBase
 {
 public:
   nsGenericHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElementBase(aNodeInfo)
   {
     NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
                  "Unexpected namespace");
-    AddStatesSilently(NS_EVENT_STATE_LTR);
-    SetFlags(NODE_HAS_DIRECTION_LTR);
   }
 
   /** Typesafe, non-refcounting cast from nsIContent.  Cheaper than QI. **/
   static nsGenericHTMLElement* FromContent(nsIContent *aContent)
   {
     if (aContent->IsHTML())
       return static_cast<nsGenericHTMLElement*>(aContent);
     return nullptr;
@@ -199,18 +197,16 @@ public:
   nsresult PostHandleEventForAnchors(nsEventChainPostVisitor& aVisitor);
   bool IsHTMLLink(nsIURI** aURI) const;
 
   // HTML element methods
   void Compact() { mAttrsAndChildren.Compact(); }
 
   virtual void UpdateEditableState(bool aNotify);
 
-  virtual nsEventStates IntrinsicState() const;
-
   // Helper for setting our editable flag and notifying
   void DoSetEditableFlag(bool aEditable, bool aNotify) {
     SetEditableFlag(aEditable);
     UpdateState(aNotify);
   }
 
   virtual bool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -260,16 +260,17 @@ MOCHITEST_FILES = \
 		test_bug651956.html \
 		test_bug694503.html \
 		test_object_plugin_nav.html \
 		test_bug742030.html \
 		test_bug742549.html \
 		test_bug745685.html \
 		test_input_file_picker.html \
 		test_bug763626.html \
+		test_bug780993.html \
 		$(NULL)
 
 MOCHITEST_BROWSER_FILES = \
 		browser_bug649778.js \
 		file_bug649778.html \
 		file_bug649778.html^headers^ \
 		$(NULL)
 
--- a/content/html/content/test/test_bug143220.html
+++ b/content/html/content/test/test_bug143220.html
@@ -19,37 +19,36 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 143220 **/
 var leafName;
 var fullPath;
 
+
 function initVals() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
-                         .getService(Components.interfaces.nsIProperties);
+  var dirSvc = SpecialPowers.wrap(Components)
+                            .classes["@mozilla.org/file/directory_service;1"]
+                            .getService(Components.interfaces.nsIProperties);
   var file = dirSvc.get("XpcomLib", Components.interfaces.nsILocalFile);
   isnot(file, null, "Must have file here");
 
   leafName = file.leafName;
   fullPath = file.path;
 }
 
 function initControl1() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  $("i1").value = fullPath;
-  is($("i1").value, fullPath, "Should have set full path 1");
+  SpecialPowers.wrap($("i1")).value = fullPath;
+  is(SpecialPowers.wrap($("i1")).value, fullPath, "Should have set full path 1");
 }
 
 function initControl2() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  $("i2").value = fullPath;
-  is($("i2").value, fullPath, "Should have set full path 2");
+  SpecialPowers.wrap($("i2")).value = fullPath;
+  is(SpecialPowers.wrap($("i2")).value, fullPath, "Should have set full path 2");
 }
 
 initVals();
 
 // Check that we can't just set the value
 try {
   $("i1").value = fullPath;
   is(0, 1, "Should have thrown exception on set!");
--- a/content/html/content/test/test_bug523771.html
+++ b/content/html/content/test/test_bug523771.html
@@ -27,36 +27,35 @@ var input2Files =
   [{ name: "523771_file2", type: "", body: "second file contents" },
    { name: "523771_file3.txt", type: "text/plain", body: "123456" },
    { name: "523771_file4.html", type: "text/html", body: "<html>content</html>" }
   ];
 
 SimpleTest.waitForExplicitFinish();
 
 function setFileInputs () {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   f = createFileWithData(input1File.name, input1File.body);
-  singleFileInput.mozSetFileNameArray([f.path], 1);
+  SpecialPowers.wrap(singleFileInput).mozSetFileNameArray([f.path], 1);
 
   var input2FileNames = [];
   for each (file in input2Files) {
     f = createFileWithData(file.name, file.body);
     input2FileNames.push(f.path);
   }
-  multiFileInput.mozSetFileNameArray(input2FileNames, input2FileNames.length);
+  SpecialPowers.wrap(multiFileInput).mozSetFileNameArray(input2FileNames, input2FileNames.length);
 }
 
 function createFileWithData(fileName, fileData) {
-  var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
-                         .getService(Components.interfaces.nsIProperties);
+  var dirSvc = SpecialPowers.wrap(Components).classes["@mozilla.org/file/directory_service;1"]
+                            .getService(Components.interfaces.nsIProperties);
   var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
   testFile.append(fileName);
-  var outStream = Components.
-                  classes["@mozilla.org/network/file-output-stream;1"].
-                  createInstance(Components.interfaces.nsIFileOutputStream);
+  var outStream = SpecialPowers.wrap(Components).
+                    classes["@mozilla.org/network/file-output-stream;1"].
+                    createInstance(Components.interfaces.nsIFileOutputStream);
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
                  0666, 0);
   outStream.write(fileData, fileData.length);
   outStream.close();
 
   filesToKill.push(testFile);
 
   return testFile;
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug780993.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test for bug 780993</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var select = document.createElement("select");
+  var option = document.createElement("option");
+  select.appendChild(option);
+  assert_equals(select[0], option);
+  select[0] = null;
+  assert_equals(option.parentNode, null);
+  assert_equals(select[0], null);
+}, "Should be able to set select[n] to null.");
+test(function() {
+  var select = document.createElement("select");
+  var option = document.createElement("option");
+  var option2 = document.createElement("option");
+  select.appendChild(option);
+  assert_equals(select[0], option);
+  select[0] = option2;
+  assert_equals(option.parentNode, null);
+  assert_equals(option2.parentNode, select);
+  assert_equals(select[0], option2);
+}, "Should be able to set select[n] to an option element");
+test(function() {
+  var select = document.createElement("select");
+  var option = document.createElement("option");
+  select.appendChild(option);
+  assert_equals(select[0], option);
+  assert_throws(null, function() {
+    select[0] = 42;
+  });
+  assert_equals(option.parentNode, select);
+  assert_equals(select[0], option);
+}, "Should not be able to set select[n] to a primitive.");
+</script>
--- a/content/html/document/src/ImageDocument.cpp
+++ b/content/html/document/src/ImageDocument.cpp
@@ -87,17 +87,19 @@ public:
   virtual void Destroy();
   virtual void OnPageShow(bool aPersisted,
                           nsIDOMEventTarget* aDispatchStartTarget);
 
   NS_DECL_NSIIMAGEDOCUMENT
 
   // imgIDecoderObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage);
+  NS_IMETHOD OnStopContainer(imgIRequest* aRequest, imgIContainer* aImage);
   NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult aStatus, const PRUnichar *aStatusArg);
+  NS_IMETHOD OnDiscard(imgIRequest *aRequest);
 
   // nsIDOMEventListener
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ImageDocument, MediaDocument)
 
   friend class ImageListener;
 
@@ -515,28 +517,36 @@ ImageDocument::OnStartContainer(imgIRequ
     NS_NewRunnableMethod(this, &ImageDocument::DefaultCheckOverflowing);
   nsContentUtils::AddScriptRunner(runnable);
   UpdateTitleAndCharset();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+ImageDocument::OnStopContainer(imgIRequest* aRequest, imgIContainer* aImage)
+{
+  if (mImageContent) {
+    // Update the background-color of the image only after the
+    // image has been decoded to prevent flashes of just the
+    // background-color.
+    mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
+                           NS_LITERAL_STRING("decoded"), true);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 ImageDocument::OnStopDecode(imgIRequest *aRequest,
                             nsresult aStatus,
                             const PRUnichar *aStatusArg)
 {
   UpdateTitleAndCharset();
 
-  nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mImageContent);
-  if (imageLoader) {
-    mObservingImageLoader = false;
-    imageLoader->RemoveObserver(this);
-  }
-
   // mImageContent can be null if the document is already destroyed
   if (NS_FAILED(aStatus) && mStringBundle && mImageContent) {
     nsCAutoString src;
     mDocumentURI->GetSpec(src);
     NS_ConvertUTF8toUTF16 srcString(src);
     const PRUnichar* formatString[] = { srcString.get() };
     nsXPIDLString errorMsg;
     NS_NAMED_LITERAL_STRING(str, "InvalidImage");
@@ -545,16 +555,28 @@ ImageDocument::OnStopDecode(imgIRequest 
 
     mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::alt, errorMsg, false);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+ImageDocument::OnDiscard(imgIRequest *aRequest)
+{
+  // mImageContent can be null if the document is already destroyed
+  if (mImageContent) {
+    // Remove any decoded-related styling when the image is unloaded.
+    mImageContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class,
+                             true);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 ImageDocument::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsAutoString eventType;
   aEvent->GetType(eventType);
   if (eventType.EqualsLiteral("resize")) {
     CheckOverflowing(false);
   }
   else if (eventType.EqualsLiteral("click") && mClickResizingEnabled) {
--- a/content/html/document/test/test_bug445004.html
+++ b/content/html/document/test/test_bug445004.html
@@ -50,19 +50,17 @@ function checkURI(uri, name, type) {
   var host = uri.match(/^http:\/\/([a-z.0-9]*)/)[1];
   var file = uri.match(/([^\/]*).png$/)[1];
   is(host, file, "Unexpected base URI for test " + name +
      " when testing " + type);
 }
 
 function checkFrame(num) {
   // Just snarf our data
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-  var outer = window.frames[num]
+  var outer = SpecialPowers.wrap(window.frames[num]);
   name = outer.name;
 
   is(outer.document.baseURI,
      "http://example.org/tests/content/html/document/test/bug445004-outer.html",
      "Unexpected base URI for " + name);
 
   var iswrite = name.match(/write/);
 
--- a/content/html/document/test/test_bug512367.html
+++ b/content/html/document/test/test_bug512367.html
@@ -19,31 +19,29 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 var frame = document.getElementById("i");
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   var viewer =
-    frame.contentWindow
-         .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-         .getInterface(Components.interfaces.nsIWebNavigation)
-         .QueryInterface(Components.interfaces.nsIDocShell)
-         .contentViewer
-         .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
+    SpecialPowers.wrap(frame.contentWindow
+                 .QueryInterface(Components.interfaces.nsIInterfaceRequestor))
+                 .getInterface(Components.interfaces.nsIWebNavigation)
+                 .QueryInterface(Components.interfaces.nsIDocShell)
+                 .contentViewer
+                 .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
 
   viewer.fullZoom = 1.5;
 
   setTimeout(function() {
     synthesizeMouse(frame, 30, 30, {});
 
-    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     is(viewer.fullZoom, 1.5, "Zoom in the image frame should not have been reset");
 
     SimpleTest.finish();
   }, 0);
 });
 </script>
 </pre>
 </body>
--- a/content/media/plugins/nsMediaPluginReader.h
+++ b/content/media/plugins/nsMediaPluginReader.h
@@ -11,18 +11,18 @@
 #include "nsBuiltinDecoderReader.h"
 
 #include "MPAPI.h"
 
 class nsMediaPluginReader : public nsBuiltinDecoderReader
 {
   nsCString mType;
   MPAPI::Decoder *mPlugin;
-  PRBool mHasAudio;
-  PRBool mHasVideo;
+  bool mHasAudio;
+  bool mHasVideo;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
   int64_t mVideoSeekTimeUs;
   int64_t mAudioSeekTimeUs;
   VideoData *mLastVideoFrame;
 public:
   nsMediaPluginReader(nsBuiltinDecoder* aDecoder);
   ~nsMediaPluginReader();
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -154,20 +154,19 @@ var gPlayTests = [
 // Converts a path/filename to a file:// URI which we can load from disk.
 // Optionally checks whether the file actually exists on disk at the location
 // we've specified.
 function fileUriToSrc(path, mustExist) {
   // android mochitest doesn't support file://
   if (navigator.appVersion.indexOf("Android") != -1)
     return path;
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   const Ci = Components.interfaces;
-  const Cc = Components.classes;
-  const Cr = Components.results;
+  const Cc = SpecialPowers.wrap(Components).classes;
+  const Cr = SpecialPowers.wrap(Components).results;
   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
                getService(Ci.nsIProperties);
   var f = dirSvc.get("CurWorkD", Ci.nsILocalFile);
   var split = path.split("/");
   for(var i = 0; i < split.length; ++i) {
     f.append(split[i]);
   }
   if (mustExist && !f.exists()) {
@@ -439,18 +438,17 @@ function MediaTestManager() {
   }
 
   // Starts the next batch of tests, or finishes if they're all done.
   // Don't call this directly, call finished(token) when you're done.
   this.nextTest = function() {
     // Force a GC after every completed testcase. This ensures that any decoders
     // with live threads waiting for the GC are killed promptly, to free up the
     // thread stacks' address space.
-    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-    Components.utils.forceGC();
+    SpecialPowers.forceGC();
     
     while (this.testNum < this.tests.length && this.tokens.length < PARALLEL_TESTS) {
       var test = this.tests[this.testNum];
       var token = (test.name ? (test.name + "-"): "") + this.testNum;
       this.testNum++;
 
       if (DEBUG_TEST_LOOP_FOREVER && this.testNum == this.tests.length) {
         this.testNum = 0;
@@ -492,40 +490,38 @@ function mediaTestCleanup() {
       V[i].parentNode.removeChild(V[i]);
       V[i] = null;
     }
     var A = document.getElementsByTagName("audio");
     for (i=0; i<A.length; i++) {
       A[i].parentNode.removeChild(A[i]);
       A[i] = null;
     }
-    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-    Components.utils.forceGC();
+    SpecialPowers.forceGC();
 }
 
 (function() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   // Ensure that preload preferences are comsistent
-  var prefService = Components.classes["@mozilla.org/preferences-service;1"]
-                               .getService(Components.interfaces.nsIPrefService);
+  var prefService = SpecialPowers.wrap(Components)
+                                 .classes["@mozilla.org/preferences-service;1"]
+                                 .getService(Components.interfaces.nsIPrefService);
   var branch = prefService.getBranch("media.");
   var oldDefault = 2;
   var oldAuto = 3;
   var oldOpus = undefined;
   try {
     oldDefault = branch.getIntPref("preload.default");
     oldAuto    = branch.getIntPref("preload.auto");
     oldOpus    = branch.getBoolPref("opus.enabled");
   } catch(ex) { }
   branch.setIntPref("preload.default", 2); // preload_metadata
   branch.setIntPref("preload.auto", 3); // preload_enough
   // test opus playback iff the pref exists
   if (oldOpus !== undefined)
     branch.setBoolPref("opus.enabled", true);
 
   window.addEventListener("unload", function() {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     branch.setIntPref("preload.default", oldDefault);
     branch.setIntPref("preload.auto", oldAuto);
     if (oldOpus !== undefined)
       branch.setBoolPref("opus.enabled", oldOpus);
   }, false);
  })();
--- a/content/xslt/src/base/txDouble.cpp
+++ b/content/xslt/src/base/txDouble.cpp
@@ -151,17 +151,17 @@ void txDouble::toString(double aValue, n
         aDest.AppendLiteral("Infinity");
         return;
     }
 
     // Mantissa length is 17, so this is plenty
     const int buflen = 20;
     char buf[buflen];
 
-    PRIntn intDigits, sign;
+    int intDigits, sign;
     char* endp;
     PR_dtoa(aValue, 0, 0, &intDigits, &sign, &endp, buf, buflen - 1);
 
     // compute length
     PRInt32 length = endp - buf;
     if (length > intDigits) {
         // decimal point needed
         ++length;
--- a/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp
+++ b/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp
@@ -567,17 +567,17 @@ txXPathNodeUtils::getXSLTId(const txXPat
 /* static */
 void
 txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsAString& aURI)
 {
     aNode.mNode->GetDOMBaseURI(aURI);
 }
 
 /* static */
-PRIntn
+int
 txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
                                   const txXPathNode& aOtherNode)
 {
     // First check for equal nodes or attribute-nodes on the same element.
     if (aNode.mNode == aOtherNode.mNode) {
         if (aNode.mIndex == aOtherNode.mIndex) {
             return 0;
         }
--- a/content/xslt/src/xpath/txNodeSet.cpp
+++ b/content/xslt/src/xpath/txNodeSet.cpp
@@ -562,33 +562,33 @@ txXPathNode*
 txNodeSet::findPosition(const txXPathNode& aNode, txXPathNode* aFirst,
                         txXPathNode* aLast, bool& aDupe) const
 {
     aDupe = false;
     if (aLast - aFirst <= 2) {
         // If we search 2 nodes or less there is no point in further divides
         txXPathNode* pos = aFirst;
         for (; pos < aLast; ++pos) {
-            PRIntn cmp = txXPathNodeUtils::comparePosition(aNode, *pos);
+            int cmp = txXPathNodeUtils::comparePosition(aNode, *pos);
             if (cmp < 0) {
                 return pos;
             }
 
             if (cmp == 0) {
                 aDupe = true;
 
                 return pos;
             }
         }
         return pos;
     }
 
     // (cannot add two pointers)
     txXPathNode* midpos = aFirst + (aLast - aFirst) / 2;
-    PRIntn cmp = txXPathNodeUtils::comparePosition(aNode, *midpos);
+    int cmp = txXPathNodeUtils::comparePosition(aNode, *midpos);
     if (cmp == 0) {
         aDupe = true;
 
         return midpos;
     }
 
     if (cmp > 0) {
         return findPosition(aNode, midpos + 1, aLast, aDupe);
--- a/content/xslt/src/xpath/txXPathTreeWalker.h
+++ b/content/xslt/src/xpath/txXPathTreeWalker.h
@@ -89,18 +89,18 @@ public:
     static void appendNodeValue(const txXPathNode& aNode, nsAString& aResult);
     static bool isWhitespace(const txXPathNode& aNode);
     static txXPathNode* getOwnerDocument(const txXPathNode& aNode);
     static PRInt32 getUniqueIdentifier(const txXPathNode& aNode);
     static nsresult getXSLTId(const txXPathNode& aNode,
                               const txXPathNode& aBase, nsAString& aResult);
     static void release(txXPathNode* aNode);
     static void getBaseURI(const txXPathNode& aNode, nsAString& aURI);
-    static PRIntn comparePosition(const txXPathNode& aNode,
-                                  const txXPathNode& aOtherNode);
+    static int comparePosition(const txXPathNode& aNode,
+                               const txXPathNode& aOtherNode);
     static bool localNameEquals(const txXPathNode& aNode,
                                   nsIAtom* aLocalName);
     static bool isRoot(const txXPathNode& aNode);
     static bool isElement(const txXPathNode& aNode);
     static bool isAttribute(const txXPathNode& aNode);
     static bool isProcessingInstruction(const txXPathNode& aNode);
     static bool isComment(const txXPathNode& aNode);
     static bool isText(const txXPathNode& aNode);
--- a/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp
+++ b/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp
@@ -272,17 +272,17 @@ txFormatNumberFunctionCall::evaluate(txI
     if (value > 1)
         bufsize = (int)log10(value) + 30;
     else
         bufsize = 1 + 30;
 
     char* buf = new char[bufsize];
     NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
 
-    PRIntn bufIntDigits, sign;
+    int bufIntDigits, sign;
     char* endp;
     PR_dtoa(value, 0, 0, &bufIntDigits, &sign, &endp, buf, bufsize-1);
 
     int buflen = endp - buf;
     int intDigits;
     intDigits = bufIntDigits > minIntegerSize ? bufIntDigits : minIntegerSize;
 
     if (groupSize < 0)
--- a/content/xul/templates/src/nsRuleNetwork.cpp
+++ b/content/xul/templates/src/nsRuleNetwork.cpp
@@ -200,17 +200,17 @@ Instantiation::Hash(const void* aKey)
     for (nsAssignmentSet::ConstIterator assignment = inst->mAssignments.First();
          assignment != last; ++assignment)
         result ^= assignment->Hash();
 
     return result;
 }
 
 
-PRIntn
+int
 Instantiation::Compare(const void* aLeft, const void* aRight)
 {
     const Instantiation* left  = static_cast<const Instantiation*>(aLeft);
     const Instantiation* right = static_cast<const Instantiation*>(aRight);
 
     return *left == *right;
 }
 
--- a/content/xul/templates/src/nsRuleNetwork.h
+++ b/content/xul/templates/src/nsRuleNetwork.h
@@ -461,17 +461,17 @@ public:
 
     bool operator==(const Instantiation& aInstantiation) const {
         return Equals(aInstantiation); }
 
     bool operator!=(const Instantiation& aInstantiation) const {
         return !Equals(aInstantiation); }
 
     static PLHashNumber Hash(const void* aKey);
-    static PRIntn Compare(const void* aLeft, const void* aRight);
+    static int Compare(const void* aLeft, const void* aRight);
 };
 
 
 //----------------------------------------------------------------------
 
 /**
  * A collection of intantiations
  */
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorStorage.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorStorage.cpp
@@ -330,17 +330,17 @@ nsXULTemplateQueryProcessorStorage::Comp
                   &nsGkAtoms::null, &nsGkAtoms::double_, &nsGkAtoms::string, nullptr };
 
             PRInt32 typeError = 1;
             PRInt32 typeValue = child->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type,
                                                        sTypeValues, eCaseMatters);
             rv = NS_ERROR_ILLEGAL_VALUE;
             PRInt32 valInt32 = 0;
             PRInt64 valInt64 = 0;
-            PRFloat64 valFloat = 0;
+            double valFloat = 0;
 
             switch (typeValue) {
               case 0:
               case 1:
                 typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%d",&valInt32);
                 if (typeError > 0)
                     rv = statement->BindInt32ByIndex(index, valInt32);
                 break;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -6050,27 +6050,29 @@ nsDocShell::OnStateChange(nsIWebProgress
 
     if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
         // Save timing statistics.
         nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
         nsCOMPtr<nsIURI> uri;
         channel->GetURI(getter_AddRefs(uri));
         nsCAutoString aURI;
         uri->GetAsciiSpec(aURI);
-        if (this == aProgress){
+
+        nsCOMPtr<nsIWyciwygChannel>  wcwgChannel(do_QueryInterface(aRequest));
+        nsCOMPtr<nsIWebProgress> webProgress =
+            do_QueryInterface(GetAsSupports(this));
+
+        // We don't update navigation timing for wyciwyg channels
+        if (this == aProgress && !wcwgChannel){
             rv = MaybeInitTiming();
             if (mTiming) {
                 mTiming->NotifyFetchStart(uri, ConvertLoadTypeToNavigationType(mLoadType));
             } 
         }
 
-        nsCOMPtr<nsIWyciwygChannel>  wcwgChannel(do_QueryInterface(aRequest));
-        nsCOMPtr<nsIWebProgress> webProgress =
-            do_QueryInterface(GetAsSupports(this));
-
         // Was the wyciwyg document loaded on this docshell?
         if (wcwgChannel && !mLSHE && (mItemType == typeContent) && aProgress == webProgress.get()) {
             bool equalUri = true;
             // Store the wyciwyg url in session history, only if it is
             // being loaded fresh for the first time. We don't want 
             // multiple entries for successive loads
             if (mCurrentURI &&
                 NS_SUCCEEDED(uri->Equals(mCurrentURI, &equalUri)) &&
--- a/docshell/test/Makefile.in
+++ b/docshell/test/Makefile.in
@@ -90,16 +90,18 @@ MOCHITEST_FILES = \
 		file_bug669671.sjs \
 		test_bug675587.html \
 		test_bfcache_plus_hash.html \
 		test_bug680257.html \
 		file_bug680257.html \
 		test_bug691547.html \
 		bug691547_frame.html \
 		test_bug694612.html \
+		test_bug703855.html \
+		file_bug703855.html \
 		test_bug713825.html \
 		test_bug728939.html \
 		file_bug728939.html \
 		$(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 MOCHITEST_FILES += \
 		test_bug511449.html \
new file mode 100644
--- /dev/null
+++ b/docshell/test/file_bug703855.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<!-- Just need an empty file here, as long as it's served over HTTP -->
--- a/docshell/test/navigation/NavigationUtils.js
+++ b/docshell/test/navigation/NavigationUtils.js
@@ -93,27 +93,28 @@ function isInaccessible(wnd, message) {
   }
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Functions that require UniversalXPConnect privilege
 ///////////////////////////////////////////////////////////////////////////
 
 function xpcEnumerateContentWindows(callback) {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
   var Ci = Components.interfaces;
-  var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
-                     .getService(Ci.nsIWindowWatcher);
+  var ww = SpecialPowers.wrap(Components)
+                        .classes["@mozilla.org/embedcomp/window-watcher;1"]
+                        .getService(Ci.nsIWindowWatcher);
   var enumerator = ww.getWindowEnumerator();
 
   var contentWindows = [];
 
   while (enumerator.hasMoreElements()) {
     var win = enumerator.getNext();
-    if (typeof ChromeWindow != "undefined" && win instanceof ChromeWindow) {
+    if (typeof ChromeWindow != "undefined" && SpecialPowers.call_Instanceof(win, ChromeWindow)) {
       var docshellTreeNode = win.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsIWebNavigation)
                                 .QueryInterface(Ci.nsIDocShellTreeNode);
       var childCount = docshellTreeNode.childCount;
       for (var i = 0; i < childCount; ++i) {
         var childTreeNode = docshellTreeNode.getChildAt(i);
 
         // we're only interested in content docshells
--- a/docshell/test/navigation/file_bug534178.html
+++ b/docshell/test/navigation/file_bug534178.html
@@ -1,15 +1,14 @@
 <html>
   <head>
     <script>
     
       function testDone() {
         document.body.removeChild(document.body.firstChild);
-        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         var isOK = false;
         try {
           isOK = history.previous != location;
         } catch(ex) {
           // history.previous should throw if this is the first page in shistory.
           isOK = true;
         }
         document.body.textContent = isOK ? "PASSED" : "FAILED";
--- a/docshell/test/navigation/test_bug386782.html
+++ b/docshell/test/navigation/test_bug386782.html
@@ -55,39 +55,36 @@ https://bugzilla.mozilla.org/show_bug.cg
         if ("onload" in gTest) {
           gTest.onload(gTest.window.document);
         }
         SimpleTest.waitForFocus(beginTest, gTest.window);
       }, false);
     }
 
     function beginTest() {
-      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
       gTest.window.document.body.focus();
 
       // WARNING: If the following test fails, give the setTimeout() in the onload()
       // a bit longer; the doc hasn't had enough time to setup its editor.
       is(gTest.window.document.body.innerHTML, gTest.expectedBodyBeforeEdit, "Is doc setup yet");
       sendString('EDITED ', gTest.window);
       is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterEdit, "Editing failed.");
 
       gTest.window.location = 'data:text/html;charset=utf-8,SomeOtherDocument';
       SimpleTest.waitForFocus(goBack, gTest.window);
     }
     
     function goBack() {
-      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
       gTest.window.history.back();
       setTimeout(function() {
         SimpleTest.waitForFocus(checkStillEditable, gTest.window);
       }, 0);
     }
 
     function checkStillEditable() {
-      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
       // Check that the contents are correct.
       is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterEdit, "Edited contents still correct?");
       
       // Check that we can undo/redo and the contents are correct.
       gTest.window.document.execCommand("undo", false, null);
       is(gTest.window.document.body.innerHTML, gTest.expectedBodyBeforeEdit, "Can we undo?");
 
--- a/docshell/test/test_bug369814.html
+++ b/docshell/test/test_bug369814.html
@@ -181,19 +181,19 @@ var gTests = [
     "func" : loadErrorTest
   },
 ];
 
 var gNextTest = 0;
 
 function runNextTest()
 {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-    getService(Components.interfaces.nsIPrefBranch);
+  var prefs = SpecialPowers.wrap(Components)
+                           .classes["@mozilla.org/preferences-service;1"]
+                           .getService(Components.interfaces.nsIPrefBranch);
 
   if (gNextTest < gTests.length) {
     gCurrentTest = gTests[gNextTest++];
     gNumPokes = 0;
 
     prefs.setBoolPref("network.jar.open-unsafe-types", gCurrentTest['pref']);
 
     // Create a new frame each time, so our restictions on loads in a
@@ -209,33 +209,33 @@ function runNextTest()
     // Put back the pref value we had at test start
     prefs.setBoolPref("network.jar.open-unsafe-types", gPrefValue);
     SimpleTest.finish();
   }
 }
 
 function finishTest()
 {
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-      getService(Components.interfaces.nsIPrefBranch);
+    var prefs = SpecialPowers.wrap(Components)
+                             .classes["@mozilla.org/preferences-service;1"]
+                             .getService(Components.interfaces.nsIPrefBranch);
     prefs.setBoolPref("network.jar.open-unsafe-types", false);
 
   if (gNumPokes == 0) {
     ok(true, gCurrentTest["name"] + ": no unexpected pokes");
   }
 
   runNextTest();
 }
 
 function startTests()
 {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  var prefs = Components.classes["@mozilla.org/preferences-service;1"].
-    getService(Components.interfaces.nsIPrefBranch);
+  var prefs = SpecialPowers.wrap(Components)
+                           .classes["@mozilla.org/preferences-service;1"]
+                           .getService(Components.interfaces.nsIPrefBranch);
   gPrefValue = prefs.getBoolPref("network.jar.open-unsafe-types");
 }
 
 addLoadEvent(runNextTest);
 
 </script>
 </pre>
 </body>
--- a/docshell/test/test_bug509055.html
+++ b/docshell/test/test_bug509055.html
@@ -36,18 +36,16 @@ function onChildHashchange(e) {
 }
 
 function onChildLoad(e) {
   if(gGen)
     gGen.next();
 }
 
 function runTest() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
   var popup = window.open("file_bug509055.html", "popup 0",
                            "height=200,width=200,location=yes," +
                            "menubar=yes,status=yes,toolbar=yes,dependent=yes");
   popup.hashchangeCallback = onChildHashchange;
   popup.onload = onChildLoad;
   dump('Waiting for initial load.\n');
   yield;
 
@@ -67,19 +65,20 @@ function runTest() {
 
   popup.document.title = "Changed";
 
   // Wait for listeners to be notified of the title change.
   shortWait();
   dump('Got second hashchange.  Spinning event loop.\n');
   yield;
 
-  var sh = popup.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                .getInterface(Components.interfaces.nsIWebNavigation)
-                .sessionHistory;
+  var sh = SpecialPowers.wrap(popup)
+                        .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                        .getInterface(Components.interfaces.nsIWebNavigation)
+                        .sessionHistory;
 
   // Get the title of the inner popup's current SHEntry 
   var sheTitle = sh.getEntryAtIndex(sh.index, false).title;
   is(sheTitle, "Changed", "SHEntry's title should change when we change.");
 
   popup.close();
 
   SimpleTest.executeSoon(SimpleTest.finish);
--- a/docshell/test/test_bug529119-1.html
+++ b/docshell/test/test_bug529119-1.html
@@ -38,42 +38,39 @@ function pollForPage(f, w)
         f(iterationsLeft > 0);
       }
     }, 100);
   }, 1000);
 }
 
 function windowLoaded()
 {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   switch (phase)
   {
     case 0:
       /* 2. We have succeededfully loaded a page, now go to a faulty URL */
       window.setTimeout(function() {
         w.location.href = faultyURL;
       }, 0);
     
       phase = 1;
 
       pollForPage(function(succeeded) {
         ok(succeeded, "Waiting for error page succeeded");
         
-        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         /* 3. now, while we are on the error page, try to reload it, actually 
            click the "Try Again" button */
-        w.location.reload();
+        SpecialPowers.wrap(w).location.reload();
 
         pollForPage(function(succeeded) {
           ok(succeeded, "Waiting for error page succeeded");
           
-          netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
           /* 4-finish, check we are still on the error page */
-          is(w.location.href, faultyURL, "Is on an error page");
-          isnot(w.location.href, workingURL, "Is not on the previous page");
+          is(SpecialPowers.wrap(w).location.href, faultyURL, "Is on an error page");
+          isnot(SpecialPowers.wrap(w).location.href, workingURL, "Is not on the previous page");
           is(gotWrongPageOnTryAgainClick, false, 
             "Must not get www.example.com page on reload of an error page");
           w.close();
           SimpleTest.finish();
         }, w);
       }, w);
       break;
       
--- a/docshell/test/test_bug529119-2.html
+++ b/docshell/test/test_bug529119-2.html
@@ -37,43 +37,37 @@ function pollForPage(expectErrorPage, f,
         f(iterationsLeft > 0);
       }
     }, 100);
   }, 1000);
 }
 
 function windowLoaded()
 {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
   /* 2. We have successfully loaded a page, now go to a faulty URL */
   // XXX The test fails when we change the location synchronously 
   window.setTimeout(function() {
     w.location.href = faultyURL;
   }, 0);
 
   pollForPage(true, function(succeeded) {
     ok(succeeded, "Waiting for error page succeeded");
-    
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     /* 3. now, while we are on the error page, navigate back */
     try {
-      w.back();
+      SpecialPowers.wrap(w).back();
     }
     catch(ex) {
       ok(false, "w.back() threw " + ex);
     }
 
     pollForPage(false, function(succeeded) {
       ok(succeeded, "Waiting for original page succeeded");
-      
-      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
       /* 4-finish, check we are back at the original page */
-      isnot(w.location.href, faultyURL, "Is on an error page");
-      is(w.location.href, workingURL, "Is not on the previous page");
+      isnot(SpecialPowers.wrap(w).location.href, faultyURL, "Is on an error page");
+      is(SpecialPowers.wrap(w).location.href, workingURL, "Is not on the previous page");
       w.close();
       SimpleTest.finish();
     }, w);
   }, w);
 }
 
 function startTest()
 {
new file mode 100644
--- /dev/null
+++ b/docshell/test/test_bug703855.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=703855
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 703855</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=703855">Mozilla Bug 703855</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe id="f" src="file_bug703855.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 703855 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var timingAttributes = [
+  'connectEnd',
+  'connectStart',
+  'domComplete',
+  'domContentLoadedEventEnd',
+  'domContentLoadedEventStart',
+  'domInteractive',
+  'domLoading',
+  'domainLookupEnd',
+  'domainLookupStart',
+  'fetchStart',
+  'loadEventEnd',
+  'loadEventStart',
+  'navigationStart',
+  'redirectEnd',
+  'redirectStart',
+  'requestStart',
+  'responseEnd',
+  'responseStart',
+  'unloadEventEnd',
+  'unloadEventStart'
+];
+var originalTiming = {};
+
+function runTest() {
+  var timing = $("f").contentWindow.performance.timing;
+  for (i in timingAttributes) {
+    originalTiming[timingAttributes[i]] = timing[timingAttributes[i]];
+  }
+
+  var doc = $("f").contentDocument;
+  doc.open();
+  doc.write("<!DOCTYPE html>");
+  doc.close();
+
+  SimpleTest.executeSoon(function() {
+    var newTiming = $("f").contentWindow.performance.timing;
+    for (var i in timingAttributes) {
+      is(timing[timingAttributes[i]], originalTiming[timingAttributes[i]],
+         "document.open should not affect value of " + timingAttributes[i]);
+    }
+    SimpleTest.finish();
+  });
+}
+
+addLoadEvent(function() {
+  SimpleTest.executeSoon(runTest);
+});
+
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/apps/src/AppsService.js
+++ b/dom/apps/src/AppsService.js
@@ -48,13 +48,33 @@ AppsService.prototype = {
       return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
     } else {
       let res = this.cpmm.sendSyncMessage("WebApps:GetAppLocalIdByManifestURL",
                                           { url: aManifestURL })[0];
       return res.id;
     }
   },
 
+  getAppByLocalId: function getAppByLocalId(aLocalId) {
+    debug("getAppByLocalId( " + aLocalId + " )");
+    if (this.inParent) {
+      return DOMApplicationRegistry.getAppByLocalId(aLocalId);
+    } else {
+      return this.cpmm.sendSyncMessage("WebApps:GetAppByLocalId",
+                                       { id: aLocalId })[0];
+    }
+  },
+
+  getManifestURLByLocalId: function getManifestURLByLocalId(aLocalId) {
+    debug("getManifestURLByLocalId( " + aLocalId + " )");
+    if (this.inParent) {
+      return DOMApplicationRegistry.getManifestURLByLocalId(aLocalId);
+    } else {
+      return this.cpmm.sendSyncMessage("WebApps:GetManifestURLByLocalId",
+                                       { id: aLocalId })[0];
+    }
+  },
+
   classID : APPS_SERVICE_CID,
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
 }
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([AppsService])
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -52,17 +52,18 @@ let DOMApplicationRegistry = {
   allAppsLaunchable: false,
 
   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:GetAppByManifestURL", "WebApps:GetAppLocalIdByManifestURL",
+                    "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,
@@ -215,16 +216,17 @@ let DOMApplicationRegistry = {
       case "Webapps:Install":
         // always ask for UI to install
         Services.obs.notifyObservers(this, "webapps-ask-install", JSON.stringify(msg));
         break;
       case "Webapps:GetSelf":
         this.getSelf(msg);
         break;
       case "Webapps:Uninstall":
+        Services.obs.notifyObservers(this, "webapps-uninstall", JSON.stringify(msg));
         this.uninstall(msg);
         break;
       case "Webapps:Launch":
         Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg));
         break;
       case "Webapps:GetInstalled":
         this.getInstalled(msg);
         break;
@@ -244,16 +246,22 @@ let DOMApplicationRegistry = {
         return FileUtils.getFile(DIRECTORY_NAME, ["webapps"], true).path;
         break;
       case "WebApps:GetAppByManifestURL":
         return this.getAppByManifestURL(msg.url);
         break;
       case "WebApps:GetAppLocalIdByManifestURL":
         return { id: this.getAppLocalIdByManifestURL(msg.url) };
         break;
+      case "WebApps:GetAppByLocalId":
+        return this.getAppByLocalId(msg.id);
+        break;
+      case "WebApps:GetManifestURLByLocalId":
+        return this.getManifestURLByLocalId(msg.id);
+        break;
     }
   },
 
   _writeFile: function ss_writeFile(aFile, aData, aCallbak) {
     // Initialize the file output stream.
     let ostream = FileUtils.openSafeFileOutputStream(aFile);
 
     // Obtain a converter to convert our data to a UTF-8 encoded input stream.
@@ -686,23 +694,63 @@ let DOMApplicationRegistry = {
 
   getAppByManifestURL: function(aManifestURL) {
     // This could be O(1) if |webapps| was a dictionary indexed on manifestURL
     // which should be the unique app identifier.
     // It's currently O(n).
     for (let id in this.webapps) {
       let app = this.webapps[id];
       if (app.manifestURL == aManifestURL) {
+        let res = this._cloneAppObject(app);
+        res.hasPermission = function(permission) {
+          let localId = DOMApplicationRegistry.getAppLocalIdByManifestURL(
+            this.manifestURL);
+          let uri = Services.io.newURI(this.manifestURL, null, null);
+          let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+                       .getService(Ci.nsIScriptSecurityManager);
+          // XXX for the purposes of permissions checking, this helper
+          // should always be called on !isBrowser frames, so we
+          // assume false here.
+          let principal = secMan.getAppCodebasePrincipal(uri, localId,
+                                                         /*mozbrowser*/false);
+          let perm = Services.perms.testExactPermissionFromPrincipal(principal,
+                                                                     permission);
+          return (perm === Ci.nsIPermissionManager.ALLOW_ACTION);
+        };
+        res.QueryInterface = XPCOMUtils.generateQI([Ci.mozIDOMApplication,
+                                                    Ci.mozIApplication]);
+        return res;
+      }
+    }
+
+    return null;
+  },
+
+  getAppByLocalId: function(aLocalId) {
+    for (let id in this.webapps) {
+      let app = this.webapps[id];
+      if (app.localId == aLocalId) {
         return this._cloneAppObject(app);
       }
     }
 
     return null;
   },
 
+  getManifestURLByLocalId: function(aLocalId) {
+    for (let id in this.webapps) {
+      let app = this.webapps[id];
+      if (app.localId == aLocalId) {
+        return app.manifestURL;
+      }
+    }
+
+    return null;
+  },
+
   getAppLocalIdByManifestURL: function(aManifestURL) {
     for (let id in this.webapps) {
       if (this.webapps[id].manifestURL == aManifestURL) {
         return this.webapps[id].localId;
       }
     }
 
     return Ci.nsIScriptSecurityManager.NO_APP_ID;
@@ -923,16 +971,20 @@ DOMApplicationManifest.prototype = {
   get icons() {
     return this._localeProp("icons");
   },
 
   get appcache_path() {
     return this._localeProp("appcache_path");
   },
 
+  get orientation() {
+    return this._localeProp("orientation");
+  },
+
   iconURLForSize: function(aSize) {
     let icons = this._localeProp("icons");
     if (!icons)
       return null;
     let dist = 100000;
     let icon = null;
     for (let size in icons) {
       let iSize = parseInt(size);
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -2,34 +2,35 @@
  * 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 "nsContentPermissionHelper.h"
 #include "nsIContentPermissionPrompt.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMElement.h"
-
+#include "nsIPrincipal.h"
 #include "mozilla/unused.h"
 
 using mozilla::unused;          // <snicker>
+using namespace mozilla::dom;
 
 nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
 {
   MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
 }
 
 nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
 {
   MOZ_COUNT_DTOR(nsContentPermissionRequestProxy);
 }
 
 nsresult
 nsContentPermissionRequestProxy::Init(const nsACString & type,
-				                      mozilla::dom::ContentPermissionRequestParent* parent)
+                                      ContentPermissionRequestParent* parent)
 {
   NS_ASSERTION(parent, "null parent");
   mParent = parent;
   mType   = type;
 
   nsCOMPtr<nsIContentPermissionPrompt> prompt = do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (!prompt) {
     return NS_ERROR_FAILURE;
@@ -58,82 +59,89 @@ NS_IMETHODIMP
 nsContentPermissionRequestProxy::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
   *aRequestingWindow = nullptr; // ipc doesn't have a window
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsContentPermissionRequestProxy::GetUri(nsIURI * *aRequestingURI)
+nsContentPermissionRequestProxy::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
 {
-  NS_ENSURE_ARG_POINTER(aRequestingURI);
-  if (mParent == nullptr)
+  NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
+  if (mParent == nullptr) {
     return NS_ERROR_FAILURE;
+  }
 
-  NS_ADDREF(*aRequestingURI = mParent->mURI);
+  NS_ADDREF(*aRequestingPrincipal = mParent->mPrincipal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContentPermissionRequestProxy::GetElement(nsIDOMElement * *aRequestingElement)
 {
   NS_ENSURE_ARG_POINTER(aRequestingElement);
-  if (mParent == nullptr)
+  if (mParent == nullptr) {
     return NS_ERROR_FAILURE;
+  }
+
   NS_ADDREF(*aRequestingElement = mParent->mElement);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContentPermissionRequestProxy::Cancel()
 {
-  if (mParent == nullptr)
+  if (mParent == nullptr) {
     return NS_ERROR_FAILURE;
-  unused << mozilla::dom::ContentPermissionRequestParent::Send__delete__(mParent, false);
+  }
+
+  unused << ContentPermissionRequestParent::Send__delete__(mParent, false);
   mParent = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContentPermissionRequestProxy::Allow()
 {
-  if (mParent == nullptr)
+  if (mParent == nullptr) {
     return NS_ERROR_FAILURE;
-  unused << mozilla::dom::ContentPermissionRequestParent::Send__delete__(mParent, true);
+  }
+  unused << ContentPermissionRequestParent::Send__delete__(mParent, true);
   mParent = nullptr;
   return NS_OK;
 }
 
 namespace mozilla {
 namespace dom {
 
 ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString& aType,
                                                                nsIDOMElement *aElement,
-                                                               const IPC::URI& aUri)
+                                                               const IPC::Principal& aPrincipal)
 {
   MOZ_COUNT_CTOR(ContentPermissionRequestParent);
-  
-  mURI       = aUri;
+
+  mPrincipal = aPrincipal;
   mElement   = aElement;
   mType      = aType;
 }
 
 ContentPermissionRequestParent::~ContentPermissionRequestParent()
 {
   MOZ_COUNT_DTOR(ContentPermissionRequestParent);
 }
 
 bool
 ContentPermissionRequestParent::Recvprompt()
 {
   mProxy = new nsContentPermissionRequestProxy();
   NS_ASSERTION(mProxy, "Alloc of request proxy failed");
-  if (NS_FAILED(mProxy->Init(mType, this)))
+  if (NS_FAILED(mProxy->Init(mType, this))) {
     mProxy->Cancel();
+  }
   return true;
 }
 
 void
 ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
 {
   mProxy->OnParentDestroyed();
 }
--- a/dom/base/nsContentPermissionHelper.h
+++ b/dom/base/nsContentPermissionHelper.h
@@ -6,51 +6,52 @@
 #define nsContentPermissionHelper_h
 
 #include "base/basictypes.h"
 
 #include "nsIContentPermissionPrompt.h"
 #include "nsString.h"
 #include "nsIDOMElement.h"
 
+#include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
 
 class nsContentPermissionRequestProxy;
 
 namespace mozilla {
 namespace dom {
 
 class ContentPermissionRequestParent : public PContentPermissionRequestParent
 {
  public:
-  ContentPermissionRequestParent(const nsACString& type, nsIDOMElement *element, const IPC::URI& principal);
+  ContentPermissionRequestParent(const nsACString& type, nsIDOMElement *element, const IPC::Principal& principal);
   virtual ~ContentPermissionRequestParent();
-  
-  nsCOMPtr<nsIURI>           mURI;
+
+  nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIDOMElement>    mElement;
   nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
   nsCString mType;
 
- private:  
+ private:
   virtual bool Recvprompt();
   virtual void ActorDestroy(ActorDestroyReason why);
 };
-  
+
 } // namespace dom
 } // namespace mozilla
 
 class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
 {
  public:
   nsContentPermissionRequestProxy();
   virtual ~nsContentPermissionRequestProxy();
-  
+
   nsresult Init(const nsACString& type, mozilla::dom::ContentPermissionRequestParent* parent);
   void OnParentDestroyed();
-  
+
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
  private:
   // Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
   mozilla::dom::ContentPermissionRequestParent* mParent;
   nsCString mType;
 };
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1702,34 +1702,40 @@ static nsDOMClassInfoData sClassInfoData
 
 // Objects that should be constructable through |new Name();|
 struct nsContractIDMapData
 {
   PRInt32 mDOMClassInfoID;
   const char *mContractID;
 };
 
-#define NS_DEFINE_CONSTRUCTOR_DATA(_class, _contract_id)                      \
-  { eDOMClassInfo_##_class##_id, _contract_id },
-
-static const nsContractIDMapData kConstructorMap[] =
-{
-  NS_DEFINE_CONSTRUCTOR_DATA(DOMParser, NS_DOMPARSER_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(FileReader, NS_FILEREADER_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(ArchiveReader, NS_ARCHIVEREADER_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(FormData, NS_FORMDATA_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(XMLSerializer, NS_XMLSERIALIZER_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(WebSocket, NS_WEBSOCKET_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(XPathEvaluator, NS_XPATH_EVALUATOR_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(XSLTProcessor,
-                             "@mozilla.org/document-transformer;1?type=xslt")
-  NS_DEFINE_CONSTRUCTOR_DATA(EventSource, NS_EVENTSOURCE_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(MutationObserver, NS_DOMMUTATIONOBSERVER_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(MozActivity, NS_DOMACTIVITY_CONTRACTID)
-};
+#define NS_DEFINE_CONTRACT_CTOR(_class, _contract_id)                           \
+  nsresult                                                                      \
+  _class##Ctor(nsISupports** aInstancePtrResult)                                \
+  {                                                                             \
+    nsresult rv = NS_OK;                                                        \
+    nsCOMPtr<nsISupports> native = do_CreateInstance(_contract_id, &rv);        \
+    native.forget(aInstancePtrResult);                                          \
+    return rv;                                                                  \
+  }
+
+NS_DEFINE_CONTRACT_CTOR(DOMParser, NS_DOMPARSER_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(FileReader, NS_FILEREADER_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(ArchiveReader, NS_ARCHIVEREADER_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(FormData, NS_FORMDATA_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(XMLSerializer, NS_XMLSERIALIZER_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(WebSocket, NS_WEBSOCKET_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(XPathEvaluator, NS_XPATH_EVALUATOR_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(XSLTProcessor,
+                        "@mozilla.org/document-transformer;1?type=xslt")
+NS_DEFINE_CONTRACT_CTOR(EventSource, NS_EVENTSOURCE_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(MutationObserver, NS_DOMMUTATIONOBSERVER_CONTRACTID)
+NS_DEFINE_CONTRACT_CTOR(MozActivity, NS_DOMACTIVITY_CONTRACTID)
+
+#undef NS_DEFINE_CONTRACT_CTOR
 
 #define NS_DEFINE_EVENT_CTOR(_class)                        \
   nsresult                                                  \
   NS_DOM##_class##Ctor(nsISupports** aInstancePtrResult)    \
   {                                                         \
     nsIDOMEvent* e = nullptr;                                \
     nsresult rv = NS_NewDOM##_class(&e, nullptr, nullptr);    \
     *aInstancePtrResult = e;                                \
@@ -1782,30 +1788,40 @@ static const nsConstructorFuncMapData kC
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MozWifiConnectionInfoEvent)
 #endif
 #define MOZ_GENERATED_EVENT_LIST
 #define MOZ_GENERATED_EVENT(_event_interface) \
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(_event_interface)
 #include "GeneratedEvents.h"
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, sms::SmsFilter::NewSmsFilter)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XMLHttpRequest, NS_XMLHttpRequestCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(DOMParser, DOMParserCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(FileReader, FileReaderCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ArchiveReader, ArchiveReaderCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(FormData, FormDataCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XMLSerializer, XMLSerializerCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebSocket, WebSocketCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XPathEvaluator, XPathEvaluatorCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XSLTProcessor, XSLTProcessorCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(EventSource, EventSourceCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MutationObserver, MutationObserverCtor)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozActivity, MozActivityCtor)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nullptr;
 bool nsDOMClassInfo::sIsInitialized = false;
 bool nsDOMClassInfo::sDisableDocumentAllSupport = false;
 bool nsDOMClassInfo::sDisableGlobalScopePollutionSupport = false;
 
 
 jsid nsDOMClassInfo::sParent_id          = JSID_VOID;
 jsid nsDOMClassInfo::sScrollbars_id      = JSID_VOID;
 jsid nsDOMClassInfo::sLocation_id        = JSID_VOID;
 jsid nsDOMClassInfo::sConstructor_id     = JSID_VOID;
-jsid nsDOMClassInfo::s_content_id        = JSID_VOID;
 jsid nsDOMClassInfo::sContent_id         = JSID_VOID;
 jsid nsDOMClassInfo::sMenubar_id         = JSID_VOID;
 jsid nsDOMClassInfo::sToolbar_id         = JSID_VOID;
 jsid nsDOMClassInfo::sLocationbar_id     = JSID_VOID;
 jsid nsDOMClassInfo::sPersonalbar_id     = JSID_VOID;
 jsid nsDOMClassInfo::sStatusbar_id       = JSID_VOID;
 jsid nsDOMClassInfo::sDialogArguments_id = JSID_VOID;
 jsid nsDOMClassInfo::sControllers_id     = JSID_VOID;
@@ -2072,17 +2088,16 @@ nsDOMClassInfo::DefineStaticJSVals(JSCon
       return NS_ERROR_OUT_OF_MEMORY;
 
   JSAutoRequest ar(cx);
 
   SET_JSID_TO_STRING(sParent_id,          cx, "parent");
   SET_JSID_TO_STRING(sScrollbars_id,      cx, "scrollbars");
   SET_JSID_TO_STRING(sLocation_id,        cx, "location");
   SET_JSID_TO_STRING(sConstructor_id,     cx, "constructor");
-  SET_JSID_TO_STRING(s_content_id,        cx, "_content");
   SET_JSID_TO_STRING(sContent_id,         cx, "content");
   SET_JSID_TO_STRING(sMenubar_id,         cx, "menubar");
   SET_JSID_TO_STRING(sToolbar_id,         cx, "toolbar");
   SET_JSID_TO_STRING(sLocationbar_id,     cx, "locationbar");
   SET_JSID_TO_STRING(sPersonalbar_id,     cx, "personalbar");
   SET_JSID_TO_STRING(sStatusbar_id,       cx, "statusbar");
   SET_JSID_TO_STRING(sDialogArguments_id, cx, "dialogArguments");
   SET_JSID_TO_STRING(sControllers_id,     cx, "controllers");
@@ -2180,33 +2195,16 @@ CutPrefix(const char *aName) {
     return aName + sizeof(prefix_nsI) - 1;
   }
 
   return aName;
 }
 
 // static
 nsresult
-nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
-{
-  nsScriptNameSpaceManager *nameSpaceManager =
-    nsJSRuntime::GetNameSpaceManager();
-  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
-
-  nameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
-                                      aClassInfoID,
-                                      sClassInfoData[aClassInfoID].mChromeOnly,
-                                      sClassInfoData[aClassInfoID].mDisabled,
-                                      &sClassInfoData[aClassInfoID].mNameUTF16);
-
-  return NS_OK;
-}
-
-// static
-nsresult
 nsDOMClassInfo::RegisterClassProtos(PRInt32 aClassInfoID)
 {
   nsScriptNameSpaceManager *nameSpaceManager =
     nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
   bool found_old;
 
   const nsIID *primary_iid = sClassInfoData[aClassInfoID].mProtoChainInterface;
@@ -4540,17 +4538,19 @@ nsDOMClassInfo::Init()
 #endif
 
   // Initialize static JSString's
   DefineStaticJSVals(cx);
 
   PRInt32 i;
 
   for (i = 0; i < eDOMClassInfoIDCount; ++i) {
-    RegisterClassName(i);
+    nsDOMClassInfoData& data = sClassInfoData[i];
+    nameSpaceManager->RegisterClassName(data.mName, i, data.mChromeOnly,
+                                        data.mDisabled, &data.mNameUTF16);
   }
 
   for (i = 0; i < eDOMClassInfoIDCount; ++i) {
     RegisterClassProtos(i);
   }
 
   RegisterExternalClasses();
 
@@ -5199,17 +5199,16 @@ nsDOMClassInfo::ShutDown()
       NS_IF_RELEASE(sClassInfoData[i].mCachedClassInfo);
     }
   }
 
   sParent_id          = JSID_VOID;
   sScrollbars_id      = JSID_VOID;
   sLocation_id        = JSID_VOID;
   sConstructor_id     = JSID_VOID;
-  s_content_id        = JSID_VOID;
   sContent_id         = JSID_VOID;
   sMenubar_id         = JSID_VOID;
   sToolbar_id         = JSID_VOID;
   sLocationbar_id     = JSID_VOID;
   sPersonalbar_id     = JSID_VOID;
   sStatusbar_id       = JSID_VOID;
   sDialogArguments_id = JSID_VOID;
   sControllers_id     = JSID_VOID;
@@ -5638,29 +5637,16 @@ nsWindowSH::Enumerate(nsIXPConnectWrappe
 {
   if (!ObjectIsNativeWrapper(cx, obj)) {
     *_retval = JS_EnumerateStandardClasses(cx, obj);
   }
 
   return NS_OK;
 }
 
-static const char*
-FindConstructorContractID(const nsDOMClassInfoData *aDOMClassInfoData)
-{
-  PRUint32 i;
-  for (i = 0; i < ArrayLength(kConstructorMap); ++i) {
-    if (&sClassInfoData[kConstructorMap[i].mDOMClassInfoID] ==
-        aDOMClassInfoData) {
-      return kConstructorMap[i].mContractID;
-    }
-  }
-  return nullptr;
-}
-
 static nsDOMConstructorFunc
 FindConstructorFunc(const nsDOMClassInfoData *aDOMClassInfoData)
 {
   for (PRUint32 i = 0; i < ArrayLength(kConstructorFuncMap); ++i) {
     if (&sClassInfoData[kConstructorFuncMap[i].mDOMClassInfoID] ==
         aDOMClassInfoData) {
       return kConstructorFuncMap[i].mConstructorFunc;
     }
@@ -5673,28 +5659,21 @@ BaseStubConstructor(nsIWeakReference* aW
                     const nsGlobalNameStruct *name_struct, JSContext *cx,
                     JSObject *obj, unsigned argc, jsval *argv, jsval *rval)
 {
   nsresult rv;
   nsCOMPtr<nsISupports> native;
   if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     const nsDOMClassInfoData* ci_data =
       &sClassInfoData[name_struct->mDOMClassInfoID];
-    const char *contractid = FindConstructorContractID(ci_data);
-    if (contractid) {
-      native = do_CreateInstance(contractid, &rv);
-    }
-    else {
-      nsDOMConstructorFunc func = FindConstructorFunc(ci_data);
-      if (func) {
-        rv = func(getter_AddRefs(native));
-      }
-      else {
-        rv = NS_ERROR_NOT_AVAILABLE;
-      }
+    nsDOMConstructorFunc func = FindConstructorFunc(ci_data);
+    if (func) {
+      rv = func(getter_AddRefs(native));
+    } else {
+      rv = NS_ERROR_NOT_AVAILABLE;
     }
   } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     native = do_CreateInstance(name_struct->mCID, &rv);
   } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
     native = do_CreateInstance(name_struct->mAlias->mCID, &rv);
   } else {
     native = do_CreateInstance(*name_struct->mData->mConstructorCID, &rv);
   }
@@ -6097,17 +6076,17 @@ private:
   static bool IsConstructable(const nsDOMClassInfoData *aData)
   {
     if (IS_EXTERNAL(aData->mCachedClassInfo)) {
       const nsExternalDOMClassInfoData* data =
         static_cast<const nsExternalDOMClassInfoData*>(aData);
       return data->mConstructorCID != nullptr;
     }
 
-    return FindConstructorContractID(aData) || FindConstructorFunc(aData);
+    return FindConstructorFunc(aData);
   }
   static bool IsConstructable(const nsGlobalNameStruct *aNameStruct)
   {
     return
       (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
        IsConstructable(&sClassInfoData[aNameStruct->mDOMClassInfoID])) ||
       (aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo &&
        IsConstructable(aNameStruct->mData)) ||
@@ -6957,28 +6936,16 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
     rv = nameset->InitializeNameSet(context);
 
     *did_resolve = true;
   }
 
   return rv;
 }
 
-// Native code for window._content getter, this simply maps
-// window._content to window.content for backwards compatibility only.
-static JSBool
-ContentWindowGetter(JSContext *cx, unsigned argc, jsval *vp)
-{
-  JSObject *obj = JS_THIS_OBJECT(cx, vp);
-  if (!obj)
-    return JS_FALSE;
-
-  return ::JS_GetProperty(cx, obj, "content", vp);
-}
-
 static JSNewResolveOp sOtherResolveFuncs[] = {
   mozilla::dom::workers::ResolveWorkerClasses
 };
 
 template<class Interface>
 static nsresult
 LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
 {
@@ -7080,78 +7047,76 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       }
     }
 
     return NS_OK;
   }
 
   nsIScriptContext *my_context = win->GetContextInternal();
 
-  nsresult rv = NS_OK;
-
   // Resolve standard classes on my_context's JSContext (or on cx,
   // if we don't have a my_context yet), in case the two contexts
   // have different origins.  We want lazy standard class
   // initialization to behave as if it were done eagerly, on each
   // window's own context (not on some other window-caller's
   // context).
-
-  JSBool did_resolve = JS_FALSE;
-  JSContext *my_cx;
-
-  JSBool ok = JS_TRUE;
-  jsval exn = JSVAL_VOID;
   if (!ObjectIsNativeWrapper(cx, obj)) {
-    JSAutoEnterCompartment ac;
-
-    if (!my_context) {
-      my_cx = cx;
-    } else {
-      my_cx = my_context->GetNativeContext();
-
-      if (my_cx != cx) {
-        if (!ac.enter(my_cx, obj)) {
-          return NS_ERROR_UNEXPECTED;
+    JSBool did_resolve = JS_FALSE;
+    JSBool ok = JS_TRUE;
+    JS::Value exn = JSVAL_VOID;
+
+    {
+      JSAutoEnterCompartment ac;
+
+      JSContext* my_cx;
+      if (!my_context) {
+        my_cx = cx;
+      } else {
+        my_cx = my_context->GetNativeContext();
+
+        if (my_cx != cx) {
+          if (!ac.enter(my_cx, obj)) {
+            return NS_ERROR_UNEXPECTED;
+          }
         }
       }
-    }
-
-    JSAutoRequest transfer(my_cx);
-
-    // Don't resolve standard classes on XPCNativeWrapper etc, only
-    // resolve them if we're resolving on the real global object.
-    ok = JS_ResolveStandardClass(my_cx, obj, id, &did_resolve);
+
+      JSAutoRequest transfer(my_cx);
+
+      // Don't resolve standard classes on XPCNativeWrapper etc, only
+      // resolve them if we're resolving on the real global object.
+      ok = JS_ResolveStandardClass(my_cx, obj, id, &did_resolve);
+
+      if (!ok) {
+        // Trust the JS engine (or the script security manager) to set
+        // the exception in the JS engine.
+
+        if (!JS_GetPendingException(my_cx, &exn)) {
+          return NS_ERROR_UNEXPECTED;
+        }
+
+        // Return NS_OK to avoid stomping over the exception that was passed
+        // down from the ResolveStandardClass call.
+        // Note that the order of the JS_ClearPendingException and
+        // JS_SetPendingException is important in the case that my_cx == cx.
+
+        JS_ClearPendingException(my_cx);
+      }
+    }
 
     if (!ok) {
-      // Trust the JS engine (or the script security manager) to set
-      // the exception in the JS engine.
-
-      if (!JS_GetPendingException(my_cx, &exn)) {
-        return NS_ERROR_UNEXPECTED;
-      }
-
-      // Return NS_OK to avoid stomping over the exception that was passed
-      // down from the ResolveStandardClass call.
-      // Note that the order of the JS_ClearPendingException and
-      // JS_SetPendingException is important in the case that my_cx == cx.
-
-      JS_ClearPendingException(my_cx);
-    }
-  }
-
-  if (!ok) {
-    JS_SetPendingException(cx, exn);
-    *_retval = JS_FALSE;
-    return NS_OK;
-  }
-
-  if (did_resolve) {
-    *objp = obj;
-
-    return NS_OK;
+      JS_SetPendingException(cx, exn);
+      *_retval = JS_FALSE;
+      return NS_OK;
+    }
+
+    if (did_resolve) {
+      *objp = obj;
+      return NS_OK;
+    }
   }
 
   if (!(flags & JSRESOLVE_ASSIGNING)) {
     // We want this code to be before the child frame lookup code
     // below so that a child frame named 'constructor' doesn't
     // shadow the window's constructor property.
     if (sConstructor_id == id) {
       return ResolveConstructor(cx, obj, objp);
@@ -7160,16 +7125,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
 
   if (!my_context || !my_context->IsContextInitialized()) {
     // The context is not yet initialized so there's nothing we can do
     // here yet.
 
     return NS_OK;
   }
 
+  nsresult rv = NS_OK;
   if (sLocation_id == id) {
     // This must be done even if we're just getting the value of
     // window.location (i.e. no checking flags & JSRESOLVE_ASSIGNING
     // here) since we must define window.location to prevent the
     // getter from being overriden (for security reasons).
 
     // Note: Because we explicitly don't forward to the inner window
     // above, we have to ensure here that our window has a current
@@ -7301,46 +7267,16 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
     if (did_resolve) {
       // GlobalResolve() resolved something, so we're done here.
       *objp = obj;
 
       return NS_OK;
     }
   }
 
-  if (s_content_id == id) {
-    // Map window._content to window.content for backwards
-    // compatibility, this should spit out an message on the JS
-    // console.
-
-    JSObject *windowObj = win->GetGlobalJSObject();
-
-    JSAutoRequest ar(cx);
-
-    JSFunction *fun = ::JS_NewFunction(cx, ContentWindowGetter, 0, 0,
-                                       windowObj, "_content");
-    if (!fun) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    JSObject *funObj = ::JS_GetFunctionObject(fun);
-
-    if (!::JS_DefinePropertyById(cx, windowObj, id, JSVAL_VOID,
-                                 JS_DATA_TO_FUNC_PTR(JSPropertyOp, funObj),
-                                 nullptr,
-                                 JSPROP_ENUMERATE | JSPROP_GETTER |
-                                 JSPROP_SHARED)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    *objp = obj;
-
-    return NS_OK;
-  }
-
   if (flags & JSRESOLVE_ASSIGNING) {
     if (IsReadonlyReplaceable(id) ||
         (!(flags & JSRESOLVE_QUALIFIED) && IsWritableReplaceable(id))) {
       // A readonly "replaceable" property is being set, or a
       // readwrite "replaceable" property is being set w/o being
       // fully qualified. Define the property on obj with the value
       // undefined to override the predefined property. This is done
       // for compatibility with other browsers.
@@ -9060,25 +8996,26 @@ GetDocumentAllHelper(JSObject *obj)
   }
 
   return obj;
 }
 
 static inline void *
 FlagsToPrivate(PRUint32 flags)
 {
-  JS_ASSERT((flags & (1 << 31)) == 0);
-  return (void *)(flags << 1);
+  MOZ_ASSERT((flags & (1 << 31)) == 0);
+  return reinterpret_cast<void*>(static_cast<uintptr_t>(flags << 1));
 }
 
 static inline PRUint32
 PrivateToFlags(void *priv)
 {
-  JS_ASSERT(size_t(priv) <= PR_UINT32_MAX && (size_t(priv) & 1) == 0);
-  return (PRUint32)(size_t(priv) >> 1);
+  uintptr_t intPriv = reinterpret_cast<uintptr_t>(priv);
+  MOZ_ASSERT(intPriv <= PR_UINT32_MAX && (intPriv & 1) == 0);
+  return static_cast<PRUint32>(intPriv >> 1);
 }
 
 JSBool
 nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
                                                JSHandleId id, JSMutableHandleValue vp)
 {
   if (nsDOMClassInfo::sAll_id != id) {
     return JS_TRUE;
@@ -9573,24 +9510,28 @@ nsHTMLSelectElementSH::GetProperty(nsIXP
 // static
 nsresult
 nsHTMLSelectElementSH::SetOption(JSContext *cx, JS::Value *vp, PRUint32 aIndex,
                                  nsIDOMHTMLOptionsCollection *aOptCollection)
 {
   JSAutoRequest ar(cx);
 
   // vp must refer to an object
-  if (!vp->isObject()) {
+  if (!vp->isObjectOrNull()) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  nsCOMPtr<nsIDOMHTMLOptionElement> new_option = do_QueryWrapper(cx, &vp->toObject());
-  if (!new_option) {
-    // Someone is trying to set an option to a non-option object.
-    return NS_ERROR_UNEXPECTED;
+  nsCOMPtr<nsIDOMHTMLOptionElement> new_option;
+
+  if (JSObject* obj = vp->toObjectOrNull()) {
+    new_option = do_QueryWrapper(cx, obj);
+    if (!new_option) {
+      // Someone is trying to set an option to a non-option object.
+      return NS_ERROR_UNEXPECTED;
+    }
   }
 
   return aOptCollection->SetOption(aIndex, new_option);
 }
 
 NS_IMETHODIMP
 nsHTMLSelectElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
                                    JSContext *cx, JSObject *obj, jsid id,
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -152,17 +152,16 @@ protected:
   }
 
   virtual PRUint32 GetInterfacesBitmap()
   {
     return mData->mInterfacesBitmap;
   }
 
   static nsresult Init();
-  static nsresult RegisterClassName(PRInt32 aDOMClassInfoID);
   static nsresult RegisterClassProtos(PRInt32 aDOMClassInfoID);
   static nsresult RegisterExternalClasses();
   nsresult ResolveConstructor(JSContext *cx, JSObject *obj,
                               JSObject **objp);
 
   // Checks if id is a number and returns the number, if aIsNumber is
   // non-null it's set to true if the id is a number and false if it's
   // not a number. If id is not a number this method returns -1
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -36,16 +36,24 @@ nsDOMNavigationTiming::Clear()
   mLoadEventStart = 0;
   mLoadEventEnd = 0;
   mDOMLoading = 0;
   mDOMInteractive = 0;
   mDOMContentLoadedEventStart = 0;
   mDOMContentLoadedEventEnd = 0;
   mDOMComplete = 0;
   mRedirectCheck = NOT_CHECKED;
+
+  mLoadEventStartSet = false;
+  mLoadEventEndSet = false;
+  mDOMLoadingSet = false;
+  mDOMInteractiveSet = false;
+  mDOMContentLoadedEventStartSet = false;
+  mDOMContentLoadedEventEndSet = false;
+  mDOMCompleteSet = false;
 }
 
 DOMTimeMilliSec
 nsDOMNavigationTiming::TimeStampToDOM(mozilla::TimeStamp aStamp) const
 {
   if (aStamp.IsNull()) {
     return 0;
   }
@@ -123,23 +131,29 @@ void
 nsDOMNavigationTiming::NotifyUnloadEventEnd()
 {
   mUnloadEnd = DurationFromStart();
 }
 
 void
 nsDOMNavigationTiming::NotifyLoadEventStart()
 {
-  mLoadEventStart = DurationFromStart();
+  if (!mLoadEventStartSet) {
+    mLoadEventStart = DurationFromStart();
+    mLoadEventStartSet = true;
+  }
 }
 
 void
 nsDOMNavigationTiming::NotifyLoadEventEnd()
 {
-  mLoadEventEnd = DurationFromStart();
+  if (!mLoadEventEndSet) {
+    mLoadEventEnd = DurationFromStart();
+    mLoadEventEndSet = true;
+  }
 }
 
 bool
 nsDOMNavigationTiming::ReportRedirects()
 {
   if (mRedirectCheck == NOT_CHECKED) {
     mRedirectCount = mRedirects.Count();
     if (mRedirects.Count() == 0) {
@@ -161,53 +175,71 @@ nsDOMNavigationTiming::ReportRedirects()
     }
   }
   return mRedirectCheck == CHECK_PASSED;
 }
 
 void
 nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue)
 {
-  mLoadedURI = aURI;
-  mDOMLoading = TimeStampToDOM(aValue);
+  if (!mDOMLoadingSet) {
+    mLoadedURI = aURI;
+    mDOMLoading = TimeStampToDOM(aValue);
+    mDOMLoadingSet = true;
+  }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
 {
-  mLoadedURI = aURI;
-  mDOMLoading = DurationFromStart();
+  if (!mDOMLoadingSet) {
+    mLoadedURI = aURI;
+    mDOMLoading = DurationFromStart();
+    mDOMLoadingSet = true;
+  }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
 {
-  mLoadedURI = aURI;
-  mDOMInteractive = DurationFromStart();
+  if (!mDOMInteractiveSet) {
+    mLoadedURI = aURI;
+    mDOMInteractive = DurationFromStart();
+    mDOMInteractiveSet = true;
+  }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
 {
-  mLoadedURI = aURI;
-  mDOMComplete = DurationFromStart();
+  if (!mDOMCompleteSet) {
+    mLoadedURI = aURI;
+    mDOMComplete = DurationFromStart();
+    mDOMCompleteSet = true;
+  }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
 {
-  mLoadedURI = aURI;
-  mDOMContentLoadedEventStart = DurationFromStart();
+  if (!mDOMContentLoadedEventStartSet) {
+    mLoadedURI = aURI;
+    mDOMContentLoadedEventStart = DurationFromStart();
+    mDOMContentLoadedEventStartSet = true;
+  }
 }
 
 void
 nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
 {
-  mLoadedURI = aURI;
-  mDOMContentLoadedEventEnd = DurationFromStart();
+  if (!mDOMContentLoadedEventEndSet) {
+    mLoadedURI = aURI;
+    mDOMContentLoadedEventEnd = DurationFromStart();
+    mDOMContentLoadedEventEndSet = true;
+  }
 }
 
 PRUint16
 nsDOMNavigationTiming::GetRedirectCount()
 {
   if (ReportRedirects()) {
     return mRedirectCount;
   }
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -131,11 +131,22 @@ private:
   DOMTimeMilliSec mLoadEventStart;
   DOMTimeMilliSec mLoadEventEnd;
 
   DOMTimeMilliSec mDOMLoading;
   DOMTimeMilliSec mDOMInteractive;
   DOMTimeMilliSec mDOMContentLoadedEventStart;
   DOMTimeMilliSec mDOMContentLoadedEventEnd;
   DOMTimeMilliSec mDOMComplete;
+
+  // Booleans to keep track of what things we've already been notified
+  // about.  We don't update those once we've been notified about them
+  // once.
+  bool mLoadEventStartSet : 1;
+  bool mLoadEventEndSet : 1;
+  bool mDOMLoadingSet : 1;
+  bool mDOMInteractiveSet : 1;
+  bool mDOMContentLoadedEventStartSet : 1;
+  bool mDOMContentLoadedEventEndSet : 1;
+  bool mDOMCompleteSet : 1;
 };
 
 #endif /* nsDOMNavigationTiming_h___ */
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1001,17 +1001,17 @@ nsDOMWindowUtils::CycleCollect(nsICycleC
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendSimpleGestureEvent(const nsAString& aType,
                                          float aX,
                                          float aY,
                                          PRUint32 aDirection,
-                                         PRFloat64 aDelta,
+                                         double aDelta,
                                          PRInt32 aModifiers,
                                          PRUint32 aClickCount)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   // get the widget to send the event to
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1951,16 +1951,27 @@ nsGlobalWindow::SetNewDocument(nsIDocume
         // Move the navigator from the old inner window to the new one since
         // this is a document.write. This is safe from a same-origin point of
         // view because document.write can only be used by the same origin.
         newInnerWindow->mNavigator = currentInner->mNavigator;
         currentInner->mNavigator = nullptr;
         if (newInnerWindow->mNavigator) {
           newInnerWindow->mNavigator->SetWindow(newInnerWindow);
         }
+
+        // Make a copy of the old window's performance object on document.open.
+        // Note that we have to force eager creation of it here, because we need
+        // to grab the current document channel and whatnot before that changes.
+        currentInner->CreatePerformanceObjectIfNeeded();
+        if (currentInner->mPerformance) {
+          newInnerWindow->mPerformance =
+            new nsPerformance(newInnerWindow,
+                              currentInner->mPerformance->GetDOMTiming(),
+                              currentInner->mPerformance->GetChannel());
+        }
       }
 
       // Don't free objects on our current inner window if it's going to be
       // held in the bfcache.
       if (!currentInner->IsFrozen()) {
         currentInner->FreeInnerObjects();
       }
     }
@@ -2926,37 +2937,41 @@ nsGlobalWindow::GetHistory(nsIDOMHistory
 NS_IMETHODIMP
 nsGlobalWindow::GetPerformance(nsISupports** aPerformance)
 {
   FORWARD_TO_INNER(GetPerformance, (aPerformance), NS_ERROR_NOT_INITIALIZED);
 
   *aPerformance = nullptr;
 
   if (nsGlobalWindow::HasPerformanceSupport()) {
-    if (!mPerformance) {
-      if (!mDoc) {
-        return NS_OK;
-      }
-      nsRefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
-      nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
-      bool timingEnabled = false;
-      if (!timedChannel ||
-          !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
-          !timingEnabled) {
-        timedChannel = nullptr;
-      }
-      if (timing) {
-        mPerformance = new nsPerformance(this, timing, timedChannel);
-      }
-    }
+    CreatePerformanceObjectIfNeeded();
     NS_IF_ADDREF(*aPerformance = mPerformance);
   }
   return NS_OK;
 }
 
+void
+nsGlobalWindow::CreatePerformanceObjectIfNeeded()
+{
+  if (mPerformance || !mDoc) {
+    return;
+  }
+  nsRefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
+  nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
+  bool timingEnabled = false;
+  if (!timedChannel ||
+      !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
+      !timingEnabled) {
+    timedChannel = nullptr;
+  }
+  if (timing) {
+    mPerformance = new nsPerformance(this, timing, timedChannel);
+  }
+}
+
 /**
  * GetScriptableParent is called when script reads window.parent.
  *
  * In contrast to GetRealParent, GetScriptableParent respects <iframe
  * mozbrowser> boundaries, so if |this| is contained by an <iframe
  * mozbrowser>, we will return |this| as its own parent.
  */
 NS_IMETHODIMP
@@ -3065,16 +3080,24 @@ nsGlobalWindow::GetTopImpl(nsIDOMWindow*
 
   if (parent) {
     parent.swap(*aTop);
   }
 
   return NS_OK;
 }
 
+// Map window._content to window.content for backwards compatibility, this
+// should spit out an message on the JS console.
+NS_IMETHODIMP
+nsGlobalWindow::GetContentForCompat(nsIDOMWindow** aContent)
+{
+  return GetContent(aContent);
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::GetContent(nsIDOMWindow** aContent)
 {
   FORWARD_TO_OUTER(GetContent, (aContent), NS_ERROR_NOT_INITIALIZED);
   *aContent = nullptr;
 
   // If we're contained in <iframe mozbrowser>, then GetContent is the same as
   // window.top.
@@ -3109,17 +3132,17 @@ nsGlobalWindow::GetContent(nsIDOMWindow*
     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
     GetTreeOwner(getter_AddRefs(treeOwner));
     NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
 
     treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));
   }
 
   nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(primaryContent));
-  NS_IF_ADDREF(*aContent = domWindow);
+  domWindow.forget(aContent);
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt)
 {
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -900,16 +900,19 @@ protected:
 
   void SetIsApp(bool aValue);
   nsresult SetApp(const nsAString& aManifestURL);
   nsresult GetApp(mozIDOMApplication** aApplication);
 
   // Implements Get{Real,Scriptable}Top.
   nsresult GetTopImpl(nsIDOMWindow **aWindow, bool aScriptable);
 
+  // Helper for creating performance objects.
+  void CreatePerformanceObjectIfNeeded();
+
   // When adding new member variables, be careful not to create cycles
   // through JavaScript.  If there is any chance that a member variable
   // could own objects that are implemented in JavaScript, then those
   // objects will keep the global object (this object) alive.  To prevent
   // these cycles, ownership of such members must be released in
   // |CleanUp| and |DetachFromDocShell|.
 
   // This member is also used on both inner and outer windows, but
@@ -985,16 +988,17 @@ protected:
   nsCOMPtr<nsIScriptContext>    mContext;
   nsWeakPtr                     mOpener;
   nsCOMPtr<nsIControllers>      mControllers;
   nsCOMPtr<nsIArray>            mArguments;
   nsCOMPtr<nsIArray>            mArgumentsLast;
   nsCOMPtr<nsIPrincipal>        mArgumentsOrigin;
   nsRefPtr<Navigator>           mNavigator;
   nsRefPtr<nsScreen>            mScreen;
+  // mPerformance is only used on inner windows.
   nsRefPtr<nsPerformance>       mPerformance;
   nsRefPtr<nsDOMWindowList>     mFrames;
   nsRefPtr<nsBarProp>           mMenubar;
   nsRefPtr<nsBarProp>           mToolbar;
   nsRefPtr<nsBarProp>           mLocationbar;
   nsRefPtr<nsBarProp>           mPersonalbar;
   nsRefPtr<nsBarProp>           mStatusbar;
   nsRefPtr<nsBarProp>           mScrollbars;
--- a/dom/base/nsPerformance.h
+++ b/dom/base/nsPerformance.h
@@ -135,16 +135,21 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPerformance)
 
   nsDOMNavigationTiming* GetDOMTiming() const
   {
     return mDOMTiming;
   }
 
+  nsITimedChannel* GetChannel() const
+  {
+    return mChannel;
+  }
+
   nsIDOMWindow* GetParentObject() const
   {
     return mWindow.get();
   }
 
   JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
 
   // Performance WebIDL methods
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -59,17 +59,17 @@ template<typename T,
          JSObject* CreateNew(JSContext*, uint32_t)>
 struct TypedArray : public TypedArray_base<T,UnboxArray> {
   TypedArray(JSContext* cx, JSObject* obj) :
     TypedArray_base<T,UnboxArray>(cx, obj)
   {}
 
   static inline JSObject*
   Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
-         T* data = NULL) {
+         const T* data = NULL) {
     JSObject* creatorWrapper;
     JSAutoEnterCompartment ac;
     if (creator && (creatorWrapper = creator->GetWrapperPreserveColor())) {
       if (!ac.enter(cx, creatorWrapper)) {
         return NULL;
       }
     }
     JSObject* obj = CreateNew(cx, length);
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -57,24 +57,28 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
   NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 
-BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aOwner, const nsAString& aPath)
+BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue)
     : BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
     , mJsUuids(nullptr)
     , mJsDeviceAddresses(nullptr)
     , mIsRooted(false)
 {
   BindToOwner(aOwner);
-  mPath = aPath;
+  const InfallibleTArray<BluetoothNamedValue>& values =
+    aValue.get_ArrayOfBluetoothNamedValue();
+  for (uint32_t i = 0; i < values.Length(); ++i) {
+    SetPropertyByValue(values[i]);
+  }
 }
 
 BluetoothAdapter::~BluetoothAdapter()
 {
   BluetoothService* bs = BluetoothService::Get();
   // We can be null on shutdown, where this might happen
   if (bs) {
     if (NS_FAILED(bs->UnregisterBluetoothSignalHandler(mPath, this))) {
@@ -170,31 +174,26 @@ BluetoothAdapter::SetPropertyByValue(con
     warningMsg.Append(NS_ConvertUTF16toUTF8(name));
     NS_WARNING(warningMsg.get());
 #endif
   }
 }
 
 // static
 already_AddRefed<BluetoothAdapter>
-BluetoothAdapter::Create(nsPIDOMWindow* aOwner, const nsAString& aPath)
+BluetoothAdapter::Create(nsPIDOMWindow* aOwner, const BluetoothValue& aValue)
 {
-  // Make sure we at least have a path
-  NS_ASSERTION(!aPath.IsEmpty(), "Adapter created with empty path!");
-    
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return nullptr;
   }
 
-  nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aOwner, aPath);
-  nsString path;
-  path = adapter->GetPath();
-  if (NS_FAILED(bs->RegisterBluetoothSignalHandler(path, adapter))) {
+  nsRefPtr<BluetoothAdapter> adapter = new BluetoothAdapter(aOwner, aValue);
+  if (NS_FAILED(bs->RegisterBluetoothSignalHandler(adapter->GetPath(), adapter))) {
     NS_WARNING("Failed to register object with observer!");
     return nullptr;
   }
   return adapter.forget();
 }
 
 void
 BluetoothAdapter::Notify(const BluetoothSignal& aData)
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -15,33 +15,34 @@
 
 class nsIEventTarget;
 class nsIDOMDOMRequest;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothSignal;
 class BluetoothNamedValue;
+class BluetoothValue;
 
 class BluetoothAdapter : public nsDOMEventTargetHelper
                        , public nsIDOMBluetoothAdapter
                        , public BluetoothSignalObserver
                        , public BluetoothPropertyContainer
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMBLUETOOTHADAPTER
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(BluetoothAdapter,
                                                          nsDOMEventTargetHelper)
 
   static already_AddRefed<BluetoothAdapter>
-  Create(nsPIDOMWindow* aOwner, const nsAString& name);
+  Create(nsPIDOMWindow* aOwner, const BluetoothValue& aValue);
 
   void Notify(const BluetoothSignal& aParam);
 
   nsIDOMEventTarget*
   ToIDOMEventTarget() const
   {
     return static_cast<nsDOMEventTargetHelper*>(
       const_cast<BluetoothAdapter*>(this));
@@ -52,17 +53,17 @@ public:
   {
     return ToIDOMEventTarget();
   }
 
   void Unroot();
   virtual void SetPropertyByValue(const BluetoothNamedValue& aValue);  
 private:
   
-  BluetoothAdapter(nsPIDOMWindow* aOwner, const nsAString& aPath);
+  BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue);
   ~BluetoothAdapter();
 
   void Root();
   nsresult StartStopDiscovery(bool aStart, nsIDOMDOMRequest** aRequest);
   
   nsString mAddress;
   nsString mName;
   bool mEnabled;
--- a/dom/bluetooth/BluetoothManager.cpp
+++ b/dom/bluetooth/BluetoothManager.cpp
@@ -59,20 +59,19 @@ public:
   }
 
   bool
   ParseSuccessfulReply(jsval* aValue)
   {
     nsCOMPtr<nsIDOMBluetoothAdapter> adapter;
     *aValue = JSVAL_VOID;
 
-    const nsString& path =
-      mReply->get_BluetoothReplySuccess().value().get_nsString();
-    adapter = BluetoothAdapter::Create(mManagerPtr->GetOwner(),
-                                       path);
+    const InfallibleTArray<BluetoothNamedValue>& v =
+      mReply->get_BluetoothReplySuccess().value().get_ArrayOfBluetoothNamedValue();
+    adapter = BluetoothAdapter::Create(mManagerPtr->GetOwner(), v);
 
     nsresult rv;
     nsIScriptContext* sc = mManagerPtr->GetContextForEventHandlers(&rv);
     if (!sc) {
       NS_WARNING("Cannot create script context!");
       SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
       return false;
     }
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -17,44 +17,47 @@
 #include "mozilla/Services.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Util.h"
 
 using namespace mozilla;
 
 USING_BLUETOOTH_NAMESPACE
 
-nsRefPtr<BluetoothService> gBluetoothService;
-nsCOMPtr<nsIThread> gToggleBtThread;
-int gPendingInitCount = 0;
-bool gInShutdown = false;
+static nsRefPtr<BluetoothService> gBluetoothService;
+static bool gInShutdown = false;
 
 NS_IMPL_ISUPPORTS1(BluetoothService, nsIObserver)
 
 class ToggleBtAck : public nsRunnable
 {
 public:
+  ToggleBtAck(bool aEnabled) :
+    mEnabled(aEnabled)
+  {
+  }
+  
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
-    gPendingInitCount--;
-    
-    if (gPendingInitCount) {
-      return NS_OK;
+
+    if (!mEnabled || gInShutdown) {
+      nsCOMPtr<nsIThread> t;
+      gBluetoothService->mBluetoothCommandThread.swap(t);
+      t->Shutdown();
     }
     
     if (gInShutdown) {
       gBluetoothService = nullptr;
     }
 
-    nsCOMPtr<nsIThread> t;
-    gToggleBtThread.swap(t);
-    t->Shutdown();
     return NS_OK;
   }
+
+  bool mEnabled;
 };
 
 class ToggleBtTask : public nsRunnable
 {
 public:
   ToggleBtTask(bool aEnabled,
                BluetoothReplyRunnable* aRunnable)
     : mEnabled(aEnabled),
@@ -77,17 +80,17 @@ public:
       if (NS_FAILED(gBluetoothService->StopInternal())) {        
         replyError.AssignLiteral("Bluetooth service not available - We should never reach this point!");
       }
     }
 
     // Always has to be called since this is where we take care of our reference
     // count for runnables. If there's an error, replyError won't be empty, so
     // consider our status flipped.
-    nsCOMPtr<nsIRunnable> ackTask = new ToggleBtAck();
+    nsCOMPtr<nsIRunnable> ackTask = new ToggleBtAck(mEnabled);
     if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
     
     if (!mRunnable) {
       return NS_OK;
     }
     
@@ -163,27 +166,26 @@ BluetoothService::StartStopBluetooth(Blu
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // If we're shutting down, bail early.
   if (gInShutdown && aStart) {
     NS_ERROR("Start called while in shutdown!");
     return NS_ERROR_FAILURE;
   }
-  if (!gToggleBtThread) {
-    nsresult rv = NS_NewNamedThread("BluetoothCtrl",
-                                    getter_AddRefs(gToggleBtThread));
+  if (!mBluetoothCommandThread) {
+    nsresult rv = NS_NewNamedThread("BluetoothCmd",
+                                    getter_AddRefs(mBluetoothCommandThread));
     NS_ENSURE_SUCCESS(rv, rv);
   }
   nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aStart, aResultRunnable);
-  if (NS_FAILED(gToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL))) {
+  if (NS_FAILED(mBluetoothCommandThread->Dispatch(r, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Cannot dispatch firmware loading task!");
     return NS_ERROR_FAILURE;
   }
-  gPendingInitCount++;
   return NS_OK;
 }
 
 nsresult
 BluetoothService::Start(BluetoothReplyRunnable* aResultRunnable)
 {
   return StartStopBluetooth(aResultRunnable, true);
 }
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -187,16 +187,29 @@ public:
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath) = 0;
 
   virtual int
   GetDeviceServiceChannelInternal(const nsAString& aObjectPath,
                                   const nsAString& aPattern,
                                   int aAttributeId) = 0;
 
+  /**
+   * Due to the fact that some operations require multiple calls, a
+   * CommandThread is created that can run blocking, platform-specific calls
+   * where either no asynchronous equivilent exists, or else where multiple
+   * asynchronous calls would require excessive runnable bouncing between main
+   * thread and IO thread.
+   *
+   * For instance, when we retrieve an Adapter object, we would like it to come
+   * with all of its properties filled in and registered as an agent, which
+   * requires a minimum of 3 calls to platform specific code on some platforms.
+   *
+   */
+  nsCOMPtr<nsIThread> mBluetoothCommandThread;
 protected:
   BluetoothService()
   {
     mBluetoothSignalObserverTable.Init();
   }
 
   virtual ~BluetoothService()
   {
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -122,16 +122,23 @@ static const char* sBluetoothDBusSignals
   "type='signal',interface='org.bluez.Device'",
   "type='signal',interface='org.bluez.Input'",
   "type='signal',interface='org.bluez.Network'",
   "type='signal',interface='org.bluez.NetworkServer'",
   "type='signal',interface='org.bluez.HealthDevice'",
   "type='signal',interface='org.bluez.AudioSink'"
 };
 
+/**
+ * DBus Connection held for the BluetoothCommandThread to use. Should never be
+ * used by any other thread.
+ * 
+ */
+static nsAutoPtr<RawDBusConnection> gThreadConnection;
+
 class DistributeBluetoothSignalTask : public nsRunnable {
   BluetoothSignal mSignal;
 public:
   DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
     mSignal(aSignal)
   {
   }
 
@@ -144,125 +151,135 @@ public:
       NS_WARNING("BluetoothService not available!");
       return NS_ERROR_FAILURE;
     }    
     return bs->DistributeSignal(mSignal);
   }  
 };
 
 bool
-IsDBusMessageError(DBusMessage* aMsg, nsAString& aError)
+IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
 {
+  if(aErr && dbus_error_is_set(aErr)) {
+    aErrorStr = NS_ConvertUTF8toUTF16(aErr->message);
+    LOG_AND_FREE_DBUS_ERROR(aErr);
+    return true;
+  }
+  
   DBusError err;
   dbus_error_init(&err);
   if (dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_ERROR) {
     const char* error_msg;
     if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_STRING,
                                &error_msg, DBUS_TYPE_INVALID) ||
         !error_msg) {
       if (dbus_error_is_set(&err)) {
-        aError = NS_ConvertUTF8toUTF16(err.message);
+        aErrorStr = NS_ConvertUTF8toUTF16(err.message);
         LOG_AND_FREE_DBUS_ERROR(&err);
         return true;
+      } else {
+        aErrorStr.AssignLiteral("Unknown Error");
+        return true;
       }
     } else {
-      aError = NS_ConvertUTF8toUTF16(error_msg);
+      aErrorStr = NS_ConvertUTF8toUTF16(error_msg);
       return true;
     }
   }
   return false;
 }
 
 void
 DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
-                       const BluetoothValue& aValue, const nsAString& aError)
+                       const BluetoothValue& aValue, const nsAString& aErrorStr)
 {
   // Reply will be deleted by the runnable after running on main thread
   BluetoothReply* reply;
-  if (!aError.IsEmpty()) {
-    nsString err(aError);
+  if (!aErrorStr.IsEmpty()) {
+    nsString err(aErrorStr);
     reply = new BluetoothReply(BluetoothReplyError(err));
-  }
-  else {
+  } else {
     reply = new BluetoothReply(BluetoothReplySuccess(aValue));
   }
   
   aRunnable->SetReply(reply);
   if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
     NS_WARNING("Failed to dispatch to main thread!");
   }
 }
 
 void
-UnpackObjectPathMessage(DBusMessage* aMsg, BluetoothValue& aValue,
-                        nsAString& aErrorStr)
+UnpackObjectPathMessage(DBusMessage* aMsg, DBusError* aErr,
+                        BluetoothValue& aValue, nsAString& aErrorStr)
 {
   DBusError err;
   dbus_error_init(&err);
-  if (!IsDBusMessageError(aMsg, aErrorStr)) {
+  if (!IsDBusMessageError(aMsg, aErr, aErrorStr)) {
     NS_ASSERTION(dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN,
                  "Got dbus callback that's not a METHOD_RETURN!");
     const char* object_path;
     if (!dbus_message_get_args(aMsg, &err, DBUS_TYPE_OBJECT_PATH,
                                &object_path, DBUS_TYPE_INVALID) ||
         !object_path) {
       if (dbus_error_is_set(&err)) {
         aErrorStr = NS_ConvertUTF8toUTF16(err.message);
         LOG_AND_FREE_DBUS_ERROR(&err);
       }
     } else {
       aValue = NS_ConvertUTF8toUTF16(object_path);
     }
   }
 }
 
-typedef void (*UnpackFunc)(DBusMessage*, BluetoothValue&, nsAString&);
+typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
 
 void
 RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
                 UnpackFunc aFunc)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   nsRefPtr<BluetoothReplyRunnable> replyRunnable =
     dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
 
   NS_ASSERTION(replyRunnable, "Callback reply runnable is null!");
 
   nsString replyError;
   BluetoothValue v;
-  aFunc(aMsg, v, replyError);
+  aFunc(aMsg, nsnull, v, replyError);
   DispatchBluetoothReply(replyRunnable, v, replyError);  
 }
 
 void
 GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
 {
-  RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackObjectPathMessage);
+  RunDBusCallback(aMsg, aBluetoothReplyRunnable,
+                  UnpackObjectPathMessage);
 }
 
 void
-UnpackVoidMessage(DBusMessage* aMsg, BluetoothValue& aValue,
+UnpackVoidMessage(DBusMessage* aMsg, DBusError* aErr, BluetoothValue& aValue,
                   nsAString& aErrorStr)
 {
   DBusError err;
   dbus_error_init(&err);
-  if (!IsDBusMessageError(aMsg, aErrorStr) &&
+  if (!IsDBusMessageError(aMsg, aErr, aErrorStr) &&
       dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN &&
       !dbus_message_get_args(aMsg, &err, DBUS_TYPE_INVALID)) {
     if (dbus_error_is_set(&err)) {
       aErrorStr = NS_ConvertUTF8toUTF16(err.message);
       LOG_AND_FREE_DBUS_ERROR(&err);
     }
   }
 }
 
 void
 GetVoidCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
 {
-  RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackVoidMessage);
+  RunDBusCallback(aMsg, aBluetoothReplyRunnable,
+                  UnpackVoidMessage);
 }
 
 bool
 GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
             int aPropertyTypeLen, int* aPropIndex,
             InfallibleTArray<BluetoothNamedValue>& aProperties)
 {
   DBusMessageIter prop_val, array_val_iter;
@@ -376,72 +393,83 @@ ParseProperties(DBusMessageIter* aIter,
       NS_WARNING("Can't create property!");
       return;
     }
   } while (dbus_message_iter_next(&dict));
 
   aValue = props;
 }
 
-void UnpackPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
-                             nsAString& aErrorStr, Properties* aPropertyTypes,
-                             const int aPropertyTypeLen)
+void
+UnpackPropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
+                        BluetoothValue& aValue, nsAString& aErrorStr,
+                        Properties* aPropertyTypes,
+                        const int aPropertyTypeLen)
 {
-  if (!IsDBusMessageError(aMsg, aErrorStr) &&
+  if (!IsDBusMessageError(aMsg, aErr, aErrorStr) &&
       dbus_message_get_type(aMsg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
     DBusMessageIter iter;
     if (!dbus_message_iter_init(aMsg, &iter)) {
       aErrorStr.AssignLiteral("Cannot create dbus message iter!");
     } else {
       ParseProperties(&iter, aValue, aErrorStr, aPropertyTypes,
                       aPropertyTypeLen);
     }
   }
 }
 
-void UnpackAdapterPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
-                                    nsAString& aErrorStr)
+void
+UnpackAdapterPropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
+                               BluetoothValue& aValue,
+                               nsAString& aErrorStr)
 {
-  UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
+  UnpackPropertiesMessage(aMsg, aErr, aValue, aErrorStr,
                           sAdapterProperties,
                           ArrayLength(sAdapterProperties));
 }
 
-void UnpackDevicePropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
-                                    nsAString& aErrorStr)
+void
+UnpackDevicePropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
+                              BluetoothValue& aValue,
+                              nsAString& aErrorStr)
 {
-  UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
+  UnpackPropertiesMessage(aMsg, aErr, aValue, aErrorStr,
                           sDeviceProperties,
                           ArrayLength(sDeviceProperties));
 }
 
-void UnpackManagerPropertiesMessage(DBusMessage* aMsg, BluetoothValue& aValue,
-                                    nsAString& aErrorStr)
+void
+UnpackManagerPropertiesMessage(DBusMessage* aMsg, DBusError* aErr,
+                               BluetoothValue& aValue,
+                               nsAString& aErrorStr)
 {
-  UnpackPropertiesMessage(aMsg, aValue, aErrorStr,
+  UnpackPropertiesMessage(aMsg, aErr, aValue, aErrorStr,
                           sManagerProperties,
                           ArrayLength(sManagerProperties));
 }
 
 void
 GetManagerPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
 {
-  RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackManagerPropertiesMessage);
+  RunDBusCallback(aMsg, aBluetoothReplyRunnable,
+                  UnpackManagerPropertiesMessage);
 }
 
 void
 GetAdapterPropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
 {
-  RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackAdapterPropertiesMessage);
+  RunDBusCallback(aMsg, aBluetoothReplyRunnable,
+                  UnpackAdapterPropertiesMessage);
 }
 
 void
 GetDevicePropertiesCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
 {
-  RunDBusCallback(aMsg, aBluetoothReplyRunnable, UnpackDevicePropertiesMessage);
+  RunDBusCallback(aMsg, aBluetoothReplyRunnable,
+                  UnpackDevicePropertiesMessage);
 }
 
 static DBusCallback sBluetoothDBusPropCallbacks[] =
 {
   GetManagerPropertiesCallback,
   GetAdapterPropertiesCallback,
   GetDevicePropertiesCallback
 };
@@ -606,17 +634,25 @@ BluetoothDBusService::StartInternal()
     return NS_ERROR_FAILURE;
   }
   
   if (mConnection) {
     return NS_OK;
   }
 
   if (NS_FAILED(EstablishDBusConnection())) {
-    NS_WARNING("Cannot start DBus connection!");
+    NS_WARNING("Cannot start Main Thread DBus connection!");
+    StopDBus();
+    return NS_ERROR_FAILURE;
+  }
+
+  gThreadConnection = new RawDBusConnection();
+  
+  if (NS_FAILED(gThreadConnection->EstablishDBusConnection())) {
+    NS_WARNING("Cannot start Sync Thread DBus connection!");
     StopDBus();
     return NS_ERROR_FAILURE;
   }
 
   DBusError err;
   dbus_error_init(&err);
 
   // Set which messages will be processed by this dbus connection.
@@ -662,43 +698,105 @@ BluetoothDBusService::StopInternal()
     if (dbus_error_is_set(&err)) {
       LOG_AND_FREE_DBUS_ERROR(&err);
     }
   }
 
   dbus_connection_remove_filter(mConnection, EventFilter, nullptr);
   
   mConnection = nullptr;
+  gThreadConnection = nullptr;
   mBluetoothSignalObserverTable.Clear();
   StopDBus();
   return NS_OK;
 }
 
+class DefaultAdapterPropertiesRunnable : public nsRunnable
+{
+public:
+  DefaultAdapterPropertiesRunnable(BluetoothReplyRunnable* aRunnable)
+    : mRunnable(dont_AddRef(aRunnable))
+  {
+  }
+
+  nsresult
+  Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+    DBusError err;
+    dbus_error_init(&err);
+   
+    BluetoothValue v;
+    nsString replyError;
+
+    DBusMessage* msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
+                                              1000,
+                                              &err,
+                                              "/",
+                                              DBUS_MANAGER_IFACE,
+                                              "DefaultAdapter",
+                                              DBUS_TYPE_INVALID);
+    UnpackObjectPathMessage(msg, &err, v, replyError);
+    if(msg) {
+      dbus_message_unref(msg);
+    }
+    if(!replyError.IsEmpty()) {
+      DispatchBluetoothReply(mRunnable, v, replyError);
+      return NS_ERROR_FAILURE;
+    }
+
+    nsString path = v.get_nsString();
+    nsCString tmp_path = NS_ConvertUTF16toUTF8(path);
+    const char* object_path = tmp_path.get();
+   
+    v = InfallibleTArray<BluetoothNamedValue>();
+    msg = dbus_func_args_timeout(gThreadConnection->GetConnection(),
+                                 1000,
+                                 &err,
+                                 object_path,
+                                 "org.bluez.Adapter",
+                                 "GetProperties",
+                                 DBUS_TYPE_INVALID);
+    UnpackAdapterPropertiesMessage(msg, &err, v, replyError);
+   
+    if(!replyError.IsEmpty()) {
+      DispatchBluetoothReply(mRunnable, v, replyError);
+      return NS_ERROR_FAILURE;
+    }
+    if(msg) {
+      dbus_message_unref(msg);
+    }
+    // We have to manually attach the path to the rest of the elements
+    v.get_ArrayOfBluetoothNamedValue().AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Path"),
+                                                                         path));
+    DispatchBluetoothReply(mRunnable, v, replyError);
+   
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<BluetoothReplyRunnable> mRunnable;
+};
+
 nsresult
 BluetoothDBusService::GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable)
 {
-  if (!mConnection) {
+  if (!mConnection || !gThreadConnection) {
     NS_ERROR("Bluetooth service not started yet!");
     return NS_ERROR_FAILURE;
   }
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
-
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
-  if (!dbus_func_args_async(mConnection,
-                            1000,
-                            GetObjectPathCallback,
-                            (void*)aRunnable,
-                            "/",
-                            "org.bluez.Manager",
-                            "DefaultAdapter",
-                            DBUS_TYPE_INVALID)) {
-    NS_WARNING("Could not start async function!");
+  nsRefPtr<nsRunnable> func(new DefaultAdapterPropertiesRunnable(runnable));
+  if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Cannot dispatch firmware loading task!");
     return NS_ERROR_FAILURE;
   }
+
   runnable.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::SendDiscoveryMessage(const nsAString& aAdapterPath,
                                            const char* aMessageName,
                                            BluetoothReplyRunnable* aRunnable)
--- a/dom/browser-element/BrowserElementScrolling.js
+++ b/dom/browser-element/BrowserElementScrolling.js
@@ -4,16 +4,17 @@
 
 const ContentPanning = {
   init: function cp_init() {
     ['mousedown', 'mouseup', 'mousemove'].forEach(function(type) {
       addEventListener(type, ContentPanning, true);
     });
 
     addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
+    addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
   },
 
   handleEvent: function cp_handleEvent(evt) {
     switch (evt.type) {
       case 'mousedown':
         this.onTouchStart(evt);
         break;
       case 'mousemove':
@@ -38,16 +39,26 @@ const ContentPanning = {
 
   onTouchStart: function cp_onTouchStart(evt) {
     this.dragging = true;
     this.panning = false;
 
     let oldTarget = this.target;
     [this.target, this.scrollCallback] = this.getPannable(evt.target);
 
+    // If we found a target, that means we have found a scrollable subframe. In
+    // this case, and if we are using async panning and zooming on the parent
+    // frame, inform the pan/zoom controller that it should not attempt to
+    // handle any touch events it gets until the next batch (meaning the next
+    // time we get a touch end).
+    if (this.target != null && ContentPanning._asyncPanZoomForViewportFrame) {
+      var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+      os.notifyObservers(docShell, 'cancel-default-pan-zoom', null);
+    }
+
     // If there is a pan animation running (from a previous pan gesture) and
     // the user touch back the screen, stop this animation immediatly and
     // prevent the possible click action if the touch happens on the same
     // target.
     this.preventNextClick = false;
     if (KineticPanning.active) {
       KineticPanning.stop();
 
@@ -185,42 +196,158 @@ const ContentPanning = {
     this._domUtils.setContentState(root.documentElement, kStateActive);
   },
 
   get _asyncPanZoomForViewportFrame() {
     return docShell.asyncPanZoomEnabled;
   },
 
   _recvViewportChange: function(data) {
-    let viewport = data.json;
-    let displayPort = viewport.displayPort;
+    let metrics = data.json;
+    let displayPort = metrics.displayPort;
+
+    let screenWidth = metrics.screenSize.width;
+    let screenHeight = metrics.screenSize.height;
+
+    let x = metrics.x;
+    let y = metrics.y;
 
-    let screenWidth = viewport.screenSize.width;
-    let screenHeight = viewport.screenSize.height;
-
-    let x = viewport.x;
-    let y = viewport.y;
+    this._zoom = metrics.zoom;
+    this._viewport = new Rect(x, y,
+                              screenWidth / metrics.zoom,
+                              screenHeight / metrics.zoom);
+    this._cssPageRect = new Rect(metrics.cssPageRect.x,
+                                 metrics.cssPageRect.y,
+                                 metrics.cssPageRect.width,
+                                 metrics.cssPageRect.height);
 
     let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
-    cwu.setCSSViewport(screenWidth, screenHeight);
+    if (this._screenWidth != screenWidth || this._screenHeight != screenHeight) {
+      cwu.setCSSViewport(screenWidth, screenHeight);
+      this._screenWidth = screenWidth;
+      this._screenHeight = screenHeight;
+    }
 
     // Set scroll position
     cwu.setScrollPositionClampingScrollPortSize(
-      screenWidth / viewport.zoom, screenHeight / viewport.zoom);
+      screenWidth / metrics.zoom, screenHeight / metrics.zoom);
     content.scrollTo(x, y);
     cwu.setResolution(displayPort.resolution, displayPort.resolution);
 
     let element = null;
     if (content.document && (element = content.document.documentElement)) {
       cwu.setDisplayPortForElement(displayPort.left,
                                    displayPort.top,
                                    displayPort.width,
                                    displayPort.height,
                                    element);
     }
+  },
+
+  _recvDoubleTap: function(data) {
+    let data = data.json;
+
+    // We haven't received a metrics update yet; don't do anything.
+    if (this._viewport == null) {
+      return;
+    }
+
+    let win = content;
+
+    let zoom = this._zoom;
+    let element = ElementTouchHelper.anyElementFromPoint(win, data.x, data.y);
+    if (!element) {
+      this._zoomOut();
+      return;
+    }
+
+    while (element && !this._shouldZoomToElement(element))
+      element = element.parentNode;
+
+    if (!element) {
+      this._zoomOut();
+    } else {
+      const margin = 15;
+      let rect = ElementTouchHelper.getBoundingContentRect(element);
+
+      let cssPageRect = this._cssPageRect;
+      let viewport = this._viewport;
+      let bRect = new Rect(Math.max(cssPageRect.left, rect.x - margin),
+                           rect.y,
+                           rect.w + 2 * margin,
+                           rect.h);
+      // constrict the rect to the screen's right edge
+      bRect.width = Math.min(bRect.width, cssPageRect.right - bRect.x);
+
+      // if the rect is already taking up most of the visible area and is stretching the
+      // width of the page, then we want to zoom out instead.
+      if (this._isRectZoomedIn(bRect, viewport)) {
+        this._zoomOut();
+        return;
+      }
+
+      rect.x = Math.round(bRect.x);
+      rect.y = Math.round(bRect.y);
+      rect.w = Math.round(bRect.width);
+      rect.h = Math.round(Math.min(bRect.width * viewport.height / viewport.height, bRect.height));
+
+      // if the block we're zooming to is really tall, and the user double-tapped
+      // more than a screenful of height from the top of it, then adjust the y-coordinate
+      // so that we center the actual point the user double-tapped upon. this prevents
+      // flying to the top of a page when double-tapping to zoom in (bug 761721).
+      // the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal
+      // margins but not vertical ones.
+      let cssTapY = viewport.y + data.y;
+      if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) {
+        rect.y = cssTapY - (rect.h / 2);
+      }
+
+      var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+      os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
+    }
+  },
+
+  _shouldZoomToElement: function(aElement) {
+    let win = aElement.ownerDocument.defaultView;
+    if (win.getComputedStyle(aElement, null).display == "inline")
+      return false;
+    if (aElement instanceof Ci.nsIDOMHTMLLIElement)
+      return false;
+    if (aElement instanceof Ci.nsIDOMHTMLQuoteElement)
+      return false;
+    return true;
+  },
+
+  _zoomOut: function() {
+    let rect = new Rect(0, 0, 0, 0);
+    var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+    os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
+  },
+
+  _isRectZoomedIn: function(aRect, aViewport) {
+    // This function checks to see if the area of the rect visible in the
+    // viewport (i.e. the "overlapArea" variable below) is approximately
+    // the max area of the rect we can show. It also checks that the rect
+    // is actually on-screen by testing the left and right edges of the rect.
+    // In effect, this tells us whether or not zooming in to this rect
+    // will significantly change what the user is seeing.
+    const minDifference = -20;
+    const maxDifference = 20;
+
+    let vRect = new Rect(aViewport.x, aViewport.y, aViewport.width, aViewport.height);
+    let overlap = vRect.intersect(aRect);
+    let overlapArea = overlap.width * overlap.height;
+    let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height);
+    let showing = overlapArea / (aRect.width * availHeight);
+    let dw = (aRect.width - vRect.width);
+    let dx = (aRect.x - vRect.x);
+
+    return (showing > 0.9 &&
+            dx > minDifference && dx < maxDifference &&
+            dw > minDifference && dw < maxDifference);
   }
 };
 
 ContentPanning.init();
 
 // Min/max velocity of kinetic panning. This is in pixels/millisecond.
 const kMinVelocity = 0.4;
 const kMaxVelocity = 6;
@@ -384,8 +511,57 @@ const KineticPanning = {
       }
 
       content.mozRequestAnimationFrame(callback);
     }).bind(this);
 
     content.mozRequestAnimationFrame(callback);
   }
 };
+
+const ElementTouchHelper = {
+  anyElementFromPoint: function(aWindow, aX, aY) {
+    let cwu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+    let elem = cwu.elementFromPoint(aX, aY, true, true);
+
+    let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
+    let HTMLFrameElement = Ci.nsIDOMHTMLFrameElement;
+    while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) {
+      let rect = elem.getBoundingClientRect();
+      aX -= rect.left;
+      aY -= rect.top;
+      cwu = elem.contentDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+      elem = cwu.elementFromPoint(aX, aY, true, true);
+    }
+
+    return elem;
+  },
+
+  getBoundingContentRect: function(aElement) {
+    if (!aElement)
+      return {x: 0, y: 0, w: 0, h: 0};
+
+    let document = aElement.ownerDocument;
+    while (document.defaultView.frameElement)
+      document = document.defaultView.frameElement.ownerDocument;
+
+    let cwu = document.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+    let scrollX = {}, scrollY = {};
+    cwu.getScrollXY(false, scrollX, scrollY);
+
+    let r = aElement.getBoundingClientRect();
+
+    // step out of iframes and frames, offsetting scroll values
+    for (let frame = aElement.ownerDocument.defaultView; frame.frameElement && frame != content; frame = frame.parent) {
+      // adjust client coordinates' origin to be top left of iframe viewport
+      let rect = frame.frameElement.getBoundingClientRect();
+      let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth;
+      let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth;
+      scrollX.value += rect.left + parseInt(left);
+      scrollY.value += rect.top + parseInt(top);
+    }
+
+    return {x: r.left + scrollX.value,
+            y: r.top + scrollY.value,
+            w: r.width,
+            h: r.height };
+  }
+};
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -2,16 +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/. */
 
 #ifndef DeviceStorage_h
 #define DeviceStorage_h
 
 #include "nsIDOMDeviceStorage.h"
 #include "nsIFile.h"
+#include "nsIPrincipal.h"
 #include "nsIObserver.h"
 #include "nsDOMEventTargetHelper.h"
 
 class nsDOMDeviceStorage MOZ_FINAL
   : public nsIDOMDeviceStorage
   , public nsIFileUpdateListener
   , public nsDOMEventTargetHelper
   , public nsIObserver
@@ -50,17 +51,17 @@ private:
                              JSContext* aCx,
                              PRUint8 aArgc, 
                              bool aEditable, 
                              nsIDOMDeviceStorageCursor** aRetval);
 
   PRInt32 mStorageType;
   nsCOMPtr<nsIFile> mFile;
 
-  nsCOMPtr<nsIURI> mURI;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
 
   friend class WatchFileEvent;
   friend class DeviceStorageRequest;
 
   bool  mIsWatchingFile;
 
   // nsIDOMDeviceStorage.type
   enum {
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -29,16 +29,17 @@
 #include "nsXULAppAPI.h"
 #include "TabChild.h"
 #include "DeviceStorageRequestChild.h"
 #include "nsIDOMDeviceStorageChangeEvent.h"
 #include "nsCRT.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 #include "GeneratedEvents.h"
+#include "mozilla/dom/PermissionMessageUtils.h"
 
 // Microsoft's API Name hackery sucks
 #undef CreateEvent
 
 #ifdef MOZ_WIDGET_GONK
 #include "nsIVolumeService.h"
 #endif
 
@@ -631,42 +632,42 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDeviceStorageCursor)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DeviceStorageCursor)
 NS_INTERFACE_MAP_END_INHERITING(DOMRequest)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorageCursor, DOMRequest)
 NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorageCursor, DOMRequest)
 
 nsDOMDeviceStorageCursor::nsDOMDeviceStorageCursor(nsIDOMWindow* aWindow,
-                                                   nsIURI* aURI,
+                                                   nsIPrincipal* aPrincipal,
                                                    DeviceStorageFile* aFile,
                                                    PRUint64 aSince)
   : DOMRequest(aWindow)
   , mOkToCallContinue(false)
   , mSince(aSince)
   , mFile(aFile)
-  , mURI(aURI)
+  , mPrincipal(aPrincipal)
 {
 }
 
 nsDOMDeviceStorageCursor::~nsDOMDeviceStorageCursor()
 {
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetType(nsACString & aType)
 {
   aType = "device-storage";
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMDeviceStorageCursor::GetUri(nsIURI * *aRequestingURI)
+nsDOMDeviceStorageCursor::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
 {
-  NS_IF_ADDREF(*aRequestingURI = mURI);
+  NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   NS_IF_ADDREF(*aRequestingWindow = GetOwner());
   return NS_OK;
@@ -932,38 +933,38 @@ public:
         DEVICE_STORAGE_REQUEST_READ,
         DEVICE_STORAGE_REQUEST_WRITE,
         DEVICE_STORAGE_REQUEST_DELETE,
         DEVICE_STORAGE_REQUEST_WATCH
     };
 
     DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
                          nsPIDOMWindow *aWindow,
-                         nsIURI *aURI,
+                         nsIPrincipal *aPrincipal,
                          DeviceStorageFile *aFile,
                          DOMRequest* aRequest,
                          nsDOMDeviceStorage *aDeviceStorage,
                          nsIDOMEventListener *aListener)
       : mRequestType(aRequestType)
       , mWindow(aWindow)
-      , mURI(aURI)
+      , mPrincipal(aPrincipal)
       , mFile(aFile)
       , mRequest(aRequest)
       , mDeviceStorage(aDeviceStorage)
-      , mListener(aListener) {}  
+      , mListener(aListener) {}
 
     DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
                          nsPIDOMWindow *aWindow,
-                         nsIURI *aURI,
+                         nsIPrincipal *aPrincipal,
                          DeviceStorageFile *aFile,
                          DOMRequest* aRequest,
                          nsIDOMBlob *aBlob = nullptr)
       : mRequestType(aRequestType)
       , mWindow(aWindow)
-      , mURI(aURI)
+      , mPrincipal(aPrincipal)
       , mFile(aFile)
       , mRequest(aRequest)
       , mBlob(aBlob) {}
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageRequest, nsIContentPermissionRequest)
 
   NS_IMETHOD Run() {
@@ -982,17 +983,17 @@ public:
         return NS_OK;
       }
 
       // Retain a reference so the object isn't deleted without IPDL's knowledge.
       // Corresponding release occurs in DeallocPContentPermissionRequest.
       AddRef();
 
       nsCString type = NS_LITERAL_CSTRING("device-storage");
-      child->SendPContentPermissionRequestConstructor(this, type, IPC::URI(mURI));
+      child->SendPContentPermissionRequestConstructor(this, type, IPC::Principal(mPrincipal));
 
       Sendprompt();
       return NS_OK;
     }
 
     nsCOMPtr<nsIContentPermissionPrompt> prompt = do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
     if (prompt) {
       prompt->Prompt(this);
@@ -1001,19 +1002,19 @@ public:
   }
 
   NS_IMETHOD GetType(nsACString & aType)
   {
     aType = "device-storage";
     return NS_OK;
   }
 
-  NS_IMETHOD GetUri(nsIURI * *aRequestingURI)
+  NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
   {
-    NS_IF_ADDREF(*aRequestingURI = mURI);
+    NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
     return NS_OK;
   }
 
   NS_IMETHOD GetWindow(nsIDOMWindow * *aRequestingWindow)
   {
     NS_IF_ADDREF(*aRequestingWindow = mWindow);
     return NS_OK;
   }
@@ -1148,17 +1149,17 @@ public:
   void IPDLRelease()
   {
     Release();
   }
 
 private:
   PRInt32 mRequestType;
   nsCOMPtr<nsPIDOMWindow> mWindow;
-  nsCOMPtr<nsIURI> mURI;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
   nsRefPtr<DeviceStorageFile> mFile;
 
   nsRefPtr<DOMRequest> mRequest;
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsRefPtr<nsDOMDeviceStorage> mDeviceStorage;
   nsCOMPtr<nsIDOMEventListener> mListener;
 };
 
@@ -1221,24 +1222,24 @@ nsDOMDeviceStorage::Init(nsPIDOMWindow* 
 
   SetRootFileForType(aType);
   if (!mFile) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   BindToOwner(aWindow);
 
-  // Grab the uri of the document
+  // Grab the principal of the document
   nsCOMPtr<nsIDOMDocument> domdoc;
   aWindow->GetDocument(getter_AddRefs(domdoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
   if (!doc) {
     return NS_ERROR_FAILURE;
   }
-  doc->NodePrincipal()->GetURI(getter_AddRefs(mURI));
+  mPrincipal = doc->NodePrincipal();
   return NS_OK;
 }
 
 nsDOMDeviceStorage::~nsDOMDeviceStorage()
 {
 }
 
 void
@@ -1306,17 +1307,17 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob 
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mFile, aPath);
 
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_FILE_NAME, dsf);
   }
   else {
     r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WRITE,
-                                 win, mURI, dsf, request, aBlob);
+                                 win, mPrincipal, dsf, request, aBlob);
   }
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Get(const JS::Value & aPath,
                         JSContext* aCx,
@@ -1362,17 +1363,17 @@ nsDOMDeviceStorage::GetInternal(const JS
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mFile, path);
   dsf->SetEditable(aEditable);
 
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_FILE_NAME, dsf);
   } else {
     r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_READ,
-                                 win, mURI, dsf, request);
+                                 win, mPrincipal, dsf, request);
   }
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMRequest * *_retval)
 {
@@ -1397,17 +1398,17 @@ nsDOMDeviceStorage::Delete(const JS::Val
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mFile, path);
 
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_FILE_NAME, dsf);
   }
   else {
     r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_DELETE,
-                                 win, mURI, dsf, request);
+                                 win, mPrincipal, dsf, request);
   }
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Enumerate(const JS::Value & aName,
                              const JS::Value & aOptions,
@@ -1480,17 +1481,18 @@ nsDOMDeviceStorage::EnumerateInternal(co
       return NS_ERROR_FAILURE;
     }
     since = ExtractDateFromOptions(aCx, aOptions);
   }
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mFile, path);
   dsf->SetEditable(aEditable);
 
-  nsRefPtr<nsDOMDeviceStorageCursor> cursor = new nsDOMDeviceStorageCursor(win, mURI, dsf, since);
+  nsRefPtr<nsDOMDeviceStorageCursor> cursor = new nsDOMDeviceStorageCursor(win, mPrincipal,
+                                                                           dsf, since);
   nsRefPtr<DeviceStorageCursorRequest> r = new DeviceStorageCursorRequest(cursor);
 
   NS_ADDREF(*aRetval = cursor);
 
   if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
     r->Allow();
     return NS_OK;
   }
@@ -1502,17 +1504,17 @@ nsDOMDeviceStorage::EnumerateInternal(co
     if (!child)
       return NS_OK;
 
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     r->AddRef();
 
     nsCString type = NS_LITERAL_CSTRING("device-storage");
-    child->SendPContentPermissionRequestConstructor(r, type, IPC::URI(mURI));
+    child->SendPContentPermissionRequestConstructor(r, type, IPC::Principal(mPrincipal));
 
     r->Sendprompt();
 
     return NS_OK;
   }
 
   nsCOMPtr<nsIContentPermissionPrompt> prompt = do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (prompt) {
@@ -1608,17 +1610,17 @@ nsDOMDeviceStorage::AddEventListener(con
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mFile);
   nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WATCH,
-                                                     win, mURI, dsf, request, this, aListener);
+                                                     win, mPrincipal, dsf, request, this, aListener);
   NS_DispatchToMainThread(r);
   return nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::AddSystemEventListener(const nsAString & aType,
                                            nsIDOMEventListener *aListener,
                                            bool aUseCapture,
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -13,16 +13,17 @@ class nsPIDOMWindow;
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIClassInfo.h"
 #include "nsIContentPermissionPrompt.h"
 #include "nsIDOMDeviceStorageCursor.h"
 #include "nsIDOMWindow.h"
 #include "nsIURI.h"
 #include "nsInterfaceHashtable.h"
+#include "nsIPrincipal.h"
 #include "nsString.h"
 #include "nsWeakPtr.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIObserver.h"
 #include "mozilla/Mutex.h"
 #include "DeviceStorage.h"
 
@@ -81,33 +82,33 @@ class nsDOMDeviceStorageCursor MOZ_FINAL
   , public PCOMContentPermissionRequestChild
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSIDOMDEVICESTORAGECURSOR
 
   nsDOMDeviceStorageCursor(nsIDOMWindow* aWindow,
-                           nsIURI* aURI,
+                           nsIPrincipal* aPrincipal,
                            DeviceStorageFile* aFile,
                            PRUint64 aSince);
 
 
   nsTArray<nsRefPtr<DeviceStorageFile> > mFiles;
   bool mOkToCallContinue;
   PRUint64 mSince;
 
   virtual bool Recv__delete__(const bool& allow);
   virtual void IPDLRelease();
 
 private:
   ~nsDOMDeviceStorageCursor();
 
   nsRefPtr<DeviceStorageFile> mFile;
-  nsCOMPtr<nsIURI> mURI;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
 //helpers
 jsval StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString);
 jsval nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile, bool aEditable);
 jsval BlobToJsval(nsPIDOMWindow* aWindow, nsIDOMBlob* aBlob);
 
 
--- a/dom/file/ArchiveEvent.cpp
+++ b/dom/file/ArchiveEvent.cpp
@@ -8,18 +8,24 @@
 
 #include "nsContentUtils.h"
 #include "nsCExternalHandlerService.h"
 
 USING_FILE_NAMESPACE
 
 NS_IMPL_THREADSAFE_ISUPPORTS0(ArchiveItem)
 
+ArchiveItem::ArchiveItem()
+{
+  MOZ_COUNT_CTOR(ArchiveItem);
+}
+
 ArchiveItem::~ArchiveItem()
 {
+  MOZ_COUNT_DTOR(ArchiveItem);
 }
 
 
 nsCString
 ArchiveItem::GetType()
 {
   return mType.IsEmpty() ? nsCString("binary/octet-stream") : mType;
 }
--- a/dom/file/ArchiveEvent.h
+++ b/dom/file/ArchiveEvent.h
@@ -19,16 +19,17 @@ BEGIN_FILE_NAMESPACE
 
 // This class contains all the info needed for a single item
 // It must contain the implementation of the File() method.
 class ArchiveItem : public nsISupports
 {
 public:
   NS_DECL_ISUPPORTS
 
+  ArchiveItem();
   virtual ~ArchiveItem();
 
   // Getter/Setter for the type
   virtual nsCString GetType();
   virtual void SetType(const nsCString& aType);
 
   // Getter for the filename
   virtual nsCString GetFilename() = 0;
--- a/dom/file/ArchiveReader.cpp
+++ b/dom/file/ArchiveReader.cpp
@@ -18,21 +18,23 @@
 
 USING_FILE_NAMESPACE
 
 ArchiveReader::ArchiveReader()
 : mBlob(nullptr),
   mWindow(nullptr),
   mStatus(NOT_STARTED)
 {
+  MOZ_COUNT_CTOR(ArchiveReader);
   nsLayoutStatics::AddRef();
 }
 
 ArchiveReader::~ArchiveReader()
 {
+  MOZ_COUNT_DTOR(ArchiveReader);
   nsLayoutStatics::Release();
 }
 
 NS_IMETHODIMP
 ArchiveReader::Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
--- a/dom/file/ArchiveRequest.cpp
+++ b/dom/file/ArchiveRequest.cpp
@@ -46,25 +46,27 @@ ArchiveRequestEvent::Run()
 
 /* ArchiveRequest */
 
 ArchiveRequest::ArchiveRequest(nsIDOMWindow* aWindow,
                                ArchiveReader* aReader)
 : DOMRequest(aWindow),
   mArchiveReader(aReader)
 {
+  MOZ_COUNT_CTOR(ArchiveRequest);
   nsLayoutStatics::AddRef();
 
   /* An event to make this request asynchronous: */
   nsRefPtr<ArchiveRequestEvent> event = new ArchiveRequestEvent(this);
   NS_DispatchToCurrentThread(event);
 }
 
 ArchiveRequest::~ArchiveRequest()
 {
+  MOZ_COUNT_DTOR(ArchiveRequest);
   nsLayoutStatics::Release();
 }
 
 nsresult
 ArchiveRequest::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = true;
   aVisitor.mParentTarget = nullptr;
--- a/dom/file/ArchiveZipEvent.cpp
+++ b/dom/file/ArchiveZipEvent.cpp
@@ -17,16 +17,22 @@ USING_FILE_NAMESPACE
 #endif
 
 // ArchiveZipItem
 ArchiveZipItem::ArchiveZipItem(const char* aFilename,
                                ZipCentral& aCentralStruct)
 : mFilename(aFilename),
   mCentralStruct(aCentralStruct)
 {
+  MOZ_COUNT_CTOR(ArchiveZipItem);
+}
+
+ArchiveZipItem::~ArchiveZipItem()
+{
+  MOZ_COUNT_DTOR(ArchiveZipItem);
 }
 
 // Getter/Setter for the filename
 nsCString
 ArchiveZipItem::GetFilename()
 {
   return mFilename;
 }
--- a/dom/file/ArchiveZipEvent.h
+++ b/dom/file/ArchiveZipEvent.h
@@ -14,16 +14,17 @@
 
 BEGIN_FILE_NAMESPACE
 
 class ArchiveZipItem : public ArchiveItem
 {
 public:
   ArchiveZipItem(const char* aFilename,
                  ZipCentral& aCentralStruct);
+  virtual ~ArchiveZipItem();
 
   void SetFilename(const nsCString& aFilename);
   nsCString GetFilename();
 
   // From zipItem to DOMFile:
   virtual nsIDOMFile* File(ArchiveReader* aArchiveReader);
 
 public: // for the event
--- a/dom/file/ArchiveZipFile.cpp
+++ b/dom/file/ArchiveZipFile.cpp
@@ -25,21 +25,24 @@ public:
                      PRUint32 aStart,
                      PRUint32 aLength,
                      ZipCentral& aCentral)
   : mArchiveReader(aReader),
     mCentral(aCentral),
     mFilename(aFilename),
     mStart(aStart),
     mLength(aLength),
-    mRunning(false)
-  {}
+    mStatus(NotStarted)
+  {
+    MOZ_COUNT_CTOR(ArchiveInputStream);
+  }
 
-  ~ArchiveInputStream()
+  virtual ~ArchiveInputStream()
   {
+    MOZ_COUNT_DTOR(ArchiveInputStream);
     Close();
   }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
 
 private:
   nsresult Init();
@@ -48,17 +51,21 @@ private: // data
   nsRefPtr<ArchiveReader> mArchiveReader;
   ZipCentral mCentral;
   nsString mFilename;
   PRUint32 mStart;
   PRUint32 mLength;
 
   z_stream mZs;
 
-  bool mRunning;
+  enum {
+    NotStarted,
+    Started,
+    Done
+  } mStatus;
 
   struct {
     nsCOMPtr<nsIInputStream> inputStream;
     unsigned char input[ZIP_CHUNK];
     PRUint32 sizeToBeRead;
     bool compressed; // a zip file can contain stored or compressed files
   } mData;
 };
@@ -142,26 +149,25 @@ ArchiveInputStream::Init()
 
       if (ret == 0)
         return NS_ERROR_UNEXPECTED;
 
       done -= ret;
     }
   }
 
-  mRunning = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ArchiveInputStream::Close()
 {
-  if (mRunning) {
+  if (mStatus != NotStarted) {
     inflateEnd(&mZs);
-    mRunning = false;
+    mStatus = NotStarted;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ArchiveInputStream::Available(PRUint32* _retval)
 {
@@ -172,48 +178,57 @@ ArchiveInputStream::Available(PRUint32* 
 NS_IMETHODIMP
 ArchiveInputStream::Read(char* aBuffer,
                          PRUint32 aCount,
                          PRUint32* _retval)
 {
   NS_ENSURE_ARG_POINTER(aBuffer);
   NS_ENSURE_ARG_POINTER(_retval);
 
-  PRUint32 ret;
   nsresult rv;
 
   // This is the first time:
-  if (!mRunning) {
+  if (mStatus == NotStarted) {
+    mStatus = Started;
+
     rv = Init();
     if (rv != NS_OK)
       return rv;
+
+    // Let's set avail_out to -1 so we read something from the stream.
+    mZs.avail_out = (uInt)-1;
   }
 
   // Nothing more can be read
-  if (mData.sizeToBeRead == 0) {
+  if (mStatus == Done) {
     *_retval = 0;
     return NS_OK;
   }
 
   // Stored file:
   if (!mData.compressed)
   {
     rv = mData.inputStream->Read(aBuffer,
                                  (mData.sizeToBeRead > aCount ?
                                       aCount : mData.sizeToBeRead),
                                  _retval);
-    if (rv == NS_OK)
+    if (rv == NS_OK) {
       mData.sizeToBeRead -= *_retval;
 
+      if (mData.sizeToBeRead == 0)
+        mStatus = Done;
+    }
+
     return rv;
   }
 
   // We have nothing ready to be processed:
-  if (mZs.avail_out == 0)
+  if (mZs.avail_out != 0 && mData.sizeToBeRead != 0)
   {
+    PRUint32 ret;
     rv = mData.inputStream->Read((char*)mData.input,
                                  (mData.sizeToBeRead > sizeof(mData.input) ?
                                       sizeof(mData.input) : mData.sizeToBeRead),
                                  &ret);
     if (rv != NS_OK)
       return rv;
 
     // Terminator:
@@ -225,20 +240,23 @@ ArchiveInputStream::Read(char* aBuffer,
     mData.sizeToBeRead -= ret;
     mZs.avail_in = ret;
     mZs.next_in = mData.input;
   }
 
   mZs.avail_out = aCount;
   mZs.next_out = (unsigned char*)aBuffer;
 
-  ret = inflate(&mZs, mData.sizeToBeRead ? Z_NO_FLUSH : Z_FINISH);
-  if (ret != Z_OK && ret != Z_STREAM_END)
+  int ret = inflate(&mZs, mData.sizeToBeRead ? Z_NO_FLUSH : Z_FINISH);
+  if (ret != Z_BUF_ERROR && ret != Z_OK && ret != Z_STREAM_END)
     return NS_ERROR_UNEXPECTED;
 
+  if (ret == Z_STREAM_END)
+    mStatus = Done;
+
   *_retval = aCount - mZs.avail_out;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ArchiveInputStream::ReadSegments(nsWriteSegmentFun aWriter,
                                  void* aClosure,
                                  PRUint32 aCount,
--- a/dom/file/ArchiveZipFile.h
+++ b/dom/file/ArchiveZipFile.h
@@ -25,30 +25,37 @@ public:
                  ZipCentral& aCentral,
                  ArchiveReader* aReader)
   : nsDOMFileCC(aName, aContentType, aLength),
     mCentral(aCentral),
     mArchiveReader(aReader),
     mFilename(aName)
   {
     NS_ASSERTION(mArchiveReader, "must have a reader");
+    MOZ_COUNT_CTOR(ArchiveZipFile);
   }
 
   ArchiveZipFile(const nsAString& aName,
                  const nsAString& aContentType,
                  PRUint64 aStart,
                  PRUint64 aLength,
                  ZipCentral& aCentral,
                  ArchiveReader* aReader)
   : nsDOMFileCC(aContentType, aStart, aLength),
     mCentral(aCentral),
     mArchiveReader(aReader),
     mFilename(aName)
   {
     NS_ASSERTION(mArchiveReader, "must have a reader");
+    MOZ_COUNT_CTOR(ArchiveZipFile);
+  }
+
+  virtual ~ArchiveZipFile()
+  {
+    MOZ_COUNT_DTOR(ArchiveZipFile);
   }
 
   // Overrides:
   NS_IMETHOD GetInternalStream(nsIInputStream**);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ArchiveZipFile, nsIDOMFile)
 
--- a/dom/interfaces/apps/Makefile.in
+++ b/dom/interfaces/apps/Makefile.in
@@ -10,14 +10,15 @@ VPATH          = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE         = dom
 XPIDL_MODULE   = dom_apps
 GRE_MODULE     = 1
 
 XPIDLSRCS =                               \
+            mozIApplication.idl \
             nsIDOMApplicationRegistry.idl \
             nsIAppsService.idl \
             nsIDOMMozApplicationEvent.idl \
             $(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/apps/mozIApplication.idl
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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 "nsIDOMApplicationRegistry.idl"
+
+/**
+ * We expose Gecko-internal helpers related to "web apps" through this
+ * sub-interface.
+ */
+[scriptable, uuid(8de25e36-b4cb-4e89-9310-a199dce4e5f4)]
+interface mozIApplication: mozIDOMApplication
+{
+  /* Return true if this app has |permission|. */
+  boolean hasPermission(in string permission);
+};
--- a/dom/interfaces/apps/nsIAppsService.idl
+++ b/dom/interfaces/apps/nsIAppsService.idl
@@ -10,21 +10,31 @@ interface mozIDOMApplication;
 #define APPS_SERVICE_CID { 0x05072afa, 0x92fe, 0x45bf, { 0xae, 0x22, 0x39, 0xb6, 0x9c, 0x11, 0x70, 0x58 } }
 #define APPS_SERVICE_CONTRACTID "@mozilla.org/AppsService;1"
 %}
 
 /*
  * This service allows accessing some DOMApplicationRegistry methods from
  * non-javascript code.
  */
-[scriptable, uuid(1210a0f3-add3-4381-b892-9c102e3afc42)]
+[scriptable, uuid(04e4ef3c-1a30-45bc-ab08-291820f13872)]
 interface nsIAppsService : nsISupports
 {
   mozIDOMApplication getAppByManifestURL(in DOMString manifestURL);
 
   /**
    * Returns the |localId| of the app associated with the |manifestURL| passed
    * in parameter.
    * Returns nsIScriptSecurityManager::NO_APP_ID if |manifestURL| isn't a valid
    * installed manifest URL.
    */
   unsigned long getAppLocalIdByManifestURL(in DOMString manifestURL);
+
+  /**
+   * Returns the application associated to this localId.
+   */
+  mozIDOMApplication getAppByLocalId(in unsigned long localId);
+
+  /**
+   * Returns the manifest URL associated to this localId.
+   */
+  DOMString getManifestURLByLocalId(in unsigned long localId);
 };
--- a/dom/interfaces/base/nsIContentPermissionPrompt.idl
+++ b/dom/interfaces/base/nsIContentPermissionPrompt.idl
@@ -1,36 +1,36 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsIURI;
+interface nsIPrincipal;
 interface nsIDOMWindow;
 interface nsIDOMElement;
 
 /**
  * Interface allows access to a content to request
  * permission to perform a privileged operation such as
  * geolocation.
  */
-[scriptable, uuid(E79C7063-DBAB-45E3-8A98-D0142E1ABC9A)]
+[scriptable, uuid(E1F3796C-ADFA-414B-B2A7-AC62F29395EE)]
 interface nsIContentPermissionRequest : nsISupports {
 
   /**
    *  The type of the permission request, such as
    *  "geolocation".
    */
   readonly attribute ACString type;
 
   /**
-   *  The uri of the permission request.
+   *  The principal of the permission request.
    */
-  readonly attribute nsIURI uri;
+  readonly attribute nsIPrincipal principal;
 
   /**
    *  The window or element that the permission request was
    *  originated in.  Typically the element will be non-null
    *  in when using out of process content.  window or
    *  element can be null but not both.
    */
   readonly attribute nsIDOMWindow window;
--- a/dom/interfaces/base/nsIDOMJSWindow.idl
+++ b/dom/interfaces/base/nsIDOMJSWindow.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
-[scriptable, uuid(6652c4d2-6b49-424b-aaf9-91f91006fab7)]
+[scriptable, uuid(1f4da4d4-1d72-4709-8207-3665dbaac4b4)]
 interface nsIDOMJSWindow : nsISupports
 {
   void                      dump(in DOMString str);
 
   /**
    * These methods take typeless arguments and optional arguments, the
    * first argument is either a function or a string, the second
    * argument must be a number (ms) and the rest of the arguments (2
@@ -71,9 +71,12 @@ interface nsIDOMJSWindow : nsISupports
    * window.frames in Netscape 4.x and IE is just a reference to the
    * window itself (i.e. window.frames === window), but this doesn't
    * make sense from a generic API point of view so that's why this is
    * JS specific.
    *
    * This property is "replaceable" in JavaScript.
    */
   readonly attribute nsIDOMWindow             frames;
+
+  [binaryname(ContentForCompat)]
+  readonly attribute nsIDOMWindow             _content;
 };
new file mode 100644
--- /dev/null
+++ b/dom/ipc/AppProcessPermissions.cpp
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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 "AppProcessPermissions.h"
+#include "ContentParent.h"
+#include "mozIApplication.h"
+#include "nsIDOMApplicationRegistry.h"
+#include "TabParent.h"
+
+using namespace mozilla::dom;
+using namespace mozilla::services;
+
+namespace mozilla {
+
+bool
+AppProcessHasPermission(PBrowserParent* aActor, const char* aPermission)
+{
+  if (!aActor) {
+    NS_WARNING("Testing permissions for null actor");
+    return false;
+  }
+
+  TabParent* tab = static_cast<TabParent*>(aActor);
+  nsCOMPtr<mozIApplication> app = tab->GetApp();
+  // isBrowser frames inherit their app descriptor to identify their
+  // data storage, but they don't inherit the permissions associated
+  // with that descriptor.
+  if (!app || tab->IsBrowserElement()) {
+    return false;
+  }
+
+  bool hasPermission = false;
+  return (NS_SUCCEEDED(app->HasPermission(aPermission, &hasPermission)) &&
+          hasPermission);
+}
+
+bool
+AppProcessHasPermission(PContentParent* aActor, const char* aPermission)
+{
+  const InfallibleTArray<PBrowserParent*>& browsers =
+    aActor->ManagedPBrowserParent();
+  for (uint32_t i = 0; i < browsers.Length(); ++i) {
+    if (AppProcessHasPermission(browsers[i], aPermission)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/AppProcessPermissions.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_Capabilities_h
+#define mozilla_Capabilities_h
+
+namespace mozilla {
+
+namespace dom {
+class PBrowserParent;
+class PContentParent;
+}
+
+/**
+ * Return true iff the specified browser has the specified capability.
+ */
+bool
+AppProcessHasPermissions(mozilla::dom::PBrowserParent* aActor,
+                         const char* aPermission);
+
+/**
+ * Return true iff any of the PBrowsers loaded in this content process
+ * has the specified capability.
+ */
+bool
+AppProcessHasPermission(mozilla::dom::PContentParent* aActor,
+                        const char* aPermission);
+
+// NB: when adding capability checks for other IPDL actors, please add
+// them to this file and have them delegate to the two functions above
+// as appropriate.  For example,
+//
+//   bool AppProcessHasCapability(PNeckoParent* aActor) {
+//     return AppProcessHasCapability(aActor->Manager());
+//   }
+
+} // namespace mozilla
+
+#endif // mozilla_Capabilities_h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -34,16 +34,17 @@
 
 #if defined(MOZ_SYDNEYAUDIO)
 #include "nsAudioStream.h"
 #endif
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsTObserverArray.h"
 #include "nsIObserver.h"
+#include "nsIScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsWeakReference.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsJSEnvironment.h"
 #include "SandboxHal.h"
 #include "nsDebugImpl.h"
@@ -397,20 +398,21 @@ PCompositorChild*
 ContentChild::AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                base::ProcessId aOtherProcess)
 {
     return CompositorChild::Create(aTransport, aOtherProcess);
 }
 
 PBrowserChild*
 ContentChild::AllocPBrowser(const PRUint32& aChromeFlags,
-                            const bool& aIsBrowserElement,
-                            const PRUint32& aAppId)
+                            const bool& aIsBrowserElement, const AppId& aApp)
 {
-    nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement, aAppId);
+    PRUint32 appId = aApp.get_uint32_t();
+    nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement,
+                                             appId);
     return NS_SUCCEEDED(iframe->Init()) ? iframe.forget().get() : NULL;
 }
 
 bool
 ContentChild::DeallocPBrowser(PBrowserChild* iframe)
 {
     TabChild* child = static_cast<TabChild*>(iframe);
     NS_RELEASE(child);
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -63,17 +63,17 @@ public:
         return mAppInfo;
     }
 
     PCompositorChild* AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                        base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags,
                                          const bool& aIsBrowserElement,
-                                         const PRUint32& aAppId);
+                                         const AppId& aAppId);
     virtual bool DeallocPBrowser(PBrowserChild*);
 
     virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestChild*);
 
     virtual PBlobChild* AllocPBlob(const BlobConstructorParams& aParams);
     virtual bool DeallocPBlob(PBlobChild*);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -8,21 +8,24 @@
 
 #include "ContentParent.h"
 
 #if defined(ANDROID) || defined(LINUX)
 # include <sys/time.h>
 # include <sys/resource.h>
 #endif
 
+#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/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/StorageParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
@@ -42,26 +45,29 @@
 #include "nsConsoleMessage.h"
 #include "nsDebugImpl.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDOMFile.h"
 #include "nsExternalHelperAppService.h"
 #include "nsFrameMessageManager.h"
 #include "nsHashPropertyBag.h"
 #include "nsIAlertsService.h"
+#include "nsIAppsService.h"
 #include "nsIClipboard.h"
 #include "nsIConsoleService.h"
+#include "nsIDOMApplicationRegistry.h"
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMWindow.h"
 #include "nsIFilePicker.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIRemoteBlob.h"
 #include "nsIScriptError.h"
+#include "nsIScriptSecurityManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIWindowWatcher.h"
 #include "nsMemoryReporterManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsSystemInfo.h"
 #include "nsThreadUtils.h"
 #include "nsToolkitCompsCID.h"
 #include "nsWidgetsCID.h"
@@ -142,62 +148,96 @@ 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;
 
-ContentParent*
+/*static*/ ContentParent*
 ContentParent::GetNewOrUsed()
 {
     if (!gNonAppContentParents)
         gNonAppContentParents = new nsTArray<ContentParent*>();
 
     PRInt32 maxContentProcesses = Preferences::GetInt("dom.ipc.processCount", 1);
     if (maxContentProcesses < 1)
         maxContentProcesses = 1;
 
     if (gNonAppContentParents->Length() >= PRUint32(maxContentProcesses)) {
         PRUint32 idx = rand() % gNonAppContentParents->Length();
         ContentParent* p = (*gNonAppContentParents)[idx];
         NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in gNonAppContentParents?");
         return p;
     }
-        
+
     nsRefPtr<ContentParent> p =
         new ContentParent(/* appManifestURL = */ EmptyString());
     p->Init();
     gNonAppContentParents->AppendElement(p);
     return p;
 }
 
-ContentParent*
-ContentParent::GetForApp(const nsAString& aAppManifestURL)
+/*static*/ TabParent*
+ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
 {
-    if (aAppManifestURL.IsEmpty()) {
-        return GetNewOrUsed();
+    if (!aApp) {
+        if (ContentParent* cp = GetNewOrUsed()) {
+            nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
+            return static_cast<TabParent*>(
+                cp->SendPBrowserConstructor(
+                    // DeallocPBrowserParent() releases the ref we take here
+                    tp.forget().get(),
+                    /*chromeFlags*/0,
+                    aIsBrowserElement, nsIScriptSecurityManager::NO_APP_ID));
+        }
+        return nullptr;
     }
 
     if (!gAppContentParents) {
         gAppContentParents =
             new nsDataHashtable<nsStringHashKey, ContentParent*>();
         gAppContentParents->Init();
     }
 
     // Each app gets its own ContentParent instance.
-    ContentParent* p = gAppContentParents->Get(aAppManifestURL);
-    if (!p) {
-        p = new ContentParent(aAppManifestURL);
-        p->Init();
-        gAppContentParents->Put(aAppManifestURL, p);
+    nsAutoString manifestURL;
+    if (NS_FAILED(aApp->GetManifestURL(manifestURL))) {
+        NS_ERROR("Failed to get manifest URL");
+        return nullptr;
+    }
+
+    nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+    if (!appsService) {
+        NS_ERROR("Failed to get apps service");
+        return nullptr;
     }
 
-    return p;
+    // 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);
+    if (!p) {
+        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,
+                                   aIsBrowserElement, appId));
 }
 
 static PLDHashOperator
 AppendToTArray(const nsAString& aKey, ContentParent* aValue, void* aArray)
 {
     nsTArray<ContentParent*> *array =
         static_cast<nsTArray<ContentParent*>*>(aArray);
     array->AppendElement(aValue);
@@ -327,16 +367,36 @@ ContentParent::OnChannelConnected(int32 
             if (nice != 0 && cpus == 1) {
                 setpriority(PRIO_PROCESS, pid, getpriority(PRIO_PROCESS, pid) + nice);
             }
         }
 #endif
     }
 }
 
+void
+ContentParent::ProcessingError(Result what)
+{
+    if (MsgDropped == what) {
+        // Messages sent after crashes etc. are not a big deal.
+        return;
+    }
+    // Other errors are big deals.  This ensures the process is
+    // eventually killed, but doesn't immediately KILLITWITHFIRE
+    // because we want to get a minidump if possible.  After a timeout
+    // though, the process is forceably killed.
+    if (!KillProcess(OtherProcess(), 1, false)) {
+        NS_WARNING("failed to kill subprocess!");
+    }
+    XRE_GetIOMessageLoop()->PostTask(
+        FROM_HERE,
+        NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated,
+                            OtherProcess(), /*force=*/true));
+}
+
 namespace {
 
 void
 DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
 {
     XRE_GetIOMessageLoop()
         ->PostTask(FROM_HERE,
                    new DeleteTask<GeckoChildProcessHost>(aSubprocess));
@@ -428,22 +488,16 @@ ContentParent::ActorDestroy(ActorDestroy
     // |this|.  If so, when we go out of scope here, we're deleted and
     // all hell breaks loose.
     //
     // This runnable ensures that a reference to |this| lives on at
     // least until after the current task finishes running.
     NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
 }
 
-TabParent*
-ContentParent::CreateTab(PRUint32 aChromeFlags, bool aIsBrowserElement, PRUint32 aAppId)
-{
-  return static_cast<TabParent*>(SendPBrowserConstructor(aChromeFlags, aIsBrowserElement, aAppId));
-}
-
 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(
@@ -835,32 +889,50 @@ PCompositorParent*
 ContentParent::AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                 base::ProcessId aOtherProcess)
 {
     return CompositorParent::Create(aTransport, aOtherProcess);
 }
 
 PBrowserParent*
 ContentParent::AllocPBrowser(const PRUint32& aChromeFlags,
-                             const bool& aIsBrowserElement,
-                             const PRUint32& aAppId)
+                             const bool& aIsBrowserElement, const AppId& aApp)
 {
-  TabParent* parent = new TabParent();
-  if (parent){
+    // We only use this Alloc() method when the content processes asks
+    // us to open a window.  In that case, we're expecting to see the
+    // opening PBrowser as its app descriptor, and we can trust the data
+    // associated with that PBrowser since it's fully owned by this
+    // process.
+    if (AppId::TPBrowserParent != aApp.type()) {
+        NS_ERROR("Content process attempting to forge app ID");
+        return nullptr;
+    }
+    TabParent* opener = static_cast<TabParent*>(aApp.get_PBrowserParent());
+
+    // Popup windows of isBrowser frames are isBrowser if the parent
+    // isBrowser.  Allocating a !isBrowser frame with same app ID
+    // would allow the content to access data it's not supposed to.
+    if (opener && opener->IsBrowserElement() && !aIsBrowserElement) {
+        NS_ERROR("Content process attempting to escalate data access privileges");
+        return nullptr;
+    }
+
+    TabParent* parent = new TabParent(opener ? opener->GetApp() : nullptr,
+                                      aIsBrowserElement);
+    // We release this ref in DeallocPBrowser()
     NS_ADDREF(parent);
-  }
-  return parent;
+    return parent;
 }
 
 bool
 ContentParent::DeallocPBrowser(PBrowserParent* frame)
 {
-  TabParent* parent = static_cast<TabParent*>(frame);
-  NS_RELEASE(parent);
-  return true;
+    TabParent* parent = static_cast<TabParent*>(frame);
+    NS_RELEASE(parent);
+    return true;
 }
 
 PDeviceStorageRequestParent*
 ContentParent::AllocPDeviceStorageRequest(const DeviceStorageParams& aParams)
 {
   return new DeviceStorageRequestParent(aParams);
 }
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -21,16 +21,17 @@
 #include "nsIPermissionManager.h"
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIMemoryReporter.h"
 #include "nsCOMArray.h"
 #include "nsDataHashtable.h"
 #include "nsInterfaceHashtable.h"
 #include "nsHashKeys.h"
 
+class mozIApplication;
 class nsFrameMessageManager;
 class nsIDOMBlob;
 
 namespace mozilla {
 
 namespace ipc {
 class TestShellParent;
 }
@@ -55,38 +56,33 @@ private:
     typedef mozilla::ipc::TestShellParent TestShellParent;
     typedef mozilla::layers::PCompositorParent PCompositorParent;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
     static ContentParent* GetNewOrUsed();
 
     /**
-     * Get or create a content process for the given app.  A given app
-     * (identified by its manifest URL) gets one process all to itself.
+     * 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.
      *
-     * If the given manifest is the empty string, then this method is equivalent
-     * to GetNewOrUsed().
+     * Currently apps are given their own process, and browser tabs
+     * share processes.
      */
-    static ContentParent* GetForApp(const nsAString& aManifestURL);
+    static TabParent* CreateBrowser(mozIApplication* aApp,
+                                    bool aIsBrowserFrame);
+
     static void GetAll(nsTArray<ContentParent*>& aArray);
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
 
-    /**
-     * Create a new tab.
-     *
-     * |aIsBrowserElement| indicates whether this tab is part of an
-     * <iframe mozbrowser>.
-     * |aAppId| indicates which app the tab belongs to.
-     */
-    TabParent* CreateTab(PRUint32 aChromeFlags, bool aIsBrowserElement, PRUint32 aAppId);
     /** Notify that a tab was destroyed during normal operation. */
     void NotifyTabDestroyed(PBrowserParent* aTab);
 
     TestShellParent* CreateTestShell();
     bool DestroyTestShell(TestShellParent* aTestShell);
     TestShellParent* GetTestShellSingleton();
 
     void ReportChildAlreadyBlocked();
@@ -138,17 +134,19 @@ private:
      * by the Get*() funtions.  However, the shutdown sequence itself
      * may be asynchronous.
      */
     void ShutDown();
 
     PCompositorParent* AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                         base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
-    virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags, const bool& aIsBrowserElement, const PRUint32& aAppId);
+    virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags,
+                                          const bool& aIsBrowserElement,
+                                          const AppId& aApp);
     virtual bool DeallocPBrowser(PBrowserParent* frame);
 
     virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestParent*);
 
     virtual PBlobParent* AllocPBlob(const BlobConstructorParams& aParams);
     virtual bool DeallocPBlob(PBlobParent*);
 
@@ -257,16 +255,18 @@ private:
                                  const PRUint32& aFlags,
                                  const nsCString& aCategory);
 
     virtual bool RecvPrivateDocShellsExist(const bool& aExist);
 
     virtual bool RecvAddFileWatch(const nsString& root);
     virtual bool RecvRemoveFileWatch(const nsString& root);
 
+    virtual void ProcessingError(Result what) MOZ_OVERRIDE;
+
     GeckoChildProcessHost* mSubprocess;
 
     PRInt32 mGeolocationWatchID;
     int mRunToCompletionDepth;
     bool mShouldCallUnblockChild;
 
     // This is a cache of all of the memory reporters
     // registered in the child process.  To update this, one
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -18,45 +18,53 @@ FAIL_ON_WARNINGS := 1
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 TEST_DIRS += tests
 endif
 
 EXPORTS = PCOMContentPermissionRequestChild.h
 
 EXPORTS_NAMESPACES = \
+  mozilla \
   mozilla/dom \
   mozilla/dom/ipc \
   $(NULL)
 
+EXPORTS_mozilla = \
+  AppProcessPermissions.h \
+  $(NULL)
+
 EXPORTS_mozilla/dom = \
   ContentChild.h \
   ContentParent.h \
   ContentProcess.h \
   CrashReporterChild.h \
   CrashReporterParent.h \
+  PermissionMessageUtils.h \
   StructuredCloneUtils.h \
   TabParent.h \
   TabChild.h \
   TabMessageUtils.h \
   $(NULL)
 
 EXPORTS_mozilla/dom/ipc = \
   Blob.h \
   ProcessPriorityManager.h \
   nsIRemoteBlob.h \
   $(NULL)
 
 CPPSRCS = \
+  AppProcessPermissions.cpp \
   Blob.cpp \
   ContentProcess.cpp \
   ContentParent.cpp \
   ContentChild.cpp \
   CrashReporterParent.cpp \
   CrashReporterChild.cpp \
+  PermissionMessageUtils.cpp \
   ProcessPriorityManager.cpp \
   StructuredCloneUtils.cpp \
   TabParent.cpp \
   TabChild.cpp \
   TabMessageUtils.cpp \
   $(NULL)
 
 ifdef MOZ_SYDNEYAUDIO
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -10,27 +10,32 @@ include protocol PContent;
 include protocol PContentDialog;
 include protocol PDocumentRenderer;
 include protocol PContentPermissionRequest;
 include protocol PRenderFrame;
 include protocol POfflineCacheUpdate;
 include protocol PIndexedDB;
 
 include "gfxMatrix.h";
+include "FrameMetrics.h";
 include "IPC/nsGUIEventIPC.h";
 include "mozilla/dom/TabMessageUtils.h";
+include "mozilla/dom/PermissionMessageUtils.h";
 include "mozilla/layout/RenderFrameUtils.h";
 include "mozilla/net/NeckoMessageUtils.h";
 
 include DOMTypes;
 
 using IPC::URI;
+using IPC::Principal;
 using gfxMatrix;
+using gfxRect;
 using gfxSize;
 using mozilla::layers::LayersBackend;
+using mozilla::layers::FrameMetrics;
 using mozilla::layout::ScrollingBehavior;
 using mozilla::WindowsHandle;
 using nscolor;
 using nsCompositionEvent;
 using nsIMEUpdatePreference;
 using nsIntPoint;
 using nsIntRect;
 using nsIntSize;
@@ -169,17 +174,30 @@ parent:
     /**
      * Return native data of root widget
      */
     sync GetWidgetNativeData() returns (WindowsHandle value);
 
     SetCursor(PRUint32 value);
     SetBackgroundColor(nscolor color);
 
-    PContentPermissionRequest(nsCString aType, URI uri);
+    /**
+     * Initiates an asynchronous request for permission for the
+     * provided principal.
+     *
+     * @param aType
+     *   The type of permission to request.
+     * @param aPrincipal
+     *   The principal of the request.
+     *
+     * NOTE: The principal is untrusted in the parent process. Only
+     *       principals that can live in the content process should
+     *       provided.
+     */
+    PContentPermissionRequest(nsCString aType, Principal principal);
 
     PContentDialog(PRUint32 aType, nsCString aName, nsCString aFeatures,
                    PRInt32[] aIntParams, nsString[] aStringParams);
 
     /**
      * Create a layout frame (encapsulating a remote layer tree) for
      * the page that is currently loaded in the <browser>.
      */
@@ -227,16 +245,24 @@ parent:
      * the window.open.
      *
      * @param opener the PBrowser whose content called window.open.
      */
     sync BrowserFrameOpenWindow(PBrowser opener, nsString aURL,
                                 nsString aName, nsString aFeatures)
       returns (bool windowOpened);
 
+    NotifyDOMTouchListenerAdded();
+
+    /**
+     * Instructs the TabParent to forward a request to zoom to a rect given in
+     * CSS pixels. This rect is relative to the document.
+     */
+    ZoomToRect(gfxRect aRect);
+
     __delete__();
 
 child:
     /**
      * Notify the remote browser that it has been Show()n on this
      * side, with the given |visibleRect|.  This message is expected
      * to trigger creation of the remote browser's "widget".
      *
@@ -245,20 +271,24 @@ child:
      * point.
      */
     Show(nsIntSize size);
 
     LoadURL(nsCString uri);
 
     UpdateDimensions(nsRect rect, nsIntSize size);
 
-    UpdateFrame(nsIntRect displayPort,
-                nsIntPoint scrollOffset,
-                gfxSize resolution,
-                nsIntRect screenSize);
+    UpdateFrame(FrameMetrics frame);
+
+    /**
+     * Requests handling of a double tap. |point| is in CSS pixels, relative to
+     * the scroll offset. This message is expected to round-trip back to
+     * ZoomToRect() with a rect indicating where we should zoom to.
+     */
+    HandleDoubleTap(nsIntPoint point);
 
     /**
      * Sending an activate message moves focus to the child.
      */
     Activate();
 
     Deactivate();
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -117,16 +117,21 @@ struct MysteryBlobConstructorParams
 union BlobConstructorParams
 {
   NormalBlobConstructorParams;
   FileBlobConstructorParams;
   SlicedBlobConstructorParams;
   MysteryBlobConstructorParams;
 };
 
+union AppId {
+  uint32_t;
+  nullable PBrowser;
+};
+
 rpc protocol PContent
 {
     parent opens PCompositor;
 
     manages PAudio;
     manages PBlob;
     manages PBrowser;
     manages PCrashReporter;
@@ -140,19 +145,26 @@ rpc protocol PContent
     manages PStorage;
     manages PTestShell;
 
 both:
     // Depending on exactly how the new browser is being created, it might be
     // created from either the child or parent process!
     //
     // The child creates the PBrowser as part of
-    // TabChild::BrowserFrameProvideWindow, and the parent creates the PBrowser
-    // as part of ContentParent::CreateTab.
-    async PBrowser(PRUint32 chromeFlags, bool isBrowserElement, PRUint32 appId);
+    // TabChild::BrowserFrameProvideWindow, and the parent creates the
+    // PBrowser as part of ContentParent::CreateTab.
+    //
+    // When the parent constructs a PBrowser, the app ID handed to the
+    // child side is trusted.  In that case, |appId| is uint32_t.
+    // However, when the child side constructs a PBrowser, for
+    // window.open(), the parent must validate the app ID used on the
+    // parent side.  To do so, the child process must pass a valid
+    // PBrowser as its |AppId|.
+    async PBrowser(PRUint32 chromeFlags, bool isBrowserElement, AppId appId);
 
     async PBlob(BlobConstructorParams params);
 
 child:
     PMemoryReportRequest();
 
     PTestShell();
 
new file mode 100644
--- /dev/null
+++ b/dom/ipc/PermissionMessageUtils.cpp
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/PermissionMessageUtils.h"
+#include "nsISerializable.h"
+#include "nsSerializationHelper.h"
+
+namespace IPC {
+
+void
+ParamTraits<Principal>::Write(Message* aMsg, const paramType& aParam) {
+  bool isNull = !aParam.mPrincipal;
+  WriteParam(aMsg, isNull);
+  if (isNull) {
+    return;
+  }
+
+  bool isSerialized = false;
+  nsCString principalString;
+  nsCOMPtr<nsISerializable> serializable = do_QueryInterface(aParam.mPrincipal);
+  if (serializable) {
+    nsresult rv = NS_SerializeToString(serializable, principalString);
+    if (NS_SUCCEEDED(rv)) {
+      isSerialized = true;
+    }
+  }
+
+  if (!isSerialized) {
+    NS_RUNTIMEABORT("Unable to serialize principal.");
+    return;
+  }
+
+  WriteParam(aMsg, principalString);
+}
+
+bool
+ParamTraits<Principal>::Read(const Message* aMsg, void** aIter, paramType* aResult)
+{
+  bool isNull;
+  if (!ReadParam(aMsg, aIter, &isNull)) {
+    return false;
+  }
+
+  if (isNull) {
+    aResult->mPrincipal = nullptr;
+    return true;
+  }
+
+  nsCString principalString;
+  if (!ReadParam(aMsg, aIter, &principalString)) {
+    return false;
+  }
+
+  nsCOMPtr<nsISupports> iSupports;
+  nsresult rv = NS_DeserializeObject(principalString, getter_AddRefs(iSupports));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(iSupports);
+  NS_ENSURE_TRUE(principal, false);
+
+  principal.swap(aResult->mPrincipal);
+  return true;
+}
+
+} // namespace IPC
+
new file mode 100644
--- /dev/null
+++ b/dom/ipc/PermissionMessageUtils.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_permission_message_utils_h__
+#define mozilla_dom_permission_message_utils_h__
+
+#include "IPC/IPCMessageUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIPrincipal.h"
+
+namespace IPC {
+
+class Principal {
+  friend struct ParamTraits<Principal>;
+
+public:
+  Principal() : mPrincipal(nsnull) {}
+  Principal(nsIPrincipal* aPrincipal) : mPrincipal(aPrincipal) {}
+  operator nsIPrincipal*() const { return mPrincipal.get(); }
+
+private:
+  // Unimplemented
+  Principal& operator=(Principal&);
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+};
+
+template <>
+struct ParamTraits<Principal>
+{
+  typedef Principal paramType;
+  static void Write(Message* aMsg, const paramType& aParam);
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
+};
+
+} // namespace IPC
+
+#endif // mozilla_dom_permission_message_utils_h__
+
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -15,16 +15,17 @@
 #include "mozilla/IntentionalCrash.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
 #include "mozilla/dom/PContentChild.h"
 #include "mozilla/dom/PContentDialogChild.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layout/RenderFrameChild.h"
+#include "mozilla/unused.h"
 #include "nsComponentManagerUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsEmbedCID.h"
 #include "nsEventListenerManager.h"
 #include "nsIBaseWindow.h"
 #include "nsIComponentManager.h"
 #include "nsIDOMClassInfo.h"
@@ -102,30 +103,80 @@ TabChild::TabChild(PRUint32 aChromeFlags
   , mDidFakeShow(false)
   , mIsBrowserElement(aIsBrowserElement)
   , mAppId(aAppId)
 {
     printf("creating %d!\n", NS_IsMainThread());
 }
 
 nsresult
+TabChild::Observe(nsISupports *aSubject,
+                  const char *aTopic,
+                  const PRUnichar *aData)
+{
+  if (!strcmp(aTopic, "dom-touch-listener-added")) {
+    nsCOMPtr<nsIDOMWindow> subject(do_QueryInterface(aSubject));
+    nsCOMPtr<nsIDOMWindow> win(do_GetInterface(mWebNav));
+    nsCOMPtr<nsIDOMWindow> topSubject;
+    subject->GetTop(getter_AddRefs(topSubject));
+    if (win == topSubject) {
+      SendNotifyDOMTouchListenerAdded();
+    }
+  } else if (!strcmp(aTopic, "cancel-default-pan-zoom")) {
+    nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
+    nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
+    if (tabChild == this) {
+      mRemoteFrame->CancelDefaultPanZoom();
+    }
+  } else if (!strcmp(aTopic, "browser-zoom-to-rect")) {
+    nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
+    nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
+    if (tabChild == this) {
+      gfxRect rect;
+      sscanf(NS_ConvertUTF16toUTF8(aData).get(),
+             "{\"x\":%lf,\"y\":%lf,\"w\":%lf,\"h\":%lf}",
+             &rect.x, &rect.y, &rect.width, &rect.height);
+      SendZoomToRect(rect);
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
 TabChild::Init()
 {
   nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
   if (!webBrowser) {
     NS_ERROR("Couldn't create a nsWebBrowser?");
     return NS_ERROR_FAILURE;
   }
 
   webBrowser->SetContainerWindow(this);
   mWebNav = do_QueryInterface(webBrowser);
   NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
 
   nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(mWebNav));
   docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
+
+  nsCOMPtr<nsIObserverService> observerService =
+    do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+
+  if (observerService) {
+    observerService->AddObserver(this,
+                                 "dom-touch-listener-added",
+                                 false);
+    observerService->AddObserver(this,
+                                 "cancel-default-pan-zoom",
+                                 false);
+    observerService->AddObserver(this,
+                                 "browser-zoom-to-rect",
+                                 false);
+  }
+
   return NS_OK;
 }
 
 NS_INTERFACE_MAP_BEGIN(TabChild)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
   NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
   NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
@@ -379,20 +430,26 @@ TabChild::BrowserFrameProvideWindow(nsID
                                     nsIURI* aURI,
                                     const nsAString& aName,
                                     const nsACString& aFeatures,
                                     bool* aWindowIsNew,
                                     nsIDOMWindow** aReturn)
 {
   *aReturn = nullptr;
 
-  nsRefPtr<TabChild> newChild =
-    static_cast<TabChild*>(Manager()->SendPBrowserConstructor(
-      /* aChromeFlags = */ 0, mIsBrowserElement, mAppId));
-
+  PRUint32 chromeFlags = 0;
+  nsRefPtr<TabChild> newChild = new TabChild(chromeFlags,
+                                             mIsBrowserElement, mAppId);
+  if (!NS_SUCCEEDED(newChild->Init())) {
+      return NS_ERROR_ABORT;
+  }
+  unused << Manager()->SendPBrowserConstructor(
+      // We release this ref in DeallocPBrowserChild
+      nsRefPtr<TabChild>(newChild).forget().get(),
+      chromeFlags, mIsBrowserElement, this);
   nsCAutoString spec;
   if (aURI) {
     aURI->GetSpec(spec);
   }
 
   NS_ConvertUTF8toUTF16 url(spec);
   nsString name(aName);
   NS_ConvertUTF8toUTF16 features(aFeatures);
@@ -639,65 +696,93 @@ TabChild::RecvUpdateDimensions(const nsR
 
     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mWebNav);
     baseWin->SetPositionAndSize(0, 0, size.width, size.height,
                                 true);
 
     return true;
 }
 
-bool
-TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort,
-                          const nsIntPoint& aScrollOffset,
-                          const gfxSize& aResolution,
-                          const nsIntRect& aScreenSize)
+void
+TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
+                                        const nsACString& aJSONData)
 {
-    if (!mCx || !mTabChildGlobal) {
-        return true;
-    }
-    nsCString data;
-    data += nsPrintfCString("{ \"x\" : %d", aScrollOffset.x);
-    data += nsPrintfCString(", \"y\" : %d", aScrollOffset.y);
-    // We don't treat the x and y scales any differently for this
-    // semi-platform-specific code.
-    data += nsPrintfCString(", \"zoom\" : %f", aResolution.width);
-    data += nsPrintfCString(", \"displayPort\" : ");
-        data += nsPrintfCString("{ \"left\" : %d", aDisplayPort.X());
-        data += nsPrintfCString(", \"top\" : %d", aDisplayPort.Y());
-        data += nsPrintfCString(", \"width\" : %d", aDisplayPort.Width());
-        data += nsPrintfCString(", \"height\" : %d", aDisplayPort.Height());
-        data += nsPrintfCString(", \"resolution\" : %f", aResolution.width);
-        data += nsPrintfCString(" }");
-    data += nsPrintfCString(", \"screenSize\" : ");
-        data += nsPrintfCString("{ \"width\" : %d", aScreenSize.width);
-        data += nsPrintfCString(", \"height\" : %d", aScreenSize.height);
-        data += nsPrintfCString(" }");
-    data += nsPrintfCString(" }");
-
     JSAutoRequest ar(mCx);
     jsval json = JSVAL_NULL;
     StructuredCloneData cloneData;
     JSAutoStructuredCloneBuffer buffer;
     if (JS_ParseJSON(mCx,
-                      static_cast<const jschar*>(NS_ConvertUTF8toUTF16(data).get()),
-                      data.Length(),
+                      static_cast<const jschar*>(NS_ConvertUTF8toUTF16(aJSONData).get()),
+                      aJSONData.Length(),
                       &json)) {
         WriteStructuredClone(mCx, json, buffer, cloneData.mClosure);
         cloneData.mData = buffer.data();
         cloneData.mDataLength = buffer.nbytes();
     }
 
     nsFrameScriptCx cx(static_cast<nsIWebBrowserChrome*>(this), this);
     // Let the BrowserElementScrolling helper (if it exists) for this
     // content manipulate the frame state.
     nsRefPtr<nsFrameMessageManager> mm =
       static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
     mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(mTabChildGlobal),
-                       NS_LITERAL_STRING("Viewport:Change"), false,
-                       &cloneData, nullptr, nullptr);
+                       aMessageName, false, &cloneData, nullptr, nullptr);
+}
+
+bool
+TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
+{
+    if (!mCx || !mTabChildGlobal) {
+        return true;
+    }
+
+    nsCString data;
+    data += nsPrintfCString("{ \"x\" : %d", aFrameMetrics.mViewportScrollOffset.x);
+    data += nsPrintfCString(", \"y\" : %d", aFrameMetrics.mViewportScrollOffset.y);
+    // We don't treat the x and y scales any differently for this
+    // semi-platform-specific code.
+    data += nsPrintfCString(", \"zoom\" : %f", aFrameMetrics.mResolution.width);
+    data += nsPrintfCString(", \"displayPort\" : ");
+        data += nsPrintfCString("{ \"left\" : %d", aFrameMetrics.mDisplayPort.X());
+        data += nsPrintfCString(", \"top\" : %d", aFrameMetrics.mDisplayPort.Y());
+        data += nsPrintfCString(", \"width\" : %d", aFrameMetrics.mDisplayPort.Width());
+        data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mDisplayPort.Height());
+        data += nsPrintfCString(", \"resolution\" : %f", aFrameMetrics.mResolution.width);
+        data += nsPrintfCString(" }");
+    data += nsPrintfCString(", \"screenSize\" : ");
+        data += nsPrintfCString("{ \"width\" : %d", aFrameMetrics.mViewport.width);
+        data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mViewport.height);
+        data += nsPrintfCString(" }");
+    data += nsPrintfCString(", \"cssPageRect\" : ");
+        data += nsPrintfCString("{ \"x\" : %f", aFrameMetrics.mCSSContentRect.x);
+        data += nsPrintfCString(", \"y\" : %f", aFrameMetrics.mCSSContentRect.y);
+        data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mCSSContentRect.width);
+        data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mCSSContentRect.height);
+        data += nsPrintfCString(" }");
+    data += nsPrintfCString(" }");
+
+    DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
+
+    return true;
+}
+
+bool
+TabChild::RecvHandleDoubleTap(const nsIntPoint& aPoint)
+{
+    if (!mCx || !mTabChildGlobal) {
+        return true;
+    }
+
+    nsCString data;
+    data += nsPrintfCString("{ \"x\" : %d", aPoint.x);
+    data += nsPrintfCString(", \"y\" : %d", aPoint.y);
+    data += nsPrintfCString(" }");
+
+    DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
+
     return true;
 }
 
 bool
 TabChild::RecvActivate()
 {
   nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(mWebNav);
   browser->Activate();
@@ -914,17 +999,17 @@ TabChild::AllocPContentDialog(const PRUi
 bool
 TabChild::DeallocPContentDialog(PContentDialogChild* aDialog)
 {
   delete aDialog;
   return true;
 }
 
 PContentPermissionRequestChild*
-TabChild::AllocPContentPermissionRequest(const nsCString& aType, const IPC::URI&)
+TabChild::AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal&)
 {
   NS_RUNTIMEABORT("unused");
   return nullptr;
 }
 
 bool
 TabChild::DeallocPContentPermissionRequest(PContentPermissionRequestChild* actor)
 {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -42,16 +42,17 @@
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsPIDOMWindow.h"
 #include "nsWeakReference.h"
 #include "nsITabChild.h"
 #include "mozilla/Attributes.h"
+#include "FrameMetrics.h"
 
 struct gfxMatrix;
 
 namespace mozilla {
 namespace layout {
 class RenderFrameChild;
 }
 
@@ -135,50 +136,52 @@ class TabChild : public PBrowserChild,
                  public nsFrameScriptExecutor,
                  public nsIWebBrowserChrome2,
                  public nsIEmbeddingSiteWindow,
                  public nsIWebBrowserChromeFocus,
                  public nsIInterfaceRequestor,
                  public nsIWindowProvider,
                  public nsSupportsWeakReference,
                  public nsIDialogCreator,
-                 public nsITabChild
+                 public nsITabChild,
+                 public nsIObserver
 {
     typedef mozilla::layout::RenderFrameChild RenderFrameChild;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
     /**
      * Create a new TabChild object.
      *
      * |aIsBrowserElement| indicates whether the tab is inside an <iframe mozbrowser>.
      * |aAppId| is the app id of the app containing this tab. If the tab isn't
      * contained in an app, aAppId will be nsIScriptSecurityManager::NO_APP_ID.
      */
     TabChild(PRUint32 aChromeFlags, bool aIsBrowserElement, PRUint32 aAppId);
     virtual ~TabChild();
     nsresult Init();
 
+    PRUint32 GetAppId() { return mAppId; }
+
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBBROWSERCHROME
     NS_DECL_NSIWEBBROWSERCHROME2
     NS_DECL_NSIEMBEDDINGSITEWINDOW
     NS_DECL_NSIWEBBROWSERCHROMEFOCUS
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSIWINDOWPROVIDER
     NS_DECL_NSIDIALOGCREATOR
     NS_DECL_NSITABCHILD
+    NS_DECL_NSIOBSERVER
 
     virtual bool RecvLoadURL(const nsCString& uri);
     virtual bool RecvShow(const nsIntSize& size);
     virtual bool RecvUpdateDimensions(const nsRe