Merge m-c to b2g-inbound. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 23 Jun 2014 10:58:47 -0400
changeset 190209 c65bf5a0595c5bf43fde1250bc5d459669a2cce4
parent 190208 df3fc195770ffc096f0607dc1e96a1f1909793aa (current diff)
parent 190113 31de1a84b27f7bf1a15d3dc9ea8a01f4acd7bd75 (diff)
child 190210 41e817fb25f06c92f61502541c27f7bfd8c6738d
push id7411
push userkwierso@gmail.com
push dateTue, 24 Jun 2014 02:07:45 +0000
treeherderfx-team@cc4602e0c1d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone33.0a1
Merge m-c to b2g-inbound. a=merge
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/webidl/moz.build
dom/xslt/xpath/nsXPathResult.cpp
dom/xslt/xpath/nsXPathResult.h
layout/style/nsCSSStyleSheet.cpp
layout/style/nsCSSStyleSheet.h
mobile/android/base/home/LastTabsPanel.java
mobile/android/base/home/MostRecentPanel.java
mobile/android/base/resources/drawable-large-land-v11/home_history_tabs_indicator.xml
mobile/android/base/resources/drawable-xlarge-v11/home_history_tabs_indicator.xml
mobile/android/base/resources/drawable/home_history_tabs_indicator.xml
mobile/android/base/resources/layout-large-land-v11/home_history_panel.xml
mobile/android/base/resources/layout-large-land-v11/home_history_tabs_indicator.xml
mobile/android/base/resources/layout-xlarge-v11/home_history_panel.xml
mobile/android/base/resources/layout-xlarge-v11/home_history_tabs_indicator.xml
mobile/android/base/resources/layout/home_history_tabs_indicator.xml
mobile/android/base/resources/layout/home_last_tabs_panel.xml
mobile/android/base/resources/layout/home_most_recent_panel.xml
mobile/android/base/resources/values-large-land-v11/dimens.xml
mobile/android/base/resources/values-xlarge-land-v11/dimens.xml
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -1298,17 +1298,17 @@ DocAccessible::GetAccessibleByUniqueIDIn
   }
 
   return nullptr;
 }
 
 Accessible*
 DocAccessible::GetAccessibleOrContainer(nsINode* aNode) const
 {
-  if (!aNode || !aNode->IsInDoc())
+  if (!aNode || !aNode->GetCrossShadowCurrentDoc())
     return nullptr;
 
   nsINode* currNode = aNode;
   Accessible* accessible = nullptr;
   while (!(accessible = GetAccessible(currNode)) &&
          (currNode = currNode->GetParentNode()));
 
   return accessible;
--- a/accessible/src/jsat/ContentControl.jsm
+++ b/accessible/src/jsat/ContentControl.jsm
@@ -70,16 +70,19 @@ this.ContentControl.prototype = {
 
   receiveMessage: function cc_receiveMessage(aMessage) {
     Logger.debug(() => {
       return ['ContentControl.receiveMessage',
         aMessage.name,
         JSON.stringify(aMessage.json)];
     });
 
+    // If we get an explicit message, we should immediately cancel any autoMove
+    this.cancelAutoMove();
+
     try {
       let func = this['handle' + aMessage.name.slice(9)]; // 'AccessFu:'.length
       if (func) {
         func.bind(this)(aMessage);
       } else {
         Logger.warning('ContentControl: Unhandled message:', aMessage.name);
       }
     } catch (x) {
@@ -376,18 +379,17 @@ this.ContentControl.prototype = {
    *    focus move. Default 0.
    * - noOpIfOnScreen: if accessible is alive and visible, don't do anything.
    * - forcePresent: present cursor location, whether we move or don't.
    * - moveToFocused: if there is a focused accessible move to that. This takes
    *    precedence over given anchor.
    * - moveMethod: pivot move method to use, default is 'moveNext',
    */
   autoMove: function cc_autoMove(aAnchor, aOptions = {}) {
-    let win = this.window;
-    win.clearTimeout(this._autoMove);
+    this.cancelAutoMove();
 
     let moveFunc = () => {
       let vc = this.vc;
       let acc = aAnchor;
       let rule = aOptions.onScreenOnly ?
         TraversalRules.SimpleOnScreen : TraversalRules.Simple;
       let forcePresentFunc = () => {
         if (aOptions.forcePresent) {
@@ -427,18 +429,23 @@ this.ContentControl.prototype = {
       });
 
       if (!moved && !sentToChild) {
         forcePresentFunc();
       }
     };
 
     if (aOptions.delay) {
-      this._autoMove = win.setTimeout(moveFunc, aOptions.delay);
+      this._autoMove = this.window.setTimeout(moveFunc, aOptions.delay);
     } else {
       moveFunc();
     }
   },
 
+  cancelAutoMove: function cc_cancelAutoMove() {
+    this.window.clearTimeout(this._autoMove);
+    this._autoMove = 0;
+  },
+
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
     Ci.nsIMessageListener
   ])
 };
--- a/accessible/src/windows/msaa/AccessibleWrap.h
+++ b/accessible/src/windows/msaa/AccessibleWrap.h
@@ -213,11 +213,12 @@ protected:
 } // namespace mozilla
 
 #ifdef XP_WIN
 // Undo the windows.h damage
 #undef GetMessage
 #undef CreateEvent
 #undef GetClassName
 #undef GetBinaryType
+#undef RemoveDirectory
 #endif
 
 #endif
--- a/accessible/tests/mochitest/elm/test_shadowroot.html
+++ b/accessible/tests/mochitest/elm/test_shadowroot.html
@@ -9,32 +9,30 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../role.js"></script>
 
   <script type="application/javascript">
-    SpecialPowers.setBoolPref("dom.webcomponents.enabled", true);
     function doTest()
     {
       testElm("component", {
         role: ROLE_GROUPING,
         children: [
         {
           role: ROLE_PUSHBUTTON,
         },
         {
           role: ROLE_LINK,
         },
         ]
       });
 
-      SpecialPowers.clearUserPref("dom.webcomponents.enabled");
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
--- a/accessible/tests/mochitest/hittest/a11y.ini
+++ b/accessible/tests/mochitest/hittest/a11y.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 support-files = zoom_tree.xul
 
 [test_browser.html]
 [test_canvas_hitregion.html]
 skip-if = (os == "android" || appname == "b2g")
 [test_general.html]
 [test_menu.xul]
+[test_shadowroot.html]
 [test_zoom.html]
 [test_zoom_text.html]
 [test_zoom_tree.xul]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/hittest/test_shadowroot.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>ShadowRoot hit tests</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../layout.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var componentAcc = getAccessible('component1');
+      testChildAtPoint(componentAcc, 1, 1, componentAcc.firstChild,
+                       componentAcc.firstChild);
+
+      componentAcc = getAccessible('component2');
+      testChildAtPoint(componentAcc, 1, 1, componentAcc.firstChild,
+                       componentAcc.firstChild);
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="Test getChildAtPoint works for shadow DOM content"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1027315">
+    Mozilla Bug 1027315
+  </a><br/>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div role="group" class="components" id="component1" style="display: inline-block;">
+  <!--
+    <div role="button" id="component-child"
+         style="width: 100px; height: 100px; background-color: pink;">
+    </div>
+  -->
+  </div>
+  <div role="group" class="components"  id="component2" style="display: inline-block;">
+  <!--
+    <button>Hello world</button>
+  -->
+  </div>
+  <script>
+    // This routine adds the comment children of each 'component' to its
+    // shadow root.
+    var components = document.querySelectorAll('.components');
+    for (var i = 0; i < components.length; i++) {
+      var component = components[i];
+      var shadow = component.createShadowRoot();
+      for (var child = component.firstChild; child; child = child.nextSibling) {
+        if (child.nodeType === 8)
+          shadow.innerHTML = child.data;
+      }
+    }
+  </script>
+
+</body>
+</html>
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1402612020000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1403216209000">
   <emItems>
       <emItem  blockID="i454" id="sqlmoz@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                                 <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
@@ -84,16 +84,22 @@
               </prefs>
     </emItem>
       <emItem  blockID="i105" id="{95ff02bc-ffc6-45f0-a5c8-619b8226a9de}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
+      <emItem  blockID="i626" id="{20AD702C-661E-4534-8CE9-BA4EC9AD6ECC}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="3">
+                    </versionRange>
+                    <prefs>
+              </prefs>
+    </emItem>
       <emItem  blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
                         <versionRange  minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i506" id="/^ext@bettersurfplus/">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
@@ -299,20 +305,18 @@
               </prefs>
     </emItem>
       <emItem  blockID="i467" id="plugin@analytic-s.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
-      <emItem  blockID="i496" id="{ACAA314B-EEBA-48e4-AD47-84E31C44796C}">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                    <prefs>
+      <emItem  blockID="i47" id="youtube@youtube2.com">
+                          <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i360" id="ytd@mybrowserbar.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
@@ -360,18 +364,18 @@
               </prefs>
     </emItem>
       <emItem  blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
-      <emItem  blockID="i584" id="{52b0f3db-f988-4788-b9dc-861d016f4487}">
-                        <versionRange  minVersion="0" maxVersion="0.1.9999999" severity="1">
+      <emItem  blockID="i624" id="/^({b95faac1-a3d7-4d69-8943-ddd5a487d966}|{ecce0073-a837-45a2-95b9-600420505f7e}|{2713b394-286f-4d7c-89ea-4174eeab9f5a}|{da7a20cf-bef4-4342-ad78-0240fdf87055})$/">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i472" id="linksicle@linksicle.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
@@ -692,33 +696,39 @@
     </emItem>
       <emItem  blockID="i479" id="mbrsepone@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i620" id="{21EAF666-26B3-4A3C-ABD0-CA2F5A326744}">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                        <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i552" id="jid0-O6MIff3eO5dIGf5Tcv8RsJDKxrs@jetpack">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i256" id="/^[0-9a-f]+@[0-9a-f]+\.info/">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
+      <emItem  blockID="i584" id="{52b0f3db-f988-4788-b9dc-861d016f4487}">
+                        <versionRange  minVersion="0" maxVersion="0.1.9999999" severity="1">
+                    </versionRange>
+                    <prefs>
+              </prefs>
+    </emItem>
       <emItem  blockID="i370" id="happylyrics@hpyproductions.net">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i440" id="{2d069a16-fca1-4e81-81ea-5d5086dcbd0c}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
@@ -1206,18 +1216,20 @@
               </prefs>
     </emItem>
       <emItem  blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
-      <emItem  blockID="i47" id="youtube@youtube2.com">
-                          <prefs>
+      <emItem  blockID="i622" id="/^({ebd898f8-fcf6-4694-bc3b-eabc7271eeb1}|{46008e0d-47ac-4daa-a02a-5eb69044431a}|{213c8ed6-1d78-4d8f-8729-25006aa86a76}|{fa23121f-ee7c-4bd8-8c06-123d087282c5}|{19803860-b306-423c-bbb5-f60a7d82cde5})$/">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                    <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i518" id="/^({d6e79525-4524-4707-9b97-1d70df8e7e59}|{ddb4644d-1a37-4e6d-8b6e-8e35e2a8ea6c}|{e55007f4-80c5-418e-ac33-10c4d60db01e}|{e77d8ca6-3a60-4ae9-8461-53b22fa3125b}|{e89a62b7-248e-492f-9715-43bf8c507a2f}|{5ce3e0cb-aa83-45cb-a7da-a2684f05b8f3})$/">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
@@ -1503,16 +1515,22 @@
               </prefs>
     </emItem>
       <emItem  blockID="i372" id="5nc3QHFgcb@r06Ws9gvNNVRfH.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
+      <emItem  blockID="i496" id="{ACAA314B-EEBA-48e4-AD47-84E31C44796C}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                    <prefs>
+              </prefs>
+    </emItem>
       <emItem  blockID="i67" id="youtube2@youtube2.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i476" id="mbroctone@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -213,18 +213,20 @@ pref("app.update.showInstalledUI", false
 //     to newer versions of installed addons that resolve them.
 // 1 = suppress prompting for incompatibilities only if there are VersionInfo
 //     updates available to installed addons that resolve them, not newer
 //     versions.
 pref("app.update.incompatible.mode", 0);
 
 // Whether or not to attempt using the service for updates.
 #ifdef MOZ_MAINTENANCE_SERVICE
+#ifndef HAVE_64BIT_OS
 pref("app.update.service.enabled", true);
 #endif
+#endif
 
 // Symmetric (can be overridden by individual extensions) update preferences.
 // e.g.
 //  extensions.{GUID}.update.enabled
 //  extensions.{GUID}.update.url
 //  .. etc ..
 //
 pref("extensions.update.enabled", true);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -752,23 +752,16 @@ var gBrowserInit = {
     gMultiProcessBrowser =
       window.QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIWebNavigation)
       .QueryInterface(Ci.nsILoadContext)
       .useRemoteTabs;
 
     var mustLoadSidebar = false;
 
-    if (!gMultiProcessBrowser) {
-      // There is a Content:Click message manually sent from content.
-      Cc["@mozilla.org/eventlistenerservice;1"]
-        .getService(Ci.nsIEventListenerService)
-        .addSystemEventListener(gBrowser, "click", contentAreaClick, true);
-    }
-
     gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
 
     // Note that the XBL binding is untrusted
     gBrowser.addEventListener("PluginBindingAttached", gPluginHandler, true, true);
     gBrowser.addEventListener("PluginCrashed",         gPluginHandler, true);
     gBrowser.addEventListener("PluginOutdated",        gPluginHandler, true);
     gBrowser.addEventListener("PluginInstantiated",    gPluginHandler, true);
     gBrowser.addEventListener("PluginRemoved",         gPluginHandler, true);
@@ -797,16 +790,25 @@ var gBrowserInit = {
           .getInterface(nsIWebNavigation)
           .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
           .QueryInterface(Ci.nsIInterfaceRequestor)
           .getInterface(Ci.nsIXULWindow)
           .XULBrowserWindow = window.XULBrowserWindow;
     window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
       new nsBrowserAccess();
 
+    if (!gMultiProcessBrowser) {
+      // There is a Content:Click message manually sent from content.
+      Cc["@mozilla.org/eventlistenerservice;1"]
+        .getService(Ci.nsIEventListenerService)
+        .addSystemEventListener(gBrowser, "click", contentAreaClick, true);
+    } else {
+      gBrowser.updateBrowserRemoteness(gBrowser.mCurrentBrowser, true);
+    }
+
     // hook up UI through progress listener
     gBrowser.addProgressListener(window.XULBrowserWindow);
     gBrowser.addTabsProgressListener(window.TabsProgressListener);
 
     // setup simple gestures support
     gGestureSupport.init(true);
 
     // setup history swipe animation
@@ -2618,17 +2620,17 @@ function onMozEnteredDomFullscreen(event
 
 function getWebNavigation()
 {
   return gBrowser.webNavigation;
 }
 
 function BrowserReloadWithFlags(reloadFlags) {
   let url = gBrowser.currentURI.spec;
-  if (gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, url)) {
+  if (gBrowser.updateBrowserRemotenessByURL(gBrowser.selectedBrowser, url)) {
     // If the remoteness has changed, the new browser doesn't have any
     // information of what was loaded before, so we need to load the previous
     // URL again.
     gBrowser.loadURIWithFlags(url, reloadFlags);
     return;
   }
 
   /* First, we'll try to use the session history object to reload so
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1369,58 +1369,67 @@
               this.selectedTab = firstTabAdded;
             }
             else
               this.selectedBrowser.focus();
           }
         ]]></body>
       </method>
 
-#ifdef MAKE_E10S_WORK
       <method name="updateBrowserRemoteness">
         <parameter name="aBrowser"/>
-        <parameter name="aURL"/>
+        <parameter name="aShouldBeRemote"/>
         <body>
           <![CDATA[
-            let shouldBeRemote = this._shouldBrowserBeRemote(aURL);
-
             let isRemote = aBrowser.getAttribute("remote") == "true";
-            if (isRemote == shouldBeRemote)
+            if (isRemote == aShouldBeRemote)
               return false;
 
             let wasActive = document.activeElement == aBrowser;
 
             // Unhook our progress listener.
             let tab = this._getTabForBrowser(aBrowser);
             let index = tab._tPos;
             let filter = this.mTabFilters[index];
             aBrowser.webProgress.removeProgressListener(filter);
 
             // Change the "remote" attribute.
             let parent = aBrowser.parentNode;
             parent.removeChild(aBrowser);
-            aBrowser.setAttribute("remote", shouldBeRemote ? "true" : "false");
+            aBrowser.setAttribute("remote", aShouldBeRemote ? "true" : "false");
             parent.appendChild(aBrowser);
 
             // Restore the progress listener.
             aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
 
-            if (shouldBeRemote)
+            if (aShouldBeRemote)
               tab.setAttribute("remote", "true");
             else
               tab.removeAttribute("remote");
 
             if (wasActive)
               aBrowser.focus();
 
             return true;
           ]]>
         </body>
       </method>
 
+#ifdef MAKE_E10S_WORK
+      <method name="updateBrowserRemotenessByURL">
+        <parameter name="aBrowser"/>
+        <parameter name="aURL"/>
+        <body>
+          <![CDATA[
+            let shouldBeRemote = this._shouldBrowserBeRemote(aURL);
+            return this.updateBrowserRemoteness(aBrowser, shouldBeRemote);
+          ]]>
+        </body>
+      </method>
+
       <!--
         Returns true if we want to load the content for this URL in a
         remote process. Eventually this should just check whether aURL
         is unprivileged. Right now, though, we would like to load
         some unprivileged URLs (like about:neterror) in the main
         process since they interact with chrome code through
         BrowserOnClick.
       -->
@@ -2721,24 +2730,24 @@
       <!-- throws exception for unknown schemes -->
       <method name="loadURI">
         <parameter name="aURI"/>
         <parameter name="aReferrerURI"/>
         <parameter name="aCharset"/>
         <body>
           <![CDATA[
 #ifdef MAKE_E10S_WORK
-            this.updateBrowserRemoteness(this.mCurrentBrowser, aURI);
+            this.updateBrowserRemotenessByURL(this.mCurrentBrowser, aURI);
             try {
 #endif
             return this.mCurrentBrowser.loadURI(aURI, aReferrerURI, aCharset);
 #ifdef MAKE_E10S_WORK
             } catch (e) {
               let url = this.mCurrentBrowser.currentURI.spec;
-              this.updateBrowserRemoteness(this.mCurrentBrowser, url);
+              this.updateBrowserRemotenessByURL(this.mCurrentBrowser, url);
               throw e;
             }
 #endif
           ]]>
         </body>
       </method>
 
       <!-- throws exception for unknown schemes -->
@@ -2746,24 +2755,24 @@
         <parameter name="aURI"/>
         <parameter name="aFlags"/>
         <parameter name="aReferrerURI"/>
         <parameter name="aCharset"/>
         <parameter name="aPostData"/>
         <body>
           <![CDATA[
 #ifdef MAKE_E10S_WORK
-            this.updateBrowserRemoteness(this.mCurrentBrowser, aURI);
+            this.updateBrowserRemotenessByURL(this.mCurrentBrowser, aURI);
             try {
 #endif
             return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
 #ifdef MAKE_E10S_WORK
             } catch (e) {
               let url = this.mCurrentBrowser.currentURI.spec;
-              this.updateBrowserRemoteness(this.mCurrentBrowser, url);
+              this.updateBrowserRemotenessByURL(this.mCurrentBrowser, url);
               throw e;
             }
 #endif
           ]]>
         </body>
       </method>
 
       <method name="goHome">
@@ -3276,17 +3285,17 @@
           if (!event.isTrusted)
             return;
 
           let browser = event.originalTarget;
           let title = browser.contentTitle;
           let uri = browser.currentURI;
           let icon = browser.mIconURL;
 
-          this.updateBrowserRemoteness(browser, "about:tabcrashed");
+          this.updateBrowserRemotenessByURL(browser, "about:tabcrashed");
 
           browser.setAttribute("crashedPageTitle", title);
           browser.docShell.displayLoadError(Cr.NS_ERROR_CONTENT_CRASHED, uri, null);
           browser.removeAttribute("crashedPageTitle");
           let tab = this._getTabForBrowser(browser);
           this.setIcon(tab, icon);
         ]]>
       </handler>
--- a/browser/components/loop/content/conversation.html
+++ b/browser/components/loop/content/conversation.html
@@ -1,16 +1,17 @@
 <!DOCTYPE html>
 <!-- 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/.  -->
 <html>
   <head>
     <meta charset="utf-8">
-    <title>Conversation</title>
+    <!-- Title is set in conversation.js -->
+    <title></title>
     <link rel="stylesheet" type="text/css" href="loop/shared/css/common.css">
     <link rel="stylesheet" type="text/css" href="loop/shared/css/conversation.css">
  </head>
   <body onload="loop.conversation.init();">
 
     <div id="messages"></div>
 
     <div id="main"></div>
--- a/browser/components/loop/content/js/conversation.js
+++ b/browser/components/loop/content/js/conversation.js
@@ -3,19 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* global loop:true */
 
 var loop = loop || {};
 loop.conversation = (function(OT, mozL10n) {
   "use strict";
 
-  var sharedViews = loop.shared.views,
-      // aliasing translation function as __ for concision
-      __ = mozL10n.get;
+  var sharedViews = loop.shared.views;
 
   /**
    * App router.
    * @type {loop.desktopRouter.DesktopConversationRouter}
    */
   var router;
 
   /**
@@ -169,16 +167,18 @@ loop.conversation = (function(OT, mozL10
   /**
    * Panel initialisation.
    */
   function init() {
     // Do the initial L10n setup, we do this before anything
     // else to ensure the L10n environment is setup correctly.
     mozL10n.initialize(window.navigator.mozLoop);
 
+    document.title = mozL10n.get("incoming_call_title");
+
     router = new ConversationRouter({
       conversation: new loop.shared.models.ConversationModel({}, {sdk: OT}),
       notifier: new sharedViews.NotificationListView({el: "#messages"})
     });
     Backbone.history.start();
   }
 
   return {
--- a/browser/components/loop/test/desktop-local/conversation_test.js
+++ b/browser/components/loop/test/desktop-local/conversation_test.js
@@ -30,16 +30,67 @@ describe("loop.conversation", function()
     };
   });
 
   afterEach(function() {
     delete window.navigator.mozLoop;
     sandbox.restore();
   });
 
+  describe("#init", function() {
+    var conversation, oldTitle;
+
+    beforeEach(function() {
+      oldTitle = document.title;
+
+      sandbox.stub(document.mozL10n, "initialize");
+      sandbox.stub(document.mozL10n, "get").returns("Fake title");
+
+      sandbox.stub(loop.conversation.ConversationRouter.prototype,
+        "initialize");
+      sandbox.stub(loop.shared.models.ConversationModel.prototype,
+        "initialize");
+      sandbox.stub(loop.shared.views.NotificationListView.prototype,
+        "initialize");
+
+      sandbox.stub(Backbone.history, "start");
+    });
+
+    afterEach(function() {
+      document.title = oldTitle;
+    });
+
+    it("should initalize L10n", function() {
+      loop.conversation.init();
+
+      sinon.assert.calledOnce(document.mozL10n.initialize);
+      sinon.assert.calledWithExactly(document.mozL10n.initialize,
+        window.navigator.mozLoop);
+    });
+
+    it("should set the document title", function() {
+      loop.conversation.init();
+
+      expect(document.title).to.be.equal("Fake title");
+    });
+
+    it("should create the router", function() {
+      loop.conversation.init();
+
+      sinon.assert.calledOnce(
+        loop.conversation.ConversationRouter.prototype.initialize);
+    });
+
+    it("should start Backbone history", function() {
+      loop.conversation.init();
+
+      sinon.assert.calledOnce(Backbone.history.start);
+    });
+  });
+
   describe("ConversationRouter", function() {
     var conversation;
 
     beforeEach(function() {
       conversation = new loop.shared.models.ConversationModel({}, {sdk: {}});
       sandbox.stub(conversation, "initiate");
     });
 
--- a/browser/components/preferences/content.js
+++ b/browser/components/preferences/content.js
@@ -183,10 +183,16 @@ var gContentPane = {
    * Displays the translation exceptions dialog where specific site and language
    * translation preferences can be set.
    */
   showTranslationExceptions: function ()
   {
     document.documentElement.openWindow("Browser:TranslationExceptions",
                                         "chrome://browser/content/preferences/translation.xul",
                                         "", null);
+  },
+
+  openTranslationProviderAttribution: function ()
+  {
+    Components.utils.import("resource:///modules/translation/Translation.jsm");
+    Translation.openProviderAttribution();
   }
 };
--- a/browser/components/preferences/content.xul
+++ b/browser/components/preferences/content.xul
@@ -139,20 +139,26 @@
           <row id="preferredLanguageRow">
             <label flex="1" control="chooseLanguage">&chooseLanguage.label;</label>
             <button id="chooseLanguage"
                     label="&chooseButton.label;"
                     accesskey="&chooseButton.accesskey;"
                     oncommand="gContentPane.showLanguages();"/>
           </row>
           <row id="translationBox" hidden="true">
-            <checkbox id="translate" preference="browser.translation.detectLanguage" flex="1"
-                      label="&translateWebPages.label;" accesskey="&translateWebPages.accesskey;"
-                      onsyncfrompreference="return gContentPane.updateButtons('translateButton',
-                                            'browser.translation.detectLanguage');"/>
+            <hbox align="center">
+              <checkbox id="translate" preference="browser.translation.detectLanguage"
+                        label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
+                        onsyncfrompreference="return gContentPane.updateButtons('translateButton',
+                                              'browser.translation.detectLanguage');"/>
+              <label>Übersetzungen von</label>
+              <image id="translationAttributionImage" aria-label="Microsoft Translator"
+                     onclick="gContentPane.openTranslationProviderAttribution()"
+                     src="chrome://browser/content/microsoft-translator-attribution.png"/>
+            </hbox>
             <button id="translateButton" label="&translateExceptions.label;"
                     oncommand="gContentPane.showTranslationExceptions();"
                     accesskey="&translateExceptions.accesskey;"/>
           </row>
         </rows>
       </grid>
 
     </groupbox>
--- a/browser/components/preferences/in-content/content.js
+++ b/browser/components/preferences/in-content/content.js
@@ -181,10 +181,16 @@ var gContentPane = {
   /**
    * Displays the translation exceptions dialog where specific site and language
    * translation preferences can be set.
    */
   showTranslationExceptions: function ()
   {
     openDialog("chrome://browser/content/preferences/translation.xul",
                "Browser:TranslationExceptions", null);
+  },
+
+  openTranslationProviderAttribution: function ()
+  {
+    Components.utils.import("resource:///modules/translation/Translation.jsm");
+    Translation.openProviderAttribution();
   }
 };
--- a/browser/components/preferences/in-content/content.xul
+++ b/browser/components/preferences/in-content/content.xul
@@ -129,17 +129,24 @@
     <description flex="1" control="chooseLanguage">&chooseLanguage.label;</description>
     <button id="chooseLanguage"
             label="&chooseButton.label;"
             accesskey="&chooseButton.accesskey;"
             oncommand="gContentPane.showLanguages();"/>
   </hbox>
 
   <hbox id="translationBox" hidden="true">
-    <checkbox id="translate" preference="browser.translation.detectLanguage" flex="1"
-              label="&translateWebPages.label;" accesskey="&translateWebPages.accesskey;"
-              onsyncfrompreference="return gContentPane.updateButtons('translateButton',
-                                    'browser.translation.detectLanguage');"/>
+    <hbox align="center" flex="1">
+      <checkbox id="translate" preference="browser.translation.detectLanguage"
+                label="&translateWebPages.label;." accesskey="&translateWebPages.accesskey;"
+                onsyncfrompreference="return gContentPane.updateButtons('translateButton',
+                                              'browser.translation.detectLanguage');"/>
+      <label>Übersetzungen von</label>
+      <separator orient="vertical" class="thin"/>
+      <image id="translationAttributionImage" aria-label="Microsoft Translator"
+             onclick="gContentPane.openTranslationProviderAttribution()"
+             src="chrome://browser/content/microsoft-translator-attribution.png"/>
+    </hbox>
     <button id="translateButton" label="&translateExceptions.label;"
             oncommand="gContentPane.showTranslationExceptions();"
             accesskey="&translateExceptions.accesskey;"/>
   </hbox>
 </groupbox>
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -2529,17 +2529,17 @@ let SessionStoreInternal = {
 
       // Save the index in case we updated it above.
       tabData.index = activeIndex + 1;
 
       // In electrolysis, we may need to change the browser's remote
       // attribute so that it runs in a content process.
       let activePageData = tabData.entries[activeIndex] || null;
       let uri = activePageData ? activePageData.url || null : null;
-      tabbrowser.updateBrowserRemoteness(browser, uri);
+      tabbrowser.updateBrowserRemotenessByURL(browser, uri);
 
       // Start a new epoch and include the epoch in the restoreHistory
       // message. If a message is received that relates to a previous epoch, we
       // discard it.
       let epoch = this._nextRestoreEpoch++;
       this._browserEpochs.set(browser.permanentKey, epoch);
 
       // keep the data around to prevent dataloss in case
--- a/browser/components/translation/Translation.jsm
+++ b/browser/components/translation/Translation.jsm
@@ -75,16 +75,22 @@ this.Translation = {
     trUI.translatedFrom = aData.translatedFrom;
     trUI.translatedTo = aData.translatedTo;
     trUI.originalShown = aData.originalShown;
 
     trUI.showURLBarIcon();
 
     if (trUI.shouldShowInfoBar(aBrowser.currentURI))
       trUI.showTranslationInfoBar();
+  },
+
+  openProviderAttribution: function() {
+    Cu.import("resource:///modules/RecentWindow.jsm");
+    RecentWindow.getMostRecentBrowserWindow().openUILinkIn(
+      "http://aka.ms/MicrosoftTranslatorAttribution", "tab");
   }
 };
 
 /* TranslationUI objects keep the information related to translation for
  * a specific browser.  This object is passed to the translation
  * infobar so that it can initialize itself.  The properties exposed to
  * the infobar are:
  * - detectedLanguage, code of the language detected on the web page.
@@ -301,16 +307,23 @@ let TranslationHealthReport = {
    *        the user has manually adjusted the detected language false should
    *        be passed.
    */
   recordLanguageChange: function (beforeFirstTranslation) {
     this._withProvider(provider => provider.recordLanguageChange(beforeFirstTranslation));
   },
 
   /**
+   * Record a denied translation offer.
+   */
+  recordDeniedTranslationOffer: function () {
+    this._withProvider(provider => provider.recordDeniedTranslationOffer());
+  },
+
+  /**
    * Retrieve the translation provider and pass it to the given function.
    *
    * @param callback
    *        The function that will be passed the translation provider.
    */
   _withProvider: function (callback) {
     try {
       let reporter = Cc["@mozilla.org/datareporting/service;1"]
@@ -358,16 +371,17 @@ TranslationMeasurement1.prototype = Obje
     missedTranslationOpportunityCount: DAILY_COUNTER_FIELD,
     pageTranslatedCount: DAILY_COUNTER_FIELD,
     charactersTranslatedCount: DAILY_COUNTER_FIELD,
     translationOpportunityCountsByLanguage: DAILY_LAST_TEXT_FIELD,
     missedTranslationOpportunityCountsByLanguage: DAILY_LAST_TEXT_FIELD,
     pageTranslatedCountsByLanguage: DAILY_LAST_TEXT_FIELD,
     detectedLanguageChangedBefore: DAILY_COUNTER_FIELD,
     detectedLanguageChangedAfter: DAILY_COUNTER_FIELD,
+    deniedTranslationOffer: DAILY_COUNTER_FIELD,
     detectLanguageEnabled: DAILY_LAST_NUMERIC_FIELD,
     showTranslationUI: DAILY_LAST_NUMERIC_FIELD,
   },
 
   shouldIncludeField: function (field) {
     if (!Services.prefs.getBoolPref("toolkit.telemetry.enabled")) {
       // This measurement should only be included when telemetry is
       // enabled, so we will not include any fields.
@@ -494,16 +508,25 @@ TranslationProvider.prototype = Object.f
       if (beforeFirstTranslation) {
           yield m.incrementDailyCounter("detectedLanguageChangedBefore");
         } else {
           yield m.incrementDailyCounter("detectedLanguageChangedAfter");
         }
     }.bind(this));
   },
 
+  recordDeniedTranslationOffer: function () {
+    let m = this.getMeasurement(TranslationMeasurement1.prototype.name,
+                                TranslationMeasurement1.prototype.version);
+
+    return this._enqueueTelemetryStorageTask(function* recordTask() {
+      yield m.incrementDailyCounter("deniedTranslationOffer");
+    }.bind(this));
+  },
+
   collectDailyData: function () {
     let m = this.getMeasurement(TranslationMeasurement1.prototype.name,
                                 TranslationMeasurement1.prototype.version);
 
     return this._enqueueTelemetryStorageTask(function* recordTask() {
       let detectLanguageEnabled = Services.prefs.getBoolPref("browser.translation.detectLanguage");
       yield m.setDailyLastNumeric("detectLanguageEnabled", detectLanguageEnabled ? 1 : 0);
 
--- a/browser/components/translation/jar.mn
+++ b/browser/components/translation/jar.mn
@@ -1,5 +1,6 @@
 # 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/.
 browser.jar:
        content/browser/translation-infobar.xml
+       content/browser/microsoft-translator-attribution.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9d277461b4b66b92f47e420649f8a20b5f5b780
GIT binary patch
literal 3422
zc$|G!2|Sct7biQ}QcP0s%vj4ZGYrOLDKqvNWeM@g3^SO_!py{2%P4!OBudm<NKr<M
zRvFD?i84jDB)mvj3nB82w(t9WzxVy_^SjTv=iLAQ+;h)8_xC($dtDvmWz}UxL`3AB
z9MSGVnJMf#(vrfrssrPWh=`ab$<v4FgT)|&XcQwnffh(KVo}0H)|#aaD;ysbMq~m5
zi6JDa6?p2wV=$0JumXFVVxib@6fu<K7(*v|#JG9}#e@Y}5WqIpKuZ=<=zv0G;(;s*
znaV)2tia#>B8B5MGXxC$4q=8_fp@P>0DZ7~fhZcC2sAY^H4K6p!+_=%Mle&j1q@~Y
zG={=VATTJz*uoG7L&D9GFf-uK1{SVHCj=wi(e^*r5^7f9P$n}R34ugKMHxkz7}4k<
z5SWF91q5mgF*Y_7A`BVPR3@HfNM&gL@_;5Xg6O1hCW%G`uIczd+99SD82oDsl<?nf
zsf?d#5+)47!iPg(Mo`Fq0kPQs52a9kqZv$hV(|Y*Gd!cii4b=pgLa4>L=?g`*T~^W
z6rG4?(&(Nv8u?ci_lDA#G)5>b9Ed^z^|1IL5_L`A{+)ouBAuuVCY~BZbV6H!g%%?c
ziGV~vp$KER>27<dtuWbkCKh&Pu-$NTgdN%hZj46Q{^Fu(L5C<rD)SeY@E@-2KXTV<
z;Rl;YCq)to_H-Hr_<hev(%-~lVqs<vGlg2%Lw6(oK9(O`!r#R5le_yLxe#G6kpDU9
zUnXJstPOwHtx)-0`9!L)-08x)zFAwUAiNWsnRY%*4_YuY3Qs4B{7AeL1s@_j8ayF7
zqKRlJ1Zj}adpw15oyd=-BJ6rUrLc?L_MiCFER=~(=-r;Ip7DaP&@4QlA>f=v%dIAm
zTyHf-1<Y}JHkO2X3UBDjMNK53gUB~E!g4_=>h|`hP?>s1rJqUh3WJsT_6t=yApAG)
zmE!yNWBXyT^VE-zY?j}?{d)h#Xl?PAd#f)F`F~l73A_~KmDp4_bPQ0nVV3aKSZ{XV
zBjitR{ImjwHWDj?`0G-Zcx(iswKjrGlL|YxSgM%l+opJwJ%hVFV6qM)J~07)0LfQR
z2e-Z-FX6#Ui+0~<ivk;~Qm!;=F-4Q&GX;OlP6w*3N<WE|DD<9KxxoHhBkJ@{=dMEa
zuAL9sCS^xpcb}wO-x-yp_)a<Bxz{YGEbj7(<U`32Qg5@~^g4};6tNXT){ae_`nt{2
zvJWLLk&4leWqUeb6)Du3)N6<oV6eqpO6e6sl~nGL^=%DCw;r%h@Xw0W9wCjtZ)`ku
zQPp;wc){~g_l9_P?p~<(V*5-FtLg-0EL%diOW~4IE!#0&t4QFylrdKPblzP_Vlq)G
zQ!A-%d%AUj>6teloq9SG!`A|}fBX9RJ0Pnu%d&Rhq}KuV#vbiW<ALv^(0B!3h3Dn-
zG|e5+0A<ygn9U)VKj;q>2KRkR>(4ko!`Pqsv0ZntKq|S*E;0aG&FWjodp4-e4#90c
z|8@(zyZ$|}9Q6Fzg+05iA4i#|2TOGij}LvZU25#wTDQ+$YNEJl(K2(}8P5Rg8yvY0
z4bmn#$#P_G<8<kcWLzZOK|AANTMACrbKt8A**Go%u=AW=maYKoV5gEYggL)0-AS(W
zh~0Jny*AWqDFSHv#MY~ND-t8Da(vcH^Ye2JvOU-G-xfN(zM_s^zV4QL5#!|IBW6*q
zU-+$L_C;W<PQwGyNp(TP*c3(W_Lv0Y1i$2MDYCcU^$lN(V>qVgw>U|3zUJmuk~-L?
zLNqzp4vn8JiH9vX#ww4h#IB192|WBfhPOG)Br3#pC);nrx9CyVF-jm8o`)+fdb}vH
zh)|KaI$CiV6ru-8hzqAw;tW=s@soqi_bL?;T*9ZjHlsF;!?z<uXWMqP%dp&mt7qB)
zBT{WBeUHaG1+pWn`4ovEWc84rLUIk9ixIuax;&X<d$r?9)8Jv}9?0oVdtdI|bPY({
zkcOPEhu|yPs!-2wdI<}yY1c6EJ%!uRaa`Ajvw($`ctO3O@&oy2gUBvRD~E;madkDE
z+9UizN@}cK#@4g3nAiIN4IqEV{gRiA4f&kB4&z*-vuFJ?jmRU0&sx$?Z!mk6Nq!k>
z3iCIIY}P6WKIZ1xW~;C7k9W~axvs@1@H{y@+*)Brbb3MR@1Gy<zPEDVz=3`n>!IPo
zQA^?T#p*HRt2S}26;nNJDo`*o>ne1?0G|#;<yfD%0z9BK`7-wzD0ss@p6^~1MmNT<
zhj5h!n1O%Z=dw|$Z!2s^b(*`E7w70*FOP33uXU3Qt@j;Jp4stvQOC`Z5IPP4J>3w^
z)A4Eu;+^IJ1|=QNf7sl&=b_FL-e{@ewN%-Y#~(UD23BW$&=u|pCj)``$6A7sFU_jp
zc5*LIrNsqaYCN+n%Uyi^h0X7*Q7U`x?LD~P!EaI?1lZKSanK~?g_V*O<Uy00&O1%4
zhMMw6%jVb0E9>JU^l!%czv^67k>eWR%%X-WH!QD0zTK&xM_`p~l(0Nk>{~~Ncs}o$
zt%hG}@v-6+UQ_)G7*8EvBS-1xzZ^+XYLPh$@NLuak9)YsJVrM7(G><f!l!H5k*r;-
z1qM&)4q9R#yAsUy;JiYo)^jb>mk*~>79O3?M;9LR9*1|$?@AEA(L_#l94>ix`(9E<
zcWC*P^vsroYXS=m>ytC@((S5Tjutl=K-gJR$(D0bN;BJLaMIk%nkyo1wuPw6e`2=-
zL@FzmCA}i`w)M=RlUS@y<)OB+xcdOTKr-7us=fOdA}!xpgAiF+(Jw{~T$BflQ+Nh}
zA`ywcwmf&}zxp;y_L`)QreYe@k7eg4WG$&1)^1aKB{FsSV4nGtLCqF*d%m~pZ1uvH
zWbUTaZ}8)-2fZ4IssY6&528RDPEiy}m+BIV?4Y8klH%t|nCtui?`(-HgJL7JiV|z>
z3WJPd_~4%4;?_?ee3nXzCg?Ix&1>yPP&I%`{Nj+jHJzV(ZorKO(!ZJg$n6lj;Kpa=
zFfLh9Fk|KgEw0)B!B6dz=qP8_+$V;ZDL&+){TT*w=H{B5;}^}9rq{F#OL8^LTGw$@
zTR!D%Ej#cf9_A}sb)mAZ-e5X9qome78_62Y#*fk6yb~*l1`-T#gwCB&kNt6#d7=aQ
z`FjdlJ3vbh?QcHIWp@Yf_#=$FG1e@`_zv}JR~)roC*NY*p+~Lb4xHJIt@8oLYfF4E
z_WFR^S$D-0N7O1j>UpD@0Mog6K6&Y=QYNV`g4_Po1*)xZxJ+p-IV&uwIzZWP?>XGI
z4@Yq81fF3%bn#J>F_6Tm?Vm2Cy>Nh%5LwdXm=q;US_<y!pf;da%+v2->z`u!0=xx4
zyP-aEf1$Waj;?CYa!29h_WX^4fP>e*Sw;jkF2sqyLP?i~NON0=!>RyrkMq*(0r@4#
z5V%h7nL&g6Bl_@Hp0~?zrJUJdGUxkR{#^xU2FI1y`>6<5M+CQm5cvi1q0-u!EyHq7
zEzM5BEuf12nqJL9L2nxzF61`&274&kLIbMk-rChTYeHlvB2x8hb~WxKFYPl<ksH_Y
z@<q+U1mE=vmK~ijoNcynFT0yOmr0V=XYA5&)+xj-r0P|78Om{7(!HSNK1X_+O*wQi
zEAg8}C3`pv{u3M*U(n<zGr?8+TX3Y}&Os+t*lFLq^)jIR=oadY5y^X7T-ADqwDMyN
zL|(y(lZ4)tR6v>zciL~N4}EyxGwV&rBKg`M_{DRa3nM8s?v&Kg8@lq|@+*9J7kggo
z7Ool{ei(nNe9FAJYhxA4GWYq}laZPev1H8<R6D%}{)8dexhwbU*8X*yK(*(`+0*eU
zID6@U*1Kxgp7`eUddc)YT96D;kmRXHSba*tH)p2ddh$;xOK!2QRz)uNjU#x-)IR=>
zJg=_ArN1P$u09RUXebj$t{UcLa0|Beb7zm{U}nb5WZW%Z-f8*#DphhuP!M-bGICBJ
zTPm&?T0Wc{z47%{ViuoV7oK@U+SN;OAUPJ+d$2z%rWj;2j*FML8?{}nKXE-9cy|9z
zg@LXFZR_oAi|2;lpE?1!Xj!X@QR8-?YPGGOlLfU?Rb8fYAHi=%XIS$%sWVgW%QSA4
fYv^|PK3EmWTN=|@$GmxK?QhP>&J}&#7RUZKMltZ&
--- a/browser/components/translation/test/unit/test_healthreport.js
+++ b/browser/components/translation/test/unit/test_healthreport.js
@@ -191,16 +191,38 @@ add_task(function* test_record_translati
   Assert.equal(day.get("detectedLanguageChangedBefore"), 1);
   Assert.ok(day.has("detectedLanguageChangedAfter"));
   Assert.equal(day.get("detectedLanguageChangedAfter"), 2);
 
   yield provider.shutdown();
   yield storage.close();
 });
 
+add_task(function* test_denied_translation_offer() {
+  let storage = yield Metrics.Storage("translation");
+  let provider = new TranslationProvider();
+  yield provider.init(storage);
+  let now = new Date();
+
+  yield provider.recordDeniedTranslationOffer();
+  yield provider.recordDeniedTranslationOffer();
+
+  let m = provider.getMeasurement("translation", 1);
+  let values = yield m.getValues();
+  Assert.equal(values.days.size, 1);
+  Assert.ok(values.days.hasDay(now));
+  let day = values.days.getDay(now);
+
+  Assert.ok(day.has("deniedTranslationOffer"));
+  Assert.equal(day.get("deniedTranslationOffer"), 2);
+
+  yield provider.shutdown();
+  yield storage.close();
+});
+
 add_task(function* test_collect_daily() {
   let storage = yield Metrics.Storage("translation");
   let provider = new TranslationProvider();
   yield provider.init(storage);
   let now = new Date();
 
   // Set the prefs we test here to `false` initially.
   const kPrefDetectLanguage = "browser.translation.detectLanguage";
@@ -248,16 +270,18 @@ add_task(function* test_healthreporter_j
     yield provider.recordTranslationOpportunity("fr", now);
     yield provider.recordLanguageChange(true);
     yield provider.recordTranslation("fr", "en", 1000, now);
     yield provider.recordLanguageChange(false);
 
     yield provider.recordTranslationOpportunity("es", now);
     yield provider.recordTranslation("es", "en", 1000, now);
 
+    yield provider.recordDeniedTranslationOffer();
+
     yield reporter.collectMeasurements();
     let payload = yield reporter.getJSONPayload(true);
     let today = reporter._formatDate(now);
 
     Assert.ok(today in payload.data.days);
     let day = payload.data.days[today];
 
     Assert.ok("org.mozilla.translation.translation" in day);
@@ -280,16 +304,19 @@ add_task(function* test_healthreporter_j
     Assert.ok("es" in translations["pageTranslatedCountsByLanguage"]);
     Assert.equal(translations["pageTranslatedCountsByLanguage"]["es"]["total"], 1);
     Assert.equal(translations["pageTranslatedCountsByLanguage"]["es"]["en"], 1);
 
     Assert.ok("detectedLanguageChangedBefore" in translations);
     Assert.equal(translations["detectedLanguageChangedBefore"], 1);
     Assert.ok("detectedLanguageChangedAfter" in translations);
     Assert.equal(translations["detectedLanguageChangedAfter"], 1);
+    
+    Assert.ok("deniedTranslationOffer" in translations);
+    Assert.equal(translations["deniedTranslationOffer"], 1);
   } finally {
     reporter._shutdown();
   }
 });
 
 // Test the payload after recording with telemetry disabled.
 add_task(function* test_healthreporter_json2() {
   Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
@@ -304,16 +331,18 @@ add_task(function* test_healthreporter_j
     yield provider.recordTranslationOpportunity("fr", now);
     yield provider.recordLanguageChange(true);
     yield provider.recordTranslation("fr", "en", 1000, now);
     yield provider.recordLanguageChange(false);
 
     yield provider.recordTranslationOpportunity("es", now);
     yield provider.recordTranslation("es", "en", 1000, now);
 
+    yield provider.recordDeniedTranslationOffer();
+
     yield reporter.collectMeasurements();
     let payload = yield reporter.getJSONPayload(true);
     let today = reporter._formatDate(now);
 
     Assert.ok(today in payload.data.days);
     let day = payload.data.days[today];
 
     Assert.ok("org.mozilla.translation.translation" in day);
@@ -322,12 +351,13 @@ add_task(function* test_healthreporter_j
 
     Assert.ok(!("translationOpportunityCount" in translations));
     Assert.ok(!("pageTranslatedCount" in translations));
     Assert.ok(!("charactersTranslatedCount" in translations));
     Assert.ok(!("translationOpportunityCountsByLanguage" in translations));
     Assert.ok(!("pageTranslatedCountsByLanguage" in translations));
     Assert.ok(!("detectedLanguageChangedBefore" in translations));
     Assert.ok(!("detectedLanguageChangedAfter" in translations));
+    Assert.ok(!("deniedTranslationOffer" in translations));
   } finally {
     reporter._shutdown();
   }
 });
--- a/browser/components/translation/translation-infobar.xml
+++ b/browser/components/translation/translation-infobar.xml
@@ -93,27 +93,35 @@
 
           </xul:deck>
           <xul:spacer flex="1"/>
 
           <xul:button type="menu"
                       class="translate-infobar-element options-menu-button"
                       anonid="options"
                       label="&translation.options.menu;">
-            <xul:menupopup onpopupshowing="document.getBindingParent(this).optionsShowing();">
+            <xul:menupopup class="translation-menupopup cui-widget-panel cui-widget-panelview
+                                  cui-widget-panelWithFooter PanelUI-subView"
+                           onpopupshowing="document.getBindingParent(this).optionsShowing();">
               <xul:menuitem anonid="neverForLanguage"
                             oncommand="document.getBindingParent(this).neverForLanguage();"/>
               <xul:menuitem anonid="neverForSite"
                             oncommand="document.getBindingParent(this).neverForSite();"
                             label="&translation.options.neverForSite.label;"
                             accesskey="&translation.options.neverForSite.accesskey;"/>
               <xul:menuseparator/>
               <xul:menuitem oncommand="openPreferences('paneContent');"
                             label="&translation.options.preferences.label;"
                             accesskey="&translation.options.preferences.accesskey;"/>
+              <xul:menuitem class="translation-attribution subviewbutton panel-subview-footer"
+                            oncommand="document.getBindingParent(this).openProviderAttribution();">
+                <xul:label>Übersetzungen von</xul:label>
+                <xul:image src="chrome://browser/content/microsoft-translator-attribution.png"
+                           aria-label="Microsoft Translator"/>
+              </xul:menuitem>
             </xul:menupopup>
           </xul:button>
 
         </xul:hbox>
         <xul:toolbarbutton ondblclick="event.stopPropagation();"
                            class="messageCloseButton close-icon tabbable"
                            xbl:inherits="hidden=hideclose"
                            tooltiptext="&closeNotification.tooltip;"
@@ -305,11 +313,19 @@
             let perms = Services.perms;
             perms.add(uri, "translate", perms.DENY_ACTION);
 
             this.close();
           ]]>
         </body>
       </method>
 
+      <method name="openProviderAttribution">
+        <body>
+          <![CDATA[
+            Translation.openProviderAttribution();
+          ]]>
+        </body>
+      </method>
+
     </implementation>
   </binding>
 </bindings>
--- a/browser/config/mozconfigs/linux32/debug
+++ b/browser/config/mozconfigs/linux32/debug
@@ -1,14 +1,17 @@
 ac_add_options --enable-debug
 ac_add_options --enable-dmd
 ac_add_options --enable-signmar
 
 ac_add_options --disable-unified-compilation
 
+MOZ_AUTOMATION_TALOS_SENDCHANGE=0
+MOZ_AUTOMATION_L10N_CHECK=0
+
 . $topsrcdir/build/unix/mozconfig.linux32
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 #Use ccache
 . "$topsrcdir/build/mozconfig.cache"
 
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -1,12 +1,15 @@
 ac_add_options --enable-debug
 ac_add_options --enable-dmd
 ac_add_options --enable-signmar
 
+MOZ_AUTOMATION_TALOS_SENDCHANGE=0
+MOZ_AUTOMATION_L10N_CHECK=0
+
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 # Use ccache
 . "$topsrcdir/build/mozconfig.cache"
 
--- a/browser/config/mozconfigs/linux64/debug-static-analysis-clang
+++ b/browser/config/mozconfigs/linux64/debug-static-analysis-clang
@@ -1,8 +1,15 @@
+MOZ_AUTOMATION_BUILD_SYMBOLS=0
+MOZ_AUTOMATION_PACKAGE_TESTS=0
+MOZ_AUTOMATION_UNITTEST_SENDCHANGE=0
+MOZ_AUTOMATION_TALOS_SENDCHANGE=0
+MOZ_AUTOMATION_L10N_CHECK=0
+MOZ_AUTOMATION_CHECK=0
+
 . "$topsrcdir/build/mozconfig.common"
 
 ac_add_options --enable-debug
 
 ac_add_options --disable-unified-compilation
 
 # Use Clang as specified in manifest
 export CC="$topsrcdir/clang/bin/clang"
--- a/browser/config/mozconfigs/linux64/nightly-nonunified
+++ b/browser/config/mozconfigs/linux64/nightly-nonunified
@@ -1,3 +1,8 @@
+MOZ_AUTOMATION_UPLOAD=0
+MOZ_AUTOMATION_UNITTEST_SENDCHANGE=0
+MOZ_AUTOMATION_TALOS_SENDCHANGE=0
+MOZ_AUTOMATION_CHECK=0
+
 . "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
 
 ac_add_options --disable-unified-compilation
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -4,19 +4,19 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOZ_APP_BASENAME=Firefox
 MOZ_APP_VENDOR=Mozilla
 MOZ_UPDATER=1
 MOZ_PHOENIX=1
 
 if test "$OS_ARCH" = "WINNT"; then
+  MOZ_MAINTENANCE_SERVICE=1
   if ! test "$HAVE_64BIT_OS"; then
     MOZ_VERIFY_MAR_SIGNATURE=1
-    MOZ_MAINTENANCE_SERVICE=1
     if test "$MOZ_UPDATE_CHANNEL" = "nightly" -o \
             "$MOZ_UPDATE_CHANNEL" = "aurora" -o \
             "$MOZ_UPDATE_CHANNEL" = "beta" -o \
             "$MOZ_UPDATE_CHANNEL" = "release"; then
       if ! test "$MOZ_DEBUG"; then
         MOZ_STUB_INSTALLER=1
       fi
     fi
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -1561,17 +1561,17 @@ Experiments.ExperimentEntry.prototype = 
 
     return Task.spawn(function ExperimentEntry_runFilterFunction_task() {
       const nullprincipal = Cc["@mozilla.org/nullprincipal;1"].createInstance(Ci.nsIPrincipal);
       let options = {
         sandboxName: "telemetry experiments jsfilter sandbox",
         wantComponents: false,
       };
 
-      let sandbox = Cu.Sandbox(nullprincipal);
+      let sandbox = Cu.Sandbox(nullprincipal, options);
       try {
         Cu.evalInSandbox(jsfilter, sandbox);
       } catch (e) {
         this._log.error("runFilterFunction() - failed to eval jsfilter: " + e.message);
         throw ["jsfilter-evalfailed"];
       }
 
       // You can't insert arbitrarily complex objects into a sandbox, so
--- a/browser/installer/windows/nsis/maintenanceservice_installer.nsi
+++ b/browser/installer/windows/nsis/maintenanceservice_installer.nsi
@@ -70,24 +70,21 @@ OutFile "maintenanceservice_installer.ex
 ; Get installation folder from registry if available
 InstallDirRegKey HKLM "Software\Mozilla\MaintenanceService" ""
 
 SetOverwrite on
 
 !define MaintUninstallKey \
  "Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService"
 
-; The HAVE_64BIT_OS define also means that we have an x64 build,
-; not just an x64 OS.
-!ifdef HAVE_64BIT_OS
-  ; See below, we actually abort the install for x64 builds currently.
-  InstallDir "$PROGRAMFILES64\${MaintFullName}\"
-!else
-  InstallDir "$PROGRAMFILES32\${MaintFullName}\"
-!endif
+; Always install into the 32-bit location even if we have a 64-bit build.
+; This is because we use only 1 service for all Firefox channels.
+; Allow either x86 and x64 builds to exist at this location, depending on
+; what is the latest build.
+InstallDir "$PROGRAMFILES32\${MaintFullName}\"
 ShowUnInstDetails nevershow
 
 ################################################################################
 # Modern User Interface - MUI
 
 !define MUI_ICON setup.ico
 !define MUI_UNICON setup.ico
 !define MUI_WELCOMEPAGE_TITLE_3LINES
@@ -116,23 +113,16 @@ BrandingText " "
 
 Function .onInit
   ; Remove the current exe directory from the search order.
   ; This only effects LoadLibrary calls and not implicitly loaded DLLs.
   System::Call 'kernel32::SetDllDirectoryW(w "")'
 
   SetSilent silent
 
-!ifdef HAVE_64BIT_OS
-  ; We plan to eventually enable 64bit native builds to use the maintenance
-  ; service, but for the initial release, to reduce testing and development,
-  ; 64-bit builds will not install the maintenanceservice.
-  Abort
-!endif
-
   ; On Windows 2000 we do not install the maintenance service.
   ; We won't run this installer from the parent installer, but just in case 
   ; someone tries to execute it on Windows 2000...
   ${Unless} ${AtLeastWinXP}
     Abort
   ${EndUnless}
 FunctionEnd
 
@@ -200,18 +190,17 @@ Section "MaintenanceService"
   WriteUninstaller "$INSTDIR\Uninstall.exe"
   WriteRegStr HKLM "${MaintUninstallKey}" "DisplayName" "${MaintFullName}"
   WriteRegStr HKLM "${MaintUninstallKey}" "UninstallString" \
                    '"$INSTDIR\uninstall.exe"'
   WriteRegStr HKLM "${MaintUninstallKey}" "DisplayIcon" \
                    "$INSTDIR\Uninstall.exe,0"
   WriteRegStr HKLM "${MaintUninstallKey}" "DisplayVersion" "${AppVersion}"
   WriteRegStr HKLM "${MaintUninstallKey}" "Publisher" "Mozilla"
-  WriteRegStr HKLM "${MaintUninstallKey}" "Comments" \
-                   "${BrandFullName} ${AppVersion} (${ARCH} ${AB_CD})"
+  WriteRegStr HKLM "${MaintUninstallKey}" "Comments" "${BrandFullName}"
   WriteRegDWORD HKLM "${MaintUninstallKey}" "NoModify" 1
   ${GetSize} "$INSTDIR" "/S=0K" $R2 $R3 $R4
   WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2
 
   ; Write out that a maintenance service was attempted.
   ; We do this because on upgrades we will check this value and we only
   ; want to install once on the first upgrade to maintenance service.
   ; Also write out that we are currently installed, preferences will check
--- a/browser/locales/en-US/chrome/browser/loop/loop.properties
+++ b/browser/locales/en-US/chrome/browser/loop/loop.properties
@@ -1,16 +1,30 @@
+# 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/.
+
+# Panel Strings
+
 get_link_to_share=Get a link and invite someone to talk
+share_link_url=Share the link below with your friend to start your call!
+do_not_disturb=Do not disturb
+
 get_a_call_url=Get a call url
 new_url=New url
+caller.placeholder=Identify this call
+
 unable_retrieve_url=Sorry, we were unable to retrieve a call url.
-share_link_url=Share the link below with your friend to start your call!
-caller.placeholder=Identify this call
-cannot_start_call_session_not_ready=Can't start call, session is not ready.
-network_disconnected=The network connection terminated abruptly.
-peer_ended_conversation=Your peer ended the conversation.
-stop=Stop
-call_has_ended=Your call has ended.
-close_window=Close this window
-do_not_disturb=Do not disturb
+
+# Conversation Window Strings
+
+incoming_call_title=Incoming Call…
 incoming_call=Incoming call
 accept_button=Accept
 decline_button=Decline
+stop=Stop
+
+peer_ended_conversation=Your peer ended the conversation.
+call_has_ended=Your call has ended.
+close_window=Close this window
+
+cannot_start_call_session_not_ready=Can't start call, session is not ready.
+network_disconnected=The network connection terminated abruptly.
--- a/browser/modules/TabCrashReporter.jsm
+++ b/browser/modules/TabCrashReporter.jsm
@@ -74,17 +74,17 @@ this.TabCrashReporter = {
         if (browser.isRemoteBrowser)
           continue;
 
         let doc = browser.contentDocument;
         if (!doc.documentURI.startsWith("about:tabcrashed"))
           continue;
 
         let url = browser.currentURI.spec;
-        window.gBrowser.updateBrowserRemoteness(browser, url);
+        window.gBrowser.updateBrowserRemotenessByURL(browser, url);
         browser.loadURIWithFlags(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null);
       }
     }
   },
 
   onAboutTabCrashedLoad: function (aBrowser) {
     if (!this.childMap)
       return;
--- a/browser/modules/test/unit/social/head.js
+++ b/browser/modules/test/unit/social/head.js
@@ -80,16 +80,17 @@ function initApp() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
   // prepare a blocklist file for the blocklist service
   var blocklistFile = gProfD.clone();
   blocklistFile.append("blocklist.xml");
   if (blocklistFile.exists())
     blocklistFile.remove(false);
   var source = do_get_file("blocklist.xml");
   source.copyTo(gProfD, "blocklist.xml");
+  blocklistFile.lastModifiedTime = Date.now();
 
 
   let internalManager = Cc["@mozilla.org/addons/integration;1"].
                      getService(Ci.nsIObserver).
                      QueryInterface(Ci.nsITimerCallback);
 
   internalManager.observe(null, "addons-startup", null);
 }
--- a/browser/themes/linux/preferences/preferences.css
+++ b/browser/themes/linux/preferences/preferences.css
@@ -49,16 +49,22 @@ radio[pane=paneSync] {
 label.small {
   font-size: smaller;
 }
 
 #tabPrefsBox {
   margin: 5px;
 }
 
+/* Content Pane */
+#translationAttributionImage {
+  width: 70px;
+  cursor: pointer;
+}
+
 /* Applications Pane */
 #BrowserPreferences[animated="true"] #handlersView {
   height: 25em;
 }
 
 #BrowserPreferences[animated="false"] #handlersView {
   -moz-box-flex: 1;
 }
--- a/browser/themes/osx/preferences/preferences.css
+++ b/browser/themes/osx/preferences/preferences.css
@@ -135,16 +135,21 @@ caption {
 }
 
 #popupPolicyRow {
   margin-bottom: 4px !important;
   padding-bottom: 4px !important;
   border-bottom: 1px solid #ccc;
 }
 
+#translationAttributionImage {
+  width: 70px;
+  cursor: pointer;
+}
+
 #browserUseCurrent,
 #browserUseBookmark,
 #browserUseBlank {
   margin-top: 10px;
 }
 
 #advancedPrefs {
   margin: 0 8px;
--- a/browser/themes/shared/translation/infobar.inc.css
+++ b/browser/themes/shared/translation/infobar.inc.css
@@ -41,8 +41,26 @@ notification[value="translation"] menuli
 
 notification[value="translation"] menulist > .menulist-dropmarker {
   -moz-appearance: toolbarbutton-dropdown;
   border: none;
   background-color: transparent;
   margin: auto;
   padding: 5px 0;
 }
+
+.translation-menupopup arrowscrollbox {
+  padding-bottom: 0;
+}
+
+.translation-attribution {
+  cursor: pointer;
+  -moz-box-align: end;
+  font-size: small;
+}
+
+.translation-attribution > label {
+  margin-bottom: 0;
+}
+
+.translation-attribution > image {
+  width: 70px;
+}
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2438,16 +2438,20 @@ notification[value="translation"] {
 }
 
 .translated-notification-icon,
 #translated-notification-icon {
   list-style-image: url(chrome://browser/skin/translation-16.png);
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
+.translation-menupopup {
+  -moz-appearance: none;
+}
+
 /* Bookmarks roots menu-items */
 #subscribeToPageMenuitem:not([disabled]),
 #subscribeToPageMenupopup,
 #BMB_subscribeToPageMenuitem:not([disabled]),
 #BMB_subscribeToPageMenupopup {
   list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
 }
 
--- a/browser/themes/windows/preferences/preferences.css
+++ b/browser/themes/windows/preferences/preferences.css
@@ -48,16 +48,22 @@ radio[pane=paneSync] {
 label.small {
   font-size: smaller;
 }
 
 #tabPrefsBox {
   margin: 6px;
 }
 
+/* Content Pane */
+#translationAttributionImage {
+  width: 70px;
+  cursor: pointer;
+}
+
 /* Applications Pane */
 #BrowserPreferences[animated="true"] #handlersView {
   height: 25em;
 }
 
 #BrowserPreferences[animated="false"] #handlersView {
   -moz-box-flex: 1;
 }
--- a/build/autoconf/altoptions.m4
+++ b/build/autoconf/altoptions.m4
@@ -13,17 +13,16 @@ dnl Send comments, improvements, bugs to
 dnl MOZ_ARG_ENABLE_BOOL(           NAME, HELP, IF-YES [, IF-NO [, ELSE]])
 dnl MOZ_ARG_DISABLE_BOOL(          NAME, HELP, IF-NO [, IF-YES [, ELSE]])
 dnl MOZ_ARG_ENABLE_STRING(         NAME, HELP, IF-SET [, ELSE])
 dnl MOZ_ARG_ENABLE_BOOL_OR_STRING( NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
 dnl MOZ_ARG_WITH_BOOL(             NAME, HELP, IF-YES [, IF-NO [, ELSE])
 dnl MOZ_ARG_WITHOUT_BOOL(          NAME, HELP, IF-NO [, IF-YES [, ELSE])
 dnl MOZ_ARG_WITH_STRING(           NAME, HELP, IF-SET [, ELSE])
 dnl MOZ_ARG_HEADER(Comment)
-dnl MOZ_CHECK_PTHREADS(            NAME, IF-YES [, ELSE ])
 dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
 
 
 dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE])
 AC_DEFUN([MOZ_TWO_STRING_TEST],
 [if test "[$2]" = "[$3]"; then
     ifelse([$4], , :, [$4])
   elif test "[$2]" = "[$5]"; then
@@ -75,48 +74,15 @@ AC_DEFUN([MOZ_ARG_WITHOUT_BOOL],
 dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE])
 AC_DEFUN([MOZ_ARG_WITH_STRING],
 [AC_ARG_WITH([$1], [$2], [$3], [$4])])
 
 dnl MOZ_ARG_HEADER(Comment)
 dnl This is used by webconfig to group options
 define(MOZ_ARG_HEADER, [# $1])
 
-dnl
-dnl Apparently, some systems cannot properly check for the pthread
-dnl library unless <pthread.h> is included so we need to test
-dnl using it
-dnl
-dnl MOZ_CHECK_PTHREADS(lib, success, failure)
-AC_DEFUN([MOZ_CHECK_PTHREADS],
-[
-AC_MSG_CHECKING([for pthread_create in -l$1])
-echo "
-    #include <pthread.h>
-    #include <stdlib.h>
-    void *foo(void *v) { int a = 1;  } 
-    int main() { 
-        pthread_t t;
-        if (!pthread_create(&t, 0, &foo, 0)) {
-            pthread_join(t, 0);
-        }
-        exit(0);
-    }" > dummy.c ;
-    echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS" 1>&5;
-    ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS 2>&5;
-    _res=$? ;
-    rm -f dummy.c dummy${ac_exeext} ;
-    if test "$_res" = "0"; then
-        AC_MSG_RESULT([yes])
-        [$2]
-    else
-        AC_MSG_RESULT([no])
-        [$3]
-    fi
-])
-
 dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
 AC_DEFUN([MOZ_READ_MOZCONFIG],
 [AC_REQUIRE([AC_INIT_BINSH])dnl
 # Read in '.mozconfig' script to set the initial options.
 # See the mozconfig2configure script for more details.
 _AUTOCONF_TOOLS_DIR=`dirname [$]0`/[$1]/build/autoconf
 . $_AUTOCONF_TOOLS_DIR/mozconfig2configure])
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -469,17 +469,17 @@ class Automation(object):
         status = self.Process([pk12util, "-i", os.path.join(certPath, item), "-w",
                     pwfilePath, "-d", profileDir], 
                     env = env).wait()
         automationutils.printstatus(status, "pk12util")
 
     os.unlink(pwfilePath)
     return 0
 
-  def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None):
+  def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None):
     if xrePath == None:
       xrePath = self.DIST_BIN
     if env == None:
       env = dict(os.environ)
 
     ldLibraryPath = os.path.abspath(os.path.join(SCRIPT_DIR, xrePath))
     dmdLibrary = None
     preloadEnvVar = None
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -443,17 +443,17 @@ def parseKeyValue(strings, separator='='
 
 def systemMemory():
   """
   Returns total system memory in kilobytes.
   Works only on unix-like platforms where `free` is in the path.
   """
   return int(os.popen("free").readlines()[1].split()[1])
 
-def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=None):
+def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None):
   """populate OS environment variables for mochitest"""
 
   env = os.environ.copy() if env is None else env
 
   assert os.path.isabs(xrePath)
 
   ldLibraryPath = xrePath
 
@@ -516,21 +516,40 @@ def environment(xrePath, env=None, crash
         log.info("TEST-UNEXPECTED-FAIL | runtests.py | Failed to find ASan symbolizer at %s", llvmsym)
 
       totalMemory = systemMemory()
 
       # Only 4 GB RAM or less available? Use custom ASan options to reduce
       # the amount of resources required to do the tests. Standard options
       # will otherwise lead to OOM conditions on the current test slaves.
       message = "INFO | runtests.py | ASan running in %s configuration"
+      asanOptions = []
       if totalMemory <= 1024 * 1024 * 4:
         message = message % 'low-memory'
-        env["ASAN_OPTIONS"] = "quarantine_size=50331648:malloc_context_size=5"
+        asanOptions = ['quarantine_size=50331648', 'malloc_context_size=5']
       else:
         message = message % 'default memory'
+
+      if lsanPath:
+        log.info("LSan enabled.")
+        asanOptions.append('detect_leaks=1')
+        lsanOptions = ["exitcode=0"]
+        suppressionsFile = os.path.join(lsanPath, 'lsan_suppressions.txt')
+        if os.path.exists(suppressionsFile):
+          log.info("LSan using suppression file " + suppressionsFile)
+          lsanOptions.append("suppressions=" + suppressionsFile)
+        else:
+          log.info("WARNING | runtests.py | LSan suppressions file does not exist! " + suppressionsFile)
+        env["LSAN_OPTIONS"] = ':'.join(lsanOptions)
+        # Run shutdown GCs and CCs to avoid spurious leaks.
+        env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1'
+
+      if len(asanOptions):
+        env['ASAN_OPTIONS'] = ':'.join(asanOptions)
+
     except OSError,err:
       log.info("Failed determine available memory, disabling ASan low-memory configuration: %s", err.strerror)
     except:
       log.info("Failed determine available memory, disabling ASan low-memory configuration")
     else:
       log.info(message)
 
   return env
@@ -673,8 +692,103 @@ class ShutdownLeaks(object):
     counted = set()
 
     for url in leakedWindows:
       if not url in counted:
         counts.append((url, leakedWindows.count(url)))
         counted.add(url)
 
     return sorted(counts, key=itemgetter(1), reverse=True)
+
+
+class LSANLeaks(object):
+  """
+  Parses the log when running an LSAN build, looking for interesting stack frames
+  in allocation stacks, and prints out reports.
+  """
+
+  def __init__(self, logger):
+    self.logger = logger
+    self.inReport = False
+    self.foundFrames = set([])
+    self.recordMoreFrames = None
+    self.currStack = None
+    self.maxNumRecordedFrames = 4
+
+    # Don't various allocation-related stack frames, as they do not help much to
+    # distinguish different leaks.
+    unescapedSkipList = [
+      "malloc", "js_malloc", "malloc_", "__interceptor_malloc", "moz_malloc", "moz_xmalloc",
+      "calloc", "js_calloc", "calloc_", "__interceptor_calloc", "moz_calloc", "moz_xcalloc",
+      "realloc","js_realloc", "realloc_", "__interceptor_realloc", "moz_realloc", "moz_xrealloc",
+      "new",
+      "js::MallocProvider",
+    ]
+    self.skipListRegExp = re.compile("^" + "|".join([re.escape(f) for f in unescapedSkipList]) + "$")
+
+    self.startRegExp = re.compile("==\d+==ERROR: LeakSanitizer: detected memory leaks")
+    self.stackFrameRegExp = re.compile("    #\d+ 0x[0-9a-f]+ in ([^(</]+)")
+    self.sysLibStackFrameRegExp = re.compile("    #\d+ 0x[0-9a-f]+ \(([^+]+)\+0x[0-9a-f]+\)")
+
+
+  def log(self, line):
+    if re.match(self.startRegExp, line):
+      self.inReport = True
+      return
+
+    if not self.inReport:
+      return
+
+    if line.startswith("Direct leak"):
+      self._finishStack()
+      self.recordMoreFrames = True
+      self.currStack = []
+      return
+
+    if line.startswith("Indirect leak"):
+      self._finishStack()
+      # Only report direct leaks, in the hope that they are less flaky.
+      self.recordMoreFrames = False
+      return
+
+    if line.startswith("SUMMARY: AddressSanitizer"):
+      self._finishStack()
+      self.inReport = False
+      return
+
+    if not self.recordMoreFrames:
+      return
+
+    stackFrame = re.match(self.stackFrameRegExp, line)
+    if stackFrame:
+      # Split the frame to remove any return types.
+      frame = stackFrame.group(1).split()[-1]
+      if not re.match(self.skipListRegExp, frame):
+        self._recordFrame(frame)
+      return
+
+    sysLibStackFrame = re.match(self.sysLibStackFrameRegExp, line)
+    if sysLibStackFrame:
+      # System library stack frames will never match the skip list,
+      # so don't bother checking if they do.
+      self._recordFrame(sysLibStackFrame.group(1))
+
+    # If we don't match either of these, just ignore the frame.
+    # We'll end up with "unknown stack" if everything is ignored.
+
+  def process(self):
+    for f in self.foundFrames:
+      self.logger("TEST-UNEXPECTED-FAIL | LeakSanitizer | leak at " + f)
+
+  def _finishStack(self):
+    if self.recordMoreFrames and len(self.currStack) == 0:
+      self.currStack = ["unknown stack"]
+    if self.currStack:
+      self.foundFrames.add(", ".join(self.currStack))
+      self.currStack = None
+    self.recordMoreFrames = False
+    self.numRecordedFrames = 0
+
+  def _recordFrame(self, frame):
+    self.currStack.append(frame)
+    self.numRecordedFrames += 1
+    if self.numRecordedFrames >= self.maxNumRecordedFrames:
+      self.recordMoreFrames = False
--- a/build/gen_mach_buildprops.py
+++ b/build/gen_mach_buildprops.py
@@ -1,15 +1,20 @@
 #!/usr/bin/python
 #
 # 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/.
 
-import sys, os, sha, json, re
+import sys
+import os
+import sha
+import json
+import re
+import errno
 from argparse import ArgumentParser
 
 def getFileHashAndSize(filename):
     sha1Hash = 'UNKNOWN'
     size = 'UNKNOWN'
 
     try:
         # open in binary mode to make sure we get consistent results
@@ -46,25 +51,30 @@ def getUrlProperties(filename):
         ('jsshellUrl', lambda m: 'jsshell-' in m and m.endswith('.zip')),
         ('completeMarUrl', lambda m: m.endswith('.complete.mar')),
         # packageUrl must be last!
         ('packageUrl', lambda m: True),
     ]
     url_re = re.compile(r'''^(https?://.*?\.(?:tar\.bz2|dmg|zip|apk|rpm|mar|tar\.gz))$''')
     properties = {}
 
-    with open(filename) as f:
-        for line in f:
-            m = url_re.match(line)
-            if m:
-                m = m.group(1)
-                for prop, condition in property_conditions:
-                    if condition(m):
-                        properties.update({prop: m})
-                        break
+    try:
+        with open(filename) as f:
+            for line in f:
+                m = url_re.match(line)
+                if m:
+                    m = m.group(1)
+                    for prop, condition in property_conditions:
+                        if condition(m):
+                            properties.update({prop: m})
+                            break
+    except IOError as e:
+        if e.errno != errno.ENOENT:
+            raise
+        properties = {prop: 'UNKNOWN' for prop, condition in property_conditions}
     return properties
 
 if __name__ == '__main__':
     parser = ArgumentParser(description='Generate mach_build_properties.json for automation builds.')
     parser.add_argument("--complete-mar-file", required=True,
                         action="store", dest="complete_mar_file",
                         help="Path to the complete MAR file, relative to the objdir.")
     parser.add_argument("--upload-output", required=True,
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -33,16 +33,17 @@ SEARCH_PATHS = [
     'python/configobj',
     'python/jsmin',
     'python/psutil',
     'python/which',
     'build/pymake',
     'config',
     'dom/bindings',
     'dom/bindings/parser',
+    'layout/tools/reftest',
     'other-licenses/ply',
     'xpcom/idl-parser',
     'testing',
     'testing/xpcshell',
     'testing/marionette/client',
     'testing/marionette/client/marionette',
     'testing/marionette/transport',
     'testing/mozbase/mozcrash',
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -43,17 +43,17 @@ class RemoteAutomation(Automation):
 
     def setProduct(self, product):
         self._product = product
 
     def setRemoteLog(self, logfile):
         self._remoteLog = logfile
 
     # Set up what we need for the remote environment
-    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None):
+    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None):
         # Because we are running remote, we don't want to mimic the local env
         # so no copying of os.environ
         if env is None:
             env = {}
 
         if dmdPath:
             env['DMD'] = '1'
             env['MOZ_REPLACE_MALLOC_LIB'] = os.path.join(dmdPath, 'libdmd.so')
--- a/build/moz-automation.mk
+++ b/build/moz-automation.mk
@@ -12,63 +12,67 @@ endif
 endif
 
 include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
 
 # Log file from the 'make upload' step. We need this to parse out the URLs of
 # the uploaded files.
 AUTOMATION_UPLOAD_OUTPUT = $(DIST)/automation-upload.txt
 
+# Helper variables to convert from MOZ_AUTOMATION_* variables to the
+# corresponding the make target
+tier_BUILD_SYMBOLS = buildsymbols
+tier_CHECK = check
+tier_L10N_CHECK = l10n-check
+tier_PACKAGE = package
+tier_PACKAGE_TESTS = package-tests
+tier_UPDATE_PACKAGING = update-packaging
+tier_UPLOAD_SYMBOLS = uploadsymbols
+tier_UPLOAD = upload
+
 # Automation build steps. Everything in MOZ_AUTOMATION_TIERS also gets used in
 # TIERS for mach display. As such, the MOZ_AUTOMATION_TIERS are roughly sorted
 # here in the order that they will be executed (since mach doesn't know of the
 # dependencies between them).
-
-MOZ_AUTOMATION_TIERS += package-tests
-MOZ_AUTOMATION_TIERS += buildsymbols
-
-ifdef NIGHTLY_BUILD
-MOZ_AUTOMATION_TIERS += uploadsymbols
-endif
-
-ifdef MOZ_UPDATE_PACKAGING
-MOZ_AUTOMATION_TIERS += update-packaging
-automation/upload: automation/update-packaging
-automation/update-packaging: automation/package
-endif
-
-MOZ_AUTOMATION_TIERS += package
-MOZ_AUTOMATION_TIERS += check
-
-ifndef MOZ_ASAN
-MOZ_AUTOMATION_TIERS += l10n-check
-automation/l10n-check: automation/package
-endif
-
-MOZ_AUTOMATION_TIERS += upload
-
-automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
-	$(PYTHON) $(topsrcdir)/build/gen_mach_buildprops.py --complete-mar-file $(DIST)/$(COMPLETE_MAR) --upload-output $(AUTOMATION_UPLOAD_OUTPUT)
+moz_automation_symbols = PACKAGE_TESTS BUILD_SYMBOLS UPLOAD_SYMBOLS PACKAGE UPDATE_PACKAGING CHECK L10N_CHECK UPLOAD
+MOZ_AUTOMATION_TIERS := $(foreach sym,$(moz_automation_symbols),$(if $(filter 1,$(MOZ_AUTOMATION_$(sym))),$(tier_$(sym))))
 
 # Dependencies between automation build steps
 automation/uploadsymbols: automation/buildsymbols
 
+automation/update-packaging: automation/package
+
+automation/l10n-check: automation/package
+
 automation/upload: automation/package
 automation/upload: automation/package-tests
 automation/upload: automation/buildsymbols
+automation/upload: automation/update-packaging
 
 # automation/package and automation/check should depend on build (which is
 # implicit due to the way client.mk invokes automation/build), but buildsymbols
 # changes the binaries/libs, and that's what we package/test.
 automation/package: automation/buildsymbols
 automation/check: automation/buildsymbols
 
+automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
+	$(PYTHON) $(topsrcdir)/build/gen_mach_buildprops.py --complete-mar-file $(DIST)/$(COMPLETE_MAR) --upload-output $(AUTOMATION_UPLOAD_OUTPUT)
+
 # make check runs with the keep-going flag so we can see all the failures
 AUTOMATION_EXTRA_CMDLINE-check = -k
 
 # We need the log from make upload to grep it for urls in order to set
 # properties.
 AUTOMATION_EXTRA_CMDLINE-upload = 2>&1 | tee $(AUTOMATION_UPLOAD_OUTPUT)
 
+# The commands only run if the corresponding MOZ_AUTOMATION_* variable is
+# enabled. This means, for example, if we enable MOZ_AUTOMATION_UPLOAD, then
+# 'buildsymbols' will only run if MOZ_AUTOMATION_BUILD_SYMBOLS is also set.
+# However, the target automation/buildsymbols will still be executed in this
+# case because it is a prerequisite of automation/upload.
+define automation_commands
+$(call BUILDSTATUS,TIER_START $1)
+@$(MAKE) $1 $(AUTOMATION_EXTRA_CMDLINE-$1)
+$(call BUILDSTATUS,TIER_FINISH $1)
+endef
+
 automation/%:
-	$(call BUILDSTATUS,TIER_START $*)
-	@$(MAKE) $* $(AUTOMATION_EXTRA_CMDLINE-$*)
-	$(call BUILDSTATUS,TIER_FINISH $*)
+	$(if $(filter $*,$(MOZ_AUTOMATION_TIERS)),$(call automation_commands,$*))
new file mode 100644
--- /dev/null
+++ b/build/mozconfig.automation
@@ -0,0 +1,21 @@
+# 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/.
+
+# Common mozconfig for automation builds.
+#
+# We export MOZ_AUTOMATION_* variables here to trigger various steps in
+# automation builds.  For example, if MOZ_AUTOMATION_PACKAGE is set, then the
+# package step will run.  This file contains the default settings, which can be
+# overridden by setting them earlier in the appropriate mozconfig.
+
+mk_add_options "export MOZ_AUTOMATION_BUILD_SYMBOLS=${MOZ_AUTOMATION_BUILD_SYMBOLS-1}"
+mk_add_options "export MOZ_AUTOMATION_CHECK=${MOZ_AUTOMATION_CHECK-1}"
+mk_add_options "export MOZ_AUTOMATION_L10N_CHECK=${MOZ_AUTOMATION_L10N_CHECK-1}"
+mk_add_options "export MOZ_AUTOMATION_PACKAGE=${MOZ_AUTOMATION_PACKAGE-1}"
+mk_add_options "export MOZ_AUTOMATION_PACKAGE_TESTS=${MOZ_AUTOMATION_PACKAGE_TESTS-1}"
+mk_add_options "export MOZ_AUTOMATION_TALOS_SENDCHANGE=${MOZ_AUTOMATION_TALOS_SENDCHANGE-1}"
+mk_add_options "export MOZ_AUTOMATION_UNITTEST_SENDCHANGE=${MOZ_AUTOMATION_UNITTEST_SENDCHANGE-1}"
+mk_add_options "export MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-0}"
+mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}"
+mk_add_options "export MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-0}"
--- a/build/mozconfig.common
+++ b/build/mozconfig.common
@@ -10,8 +10,10 @@
 # another mozconfig file, you'll need to use mozconfig.common.override instead
 # of this file.
 
 mk_add_options AUTOCLOBBER=1
 
 ac_add_options --enable-crashreporter
 
 ac_add_options --enable-release
+
+. "$topsrcdir/build/mozconfig.automation"
new file mode 100644
--- /dev/null
+++ b/build/sanitizers/lsan_suppressions.txt
@@ -0,0 +1,108 @@
+### !!! Please do not add suppressions for new leaks in Gecko code, unless they are intentional !!!
+
+###
+### Some of these leak in every test run.
+###
+
+# LSan runs with a shallow stack depth and no debug symbols, so some small intentional
+# leaks in system libraries show up with this.  You do not want this enabled
+# when running locally with a deep stack, as it can catch too much.
+leak:libc.so
+
+# nsComponentManagerImpl intentionally leaks factory entries, and probably some other stuff.
+leak:nsComponentManagerImpl
+# These two variants are needed when fast unwind is disabled and stack depth is limited.
+leak:mozJSComponentLoader::LoadModule
+leak:nsNativeModuleLoader::LoadModule
+
+# Bug 980109 - Freeing this properly on shutdown is hard.
+leak:profiler_init
+
+# Bug 981220 - Pixman fails to free TLS memory.
+leak:pixman_implementation_lookup_composite
+
+# Bug 987918 - Font shutdown leaks when CLEANUP_MEMORY is not enabled.
+leak:libfontconfig.so
+leak:GI___strdup
+# The symbol is really __GI___strdup, but if you have the leading _, it doesn't suppress it.
+
+
+###
+### Many leaks only affect some test suites.  The suite annotations are not checked.
+###
+
+# Bug 800200 - JSD1 is leaking, but it is about to be removed, so ignore it. m4
+leak:jsd_CreateLock
+leak:jsdScript::GetExecutableLines
+leak:jsdService::ActivateDebugger
+
+# Bug 979928 - WebRTC is leaky. m2, m3
+leak:/media/mtransport/
+leak:/media/webrtc/signaling/
+
+# Bug 981195 - Small leak in the parser. m4
+leak:TypeCompartment::fixObjectType
+
+# Bug 982111 - WebM is leaking. m1
+leak:nestegg_read_packet
+
+# Bug 987385 - Various plugin leaks. m3
+leak:mozilla::plugins::PPluginInstanceParent::CallNPP_HandleEvent
+leak:mozilla::plugins::PPluginModuleParent::OnCallReceived
+
+# Bug 987925 - Small leak under PK11_ChangePW. m5
+leak:sec_asn1e_allocate_item
+leak:PORT_Strdup_Util
+
+# Bug 1021302 - Leak of fds allocated in nsSocketTransport::BuildSocket(). m1, m5, dt, oth
+leak:nsSocketTransport::BuildSocket
+leak:nsServerSocket::OnSocketReady
+
+# Bug 1021350 - Small leak under event_base_once. m1, m4, bc3
+leak:event_base_once
+
+# Bug 1021854 - nsFileStreamBase::DoOpen() leaking fds. bc1, oth
+leak:nsLocalFile::OpenNSPRFileDesc
+
+# Bug 1021932 - AllocateArrayBufferContents leaks. m1
+# Bug 1023583 - Leak of array buffer data involving web audio and XHR::OnStopRequest(). m1
+# Bug 1023585 - Leak of array buffer in JSStructuredCloneWriter::transferOwnership(). m1
+leak:AllocateArrayBufferContents
+
+# Bug 1022010 - Small leak under _render_glyph_outline. bc1
+leak:_render_glyph_outline
+
+# Bug 1022042 - compareVariants in the test plugin leaks identifiers. oth
+leak:compareVariants(_NPP*,
+
+# Bug 1022954 - ScriptSource leaks sourceMapURL_ sometimes. dt
+leak:ScriptSource::setSourceMapURL
+
+# Bug 1023548 - Small leak under SECITEM_AllocItem_Util. bc1, bc3
+leak:SECITEM_AllocItem_Util
+
+# This is a one-time leak, so it is probably okay to ignore. bc1, oth
+leak:GlobalPrinters::InitializeGlobalPrinters
+leak:nsPSPrinterList::GetPrinterList
+
+# Bug 1028456 - More leaks with _PR_Getfd, in nsLocalFile::CopyToNative and do_create. bc1, bc3
+leak:_PR_Getfd
+
+
+###
+### Leaks with system libraries in their stacks. These show up across a number of tests.
+### Better symbols and disabling fast stackwalking may help diagnose these.
+###
+
+leak:libcairo.so
+leak:libdricore.so
+leak:libGL.so
+leak:libglib-2.0.so
+leak:libp11-kit.so
+leak:libpulse.so
+leak:libpulsecommon-1.1.so
+leak:libresolv.so
+leak:libstdc++.so
+leak:libXrandr.so
+leak:pthread_setspecific_internal
+leak:swrast_dri.so
--- a/build/unix/mozconfig.asan
+++ b/build/unix/mozconfig.asan
@@ -1,8 +1,14 @@
+if [ "x$IS_NIGHTLY" = "xyes" ]; then
+  MOZ_AUTOMATION_UPDATE_PACKAGING=1
+fi
+MOZ_AUTOMATION_TALOS_SENDCHANGE=0
+MOZ_AUTOMATION_L10N_CHECK=0
+
 . "$topsrcdir/build/mozconfig.common"
 
 # Use Clang as specified in manifest
 export CC="$topsrcdir/clang/bin/clang -fgnu89-inline"
 export CXX="$topsrcdir/clang/bin/clang++"
 export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
 
 # Mandatory flags for ASan
--- a/build/unix/mozconfig.linux
+++ b/build/unix/mozconfig.linux
@@ -1,8 +1,13 @@
+if [ "x$IS_NIGHTLY" = "xyes" ]; then
+  MOZ_AUTOMATION_UPLOAD_SYMBOLS=1
+  MOZ_AUTOMATION_UPDATE_PACKAGING=1
+fi
+
 . "$topsrcdir/build/mozconfig.common"
 
 # some b2g desktop builds still happen on i686 machines, and the tooltool
 # toolchain is x86_64 only.
 # We also deal with valgrind builds here, they don't use tooltool manifests at
 # all yet.
 if [ -z "$no_tooltool" ]
 then
--- a/build/virtualenv_packages.txt
+++ b/build/virtualenv_packages.txt
@@ -12,13 +12,14 @@ which.pth:python/which
 ply.pth:other-licenses/ply/
 codegen.pth:python/codegen/
 mock.pth:python/mock-1.0.0
 mozilla.pth:build
 mozilla.pth:config
 mozilla.pth:xpcom/typelib/xpt/tools
 mozilla.pth:dom/bindings
 mozilla.pth:dom/bindings/parser
+mozilla.pth:layout/tools/reftest
 moztreedocs.pth:tools/docs
 copy:build/buildconfig.py
 packages.txt:testing/mozbase/packages.txt
 objdir:build
 gyp.pth:media/webrtc/trunk/tools/gyp/pylib
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -11,30 +11,34 @@
 #include "prprf.h"
 
 #include "nsCOMPtr.h"
 #include "nsError.h"
 #include "nsEscape.h"
 #include "nsNetUtil.h"
 #include "nsString.h"
 
-#include "nsCSSStyleSheet.h"
+#include "mozilla/CSSStyleSheet.h"
+#include "mozilla/dom/URL.h"
 #include "nsIConsoleService.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMLocation.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsIDOMWindow.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIScriptError.h"
 #include "nsIWindowMediator.h"
-#include "mozilla/dom/URL.h"
 
 nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
+
+// DO NOT use namespace mozilla; it'll break due to a naming conflict between
+// mozilla::TextRange and a TextRange in OSX headers.
+using mozilla::CSSStyleSheet;
 using mozilla::dom::IsChromeURI;
 
 ////////////////////////////////////////////////////////////////////////////////
 
 void
 nsChromeRegistry::LogMessage(const char* aMsg, ...)
 {
   nsCOMPtr<nsIConsoleService> console 
@@ -289,17 +293,17 @@ nsChromeRegistry::ConvertChromeURL(nsIUR
 #else
     path.Insert("unix/", 0);
 #endif
   }
 
   if (!baseURI) {
     LogMessage("No chrome package registered for chrome://%s/%s/%s",
                package.get(), provider.get(), path.get());
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_FILE_NOT_FOUND;
   }
 
   return NS_NewURI(aResult, path, nullptr, baseURI);
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 // theme stuff
@@ -410,17 +414,17 @@ nsresult nsChromeRegistry::RefreshWindow
     nsCOMArray<nsIStyleSheet> newAgentSheets;
     for (int32_t l = 0; l < agentSheets.Count(); ++l) {
       nsIStyleSheet *sheet = agentSheets[l];
 
       nsIURI* uri = sheet->GetSheetURI();
 
       if (IsChromeURI(uri)) {
         // Reload the sheet.
-        nsRefPtr<nsCSSStyleSheet> newSheet;
+        nsRefPtr<CSSStyleSheet> newSheet;
         rv = document->LoadChromeSheetSync(uri, true,
                                            getter_AddRefs(newSheet));
         if (NS_FAILED(rv)) return rv;
         if (newSheet) {
           rv = newAgentSheets.AppendObject(newSheet) ? NS_OK : NS_ERROR_FAILURE;
           if (NS_FAILED(rv)) return rv;
         }
       }
@@ -449,22 +453,22 @@ nsresult nsChromeRegistry::RefreshWindow
     if (!oldSheets.AppendObject(styleSheet)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   // Iterate over our old sheets and kick off a sync load of the new
   // sheet if and only if it's a chrome URL.
   for (i = 0; i < count; i++) {
-    nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(oldSheets[i]);
+    nsRefPtr<CSSStyleSheet> sheet = do_QueryObject(oldSheets[i]);
     nsIURI* uri = sheet ? sheet->GetOriginalURI() : nullptr;
 
     if (uri && IsChromeURI(uri)) {
       // Reload the sheet.
-      nsRefPtr<nsCSSStyleSheet> newSheet;
+      nsRefPtr<CSSStyleSheet> newSheet;
       // XXX what about chrome sheets that have a title or are disabled?  This
       // only works by sheer dumb luck.
       document->LoadChromeSheetSync(uri, false, getter_AddRefs(newSheet));
       // Even if it's null, we put in in there.
       newSheets.AppendObject(newSheet);
     }
     else {
       // Just use the same sheet.
--- a/chrome/src/nsChromeRegistryChrome.cpp
+++ b/chrome/src/nsChromeRegistryChrome.cpp
@@ -267,17 +267,17 @@ nsChromeRegistryChrome::GetSelectedLocal
   if (NS_FAILED(rv))
     return rv;
   PackageEntry* entry =
       static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
                                                       & realpackage,
                                                       PL_DHASH_LOOKUP));
 
   if (PL_DHASH_ENTRY_IS_FREE(entry))
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_FILE_NOT_FOUND;
 
   aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE);
   if (aLocale.IsEmpty())
     return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
@@ -555,17 +555,17 @@ nsresult
 nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
                                             uint32_t* aFlags)
 {
   PackageEntry* entry =
       static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
                                                       & (nsACString&) aPackage,
                                                       PL_DHASH_LOOKUP));
   if (PL_DHASH_ENTRY_IS_FREE(entry))
-    return NS_ERROR_NOT_AVAILABLE;
+    return NS_ERROR_FILE_NOT_FOUND;
 
   *aFlags = entry->flags;
   return NS_OK;
 }
 
 PLHashNumber
 nsChromeRegistryChrome::HashKey(PLDHashTable *table, const void *key)
 {
--- a/configure.in
+++ b/configure.in
@@ -2799,23 +2799,23 @@ dnl ====================================
 dnl = pthread support
 dnl = Start by checking whether the system support pthreads
 dnl ========================================================
 case "$target_os" in
 darwin*)
     MOZ_USE_PTHREADS=1
     ;;
 *)
-    MOZ_CHECK_PTHREADS(pthreads,
+    AC_CHECK_LIB(pthreads, pthread_create,
         MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads",
-        MOZ_CHECK_PTHREADS(pthread,
+        AC_CHECK_LIB(pthread, pthread_create,
             MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread",
-            MOZ_CHECK_PTHREADS(c_r,
+            AC_CHECK_LIB(c_r, pthread_create,
                 MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r",
-                MOZ_CHECK_PTHREADS(c,
+                AC_CHECK_LIB(c, pthread_create,
                     MOZ_USE_PTHREADS=1
                 )
             )
         )
     )
     ;;
 esac
 
@@ -7796,59 +7796,16 @@ if test "$SOLARIS_SUNPRO_CC"; then
   PROFILE_USE_LDFLAGS="-xprofile=use:$_objdir/$enable_application"
 fi
 
 AC_SUBST(PROFILE_GEN_CFLAGS)
 AC_SUBST(PROFILE_GEN_LDFLAGS)
 AC_SUBST(PROFILE_USE_CFLAGS)
 AC_SUBST(PROFILE_USE_LDFLAGS)
 
-AC_LANG_CPLUSPLUS
-
-dnl ========================================================
-dnl Autoconf test for gcc 2.7.2.x (and maybe others?) so that we don't
-dnl provide non-const forms of the operator== for comparing nsCOMPtrs to
-dnl raw pointers in nsCOMPtr.h.  (VC++ has the same bug.)
-dnl ========================================================
-_SAVE_CXXFLAGS=$CXXFLAGS
-CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS}"
-AC_CACHE_CHECK(for correct overload resolution with const and templates,
-    ac_nscap_nonconst_opeq_bug,
-    [AC_TRY_COMPILE([
-                      template <class T>
-                      class Pointer
-                        {
-                        public:
-                          T* myPtr;
-                        };
-
-                      template <class T, class U>
-                      int operator==(const Pointer<T>& rhs, U* lhs)
-                        {
-                          return rhs.myPtr == lhs;
-                        }
-
-                      template <class T, class U>
-                      int operator==(const Pointer<T>& rhs, const U* lhs)
-                        {
-                          return rhs.myPtr == lhs;
-                        }
-                    ],
-                    [
-                      Pointer<int> foo;
-                      const int* bar;
-                      return foo == bar;
-                    ],
-                    ac_nscap_nonconst_opeq_bug="no",
-                    ac_nscap_nonconst_opeq_bug="yes")])
-CXXFLAGS="$_SAVE_CXXFLAGS"
-
-if test "$ac_nscap_nonconst_opeq_bug" = "yes" ; then
-    AC_DEFINE(NSCAP_DONT_PROVIDE_NONCONST_OPEQ)
-fi
 fi # ! SKIP_COMPILER_CHECKS
 
 AC_DEFINE(CPP_THROW_NEW, [throw()])
 AC_LANG_C
 
 if test "$COMPILE_ENVIRONMENT"; then
 MOZ_EXPAND_LIBS
 fi # COMPILE_ENVIRONMENT
@@ -7870,17 +7827,17 @@ else
   if test -z "$_WIN32_MSVC"; then
     _USE_CPP_INCLUDE_FLAG=
     _DEFINES_CFLAGS='$(ACDEFINES) -D_MOZILLA_CONFIG_H_ -DMOZILLA_CLIENT'
     _DEFINES_CXXFLAGS='$(ACDEFINES) -D_MOZILLA_CONFIG_H_ -DMOZILLA_CLIENT'
   else
     echo '#include <stdio.h>' > dummy-hello.c
     changequote(,)
     dnl This output is localized, split at the first double space or colon and space.
-    _CL_PREFIX_REGEX="^\([^:]*:.*[ :] \)\(.*stdio.h\)$"
+    _CL_PREFIX_REGEX="^\([^:]*:.*[ :] \)\(.*\\\stdio.h\)$"
     CL_INCLUDES_PREFIX=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/'"$_CL_PREFIX_REGEX"'/\1/p'`
     _CL_STDIO_PATH=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/'"$_CL_PREFIX_REGEX"'/\2/p'`
     changequote([,])
     if ! test -e "$_CL_STDIO_PATH"; then
         AC_MSG_ERROR([Unable to parse cl -showIncludes prefix. This compiler's locale has an unsupported formatting.])
     fi
     if test -z "$CL_INCLUDES_PREFIX"; then
         AC_MSG_ERROR([Cannot find cl -showIncludes prefix.])
--- a/content/base/public/FragmentOrElement.h
+++ b/content/base/public/FragmentOrElement.h
@@ -119,16 +119,17 @@ public:
 
   ~nsNodeWeakReference();
 
   // nsISupports
   NS_DECL_ISUPPORTS
 
   // nsIWeakReference
   NS_DECL_NSIWEAKREFERENCE
+  virtual size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   void NoticeNodeDestruction()
   {
     mNode = nullptr;
   }
 
 private:
   nsINode* mNode;
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -24,17 +24,16 @@
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
 
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
-class nsCSSStyleSheet;
 class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsFrameLoader;
 class nsHTMLCSSStyleSheet;
 class nsHTMLDocument;
 class nsHTMLStyleSheet;
 class nsIAtom;
@@ -78,16 +77,17 @@ class nsTextNode;
 class nsWindowSizes;
 class nsSmallVoidArray;
 class nsDOMCaretPosition;
 class nsViewportInfo;
 class nsIGlobalObject;
 struct nsCSSSelectorList;
 
 namespace mozilla {
+class CSSStyleSheet;
 class ErrorResult;
 class EventStates;
 
 namespace css {
 class Loader;
 class ImageLoader;
 } // namespace css
 
@@ -117,16 +117,17 @@ class NodeIterator;
 class ProcessingInstruction;
 class StyleSheetList;
 class SVGDocument;
 class Touch;
 class TouchList;
 class TreeWalker;
 class UndoManager;
 class XPathEvaluator;
+class XPathResult;
 template<typename> class OwningNonNull;
 template<typename> class Sequence;
 
 template<typename, typename> class CallbackObjectHolder;
 typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
 } // namespace dom
 } // namespace mozilla
 
@@ -774,17 +775,17 @@ public:
    * This function prepends the given style sheet to the document's style set
    * in order to make sure that it does not override user-agent style sheets
    * supplied by add-ons or by the app (Firefox OS or Firefox Mobile, for
    * example), since their sheets should override built-in sheets.
    *
    * TODO We can get rid of the whole concept of delayed loading if we fix
    * bug 77999.
    */
-  virtual void EnsureOnDemandBuiltInUASheet(nsCSSStyleSheet* aSheet) = 0;
+  virtual void EnsureOnDemandBuiltInUASheet(mozilla::CSSStyleSheet* aSheet) = 0;
 
   /**
    * Get the number of (document) stylesheets
    *
    * @return the number of stylesheets
    * @throws no exceptions
    */
   virtual int32_t GetNumberOfStyleSheets() const = 0;
@@ -1831,17 +1832,17 @@ public:
    * Called by the chrome registry to load style sheets.  Can be put
    * back there if and when when that module is merged with libgklayout.
    *
    * This always does a synchronous load.  If aIsAgentSheet is true,
    * it also uses the system principal and enables unsafe rules.
    * DO NOT USE FOR UNTRUSTED CONTENT.
    */
   virtual nsresult LoadChromeSheetSync(nsIURI* aURI, bool aIsAgentSheet,
-                                       nsCSSStyleSheet** aSheet) = 0;
+                                       mozilla::CSSStyleSheet** aSheet) = 0;
 
   /**
    * Returns true if the locale used for the document specifies a direction of
    * right to left. For chrome documents, this comes from the chrome registry.
    * This is used to determine the current state for the :-moz-locale-dir pseudoclass
    * so once can know whether a document is expected to be rendered left-to-right
    * or right-to-left.
    */
@@ -2269,20 +2270,20 @@ public:
   Element* GetBindingParent(nsINode& aNode);
   void LoadBindingDocument(const nsAString& aURI, mozilla::ErrorResult& rv);
   already_AddRefed<nsIDOMXPathExpression>
     CreateExpression(const nsAString& aExpression,
                      nsIDOMXPathNSResolver* aResolver,
                      mozilla::ErrorResult& rv);
   already_AddRefed<nsIDOMXPathNSResolver>
     CreateNSResolver(nsINode* aNodeResolver, mozilla::ErrorResult& rv);
-  already_AddRefed<nsISupports>
-    Evaluate(const nsAString& aExpression, nsINode* aContextNode,
+  already_AddRefed<mozilla::dom::XPathResult>
+    Evaluate(JSContext* aCx, const nsAString& aExpression, nsINode* aContextNode,
              nsIDOMXPathNSResolver* aResolver, uint16_t aType,
-             nsISupports* aResult, mozilla::ErrorResult& rv);
+             JS::Handle<JSObject*> aResult, mozilla::ErrorResult& rv);
   // Touch event handlers already on nsINode
   already_AddRefed<mozilla::dom::Touch>
     CreateTouch(nsIDOMWindow* aView, mozilla::dom::EventTarget* aTarget,
                 int32_t aIdentifier, int32_t aPageX, int32_t aPageY,
                 int32_t aScreenX, int32_t aScreenY, int32_t aClientX,
                 int32_t aClientY, int32_t aRadiusX, int32_t aRadiusY,
                 float aRotationAngle, float aForce);
   already_AddRefed<mozilla::dom::TouchList> CreateTouchList();
--- a/content/base/public/nsIStyleSheetLinkingElement.h
+++ b/content/base/public/nsIStyleSheetLinkingElement.h
@@ -11,30 +11,33 @@
 class nsICSSLoaderObserver;
 class nsIURI;
 
 #define NS_ISTYLESHEETLINKINGELEMENT_IID          \
 { 0xd753c84a, 0x17fd, 0x4d5f, \
  { 0xb2, 0xe9, 0x63, 0x52, 0x8c, 0x87, 0x99, 0x7a } }
 
 class nsIStyleSheet;
-class nsCSSStyleSheet;
+
+namespace mozilla {
+class CSSStyleSheet;
+} // namespace mozilla
 
 class nsIStyleSheetLinkingElement : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISTYLESHEETLINKINGELEMENT_IID)
 
   /**
    * Used to make the association between a style sheet and
    * the element that linked it to the document.
    *
    * @param aStyleSheet the style sheet associated with this
    *                    element.
    */
-  NS_IMETHOD SetStyleSheet(nsCSSStyleSheet* aStyleSheet) = 0;
+  NS_IMETHOD SetStyleSheet(mozilla::CSSStyleSheet* aStyleSheet) = 0;
 
   /**
    * Used to obtain the style sheet linked in by this element.
    *
    * @param aStyleSheet out parameter that returns the style
    *                    sheet associated with this element.
    */
   NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aStyleSheet) = 0;
--- a/content/base/src/ChildIterator.cpp
+++ b/content/base/src/ChildIterator.cpp
@@ -20,29 +20,29 @@ public:
     : mIsContentElement(true), mContentElement(aInsertionPoint) {}
 
   MatchedNodes(XBLChildrenElement* aInsertionPoint)
     : mIsContentElement(false), mChildrenElement(aInsertionPoint) {}
 
   uint32_t Length() const
   {
     return mIsContentElement ? mContentElement->MatchedNodes().Length()
-                             : mChildrenElement->mInsertedChildren.Length();
+                             : mChildrenElement->InsertedChildrenLength();
   }
 
   nsIContent* operator[](int32_t aIndex) const
   {
     return mIsContentElement ? mContentElement->MatchedNodes()[aIndex]
-                             : mChildrenElement->mInsertedChildren[aIndex];
+                             : mChildrenElement->InsertedChild(aIndex);
   }
 
   bool IsEmpty() const
   {
     return mIsContentElement ? mContentElement->MatchedNodes().IsEmpty()
-                             : mChildrenElement->mInsertedChildren.IsEmpty();
+                             : !mChildrenElement->HasInsertedChildren();
   }
 protected:
   bool mIsContentElement;
   union {
     HTMLContentElement* mContentElement;
     XBLChildrenElement* mChildrenElement;
   };
 };
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -1231,25 +1231,21 @@ EventSource::DispatchAllMessageEvents()
 
   mGoingToDispatchAllMessages = false;
 
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return;
   }
 
-  // We need a parent object so that we can enter its compartment.
-  nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject());
-  if (NS_WARN_IF(!parentObject)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) {
     return;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, parentObject->GetGlobalJSObject());
 
   while (mMessagesToDispatch.GetSize() > 0) {
     nsAutoPtr<Message>
       message(static_cast<Message*>(mMessagesToDispatch.PopFront()));
 
     // Now we can turn our string into a jsval
     JS::Rooted<JS::Value> jsData(cx);
     {
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -495,16 +495,22 @@ nsNodeWeakReference::~nsNodeWeakReferenc
 
 NS_IMETHODIMP
 nsNodeWeakReference::QueryReferent(const nsIID& aIID, void** aInstancePtr)
 {
   return mNode ? mNode->QueryInterface(aIID, aInstancePtr) :
                  NS_ERROR_NULL_POINTER;
 }
 
+size_t
+nsNodeWeakReference::SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const
+{
+  return aMallocSizeOf(this);
+}
+
 
 NS_IMPL_CYCLE_COLLECTION(nsNodeSupportsWeakRefTearoff, mNode)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSupportsWeakRefTearoff)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_AGGREGATED(mNode)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSupportsWeakRefTearoff)
--- a/content/base/src/ShadowRoot.cpp
+++ b/content/base/src/ShadowRoot.cpp
@@ -132,17 +132,17 @@ ShadowRoot::StyleSheetChanged()
   if (shell) {
     OwnerDoc()->BeginUpdate(UPDATE_STYLE);
     shell->RecordShadowStyleChange(this);
     OwnerDoc()->EndUpdate(UPDATE_STYLE);
   }
 }
 
 void
-ShadowRoot::InsertSheet(nsCSSStyleSheet* aSheet,
+ShadowRoot::InsertSheet(CSSStyleSheet* aSheet,
                         nsIContent* aLinkingContent)
 {
   nsCOMPtr<nsIStyleSheetLinkingElement>
     linkingElement = do_QueryInterface(aLinkingContent);
   MOZ_ASSERT(linkingElement, "The only styles in a ShadowRoot should come "
                              "from <style>.");
 
   linkingElement->SetStyleSheet(aSheet); // This sets the ownerNode on the sheet
@@ -163,17 +163,17 @@ ShadowRoot::InsertSheet(nsCSSStyleSheet*
   }
 
   if (aSheet->IsApplicable()) {
     StyleSheetChanged();
   }
 }
 
 void
-ShadowRoot::RemoveSheet(nsCSSStyleSheet* aSheet)
+ShadowRoot::RemoveSheet(CSSStyleSheet* aSheet)
 {
   mProtoBinding->RemoveStyleSheet(aSheet);
 
   if (aSheet->IsApplicable()) {
     StyleSheetChanged();
   }
 }
 
@@ -714,17 +714,17 @@ ShadowRootStyleSheetList::ShadowRootStyl
   MOZ_COUNT_CTOR(ShadowRootStyleSheetList);
 }
 
 ShadowRootStyleSheetList::~ShadowRootStyleSheetList()
 {
   MOZ_COUNT_DTOR(ShadowRootStyleSheetList);
 }
 
-nsCSSStyleSheet*
+CSSStyleSheet*
 ShadowRootStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   aFound = aIndex < mShadowRoot->mProtoBinding->SheetCount();
 
   if (!aFound) {
     return nullptr;
   }
 
--- a/content/base/src/ShadowRoot.h
+++ b/content/base/src/ShadowRoot.h
@@ -43,18 +43,18 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   ShadowRoot(nsIContent* aContent, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
              nsXBLPrototypeBinding* aProtoBinding);
   virtual ~ShadowRoot();
 
   void AddToIdTable(Element* aElement, nsIAtom* aId);
   void RemoveFromIdTable(Element* aElement, nsIAtom* aId);
-  void InsertSheet(nsCSSStyleSheet* aSheet, nsIContent* aLinkingContent);
-  void RemoveSheet(nsCSSStyleSheet* aSheet);
+  void InsertSheet(CSSStyleSheet* aSheet, nsIContent* aLinkingContent);
+  void RemoveSheet(CSSStyleSheet* aSheet);
   bool ApplyAuthorStyles();
   void SetApplyAuthorStyles(bool aApplyAuthorStyles);
   StyleSheetList* StyleSheets();
   HTMLShadowElement* GetShadowElement() { return mShadowElement; }
 
   /**
    * Sets the current shadow insertion point where the older
    * ShadowRoot will be projected.
@@ -182,17 +182,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
 
   virtual nsINode* GetParentObject() const MOZ_OVERRIDE
   {
     return mShadowRoot;
   }
 
   virtual uint32_t Length() MOZ_OVERRIDE;
-  virtual nsCSSStyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
+  virtual CSSStyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
 
 protected:
   nsRefPtr<ShadowRoot> mShadowRoot;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/content/base/src/StyleSheetList.cpp
+++ b/content/base/src/StyleSheetList.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/StyleSheetList.h"
 
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/dom/StyleSheetListBinding.h"
-#include "nsCSSStyleSheet.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(StyleSheetList)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StyleSheetList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
--- a/content/base/src/StyleSheetList.h
+++ b/content/base/src/StyleSheetList.h
@@ -4,20 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_StyleSheetList_h
 #define mozilla_dom_StyleSheetList_h
 
 #include "nsIDOMStyleSheetList.h"
 #include "nsWrapperCache.h"
 
-class nsCSSStyleSheet;
 class nsINode;
 
 namespace mozilla {
+class CSSStyleSheet;
+
 namespace dom {
 
 class StyleSheetList : public nsIDOMStyleSheetList
                      , public nsWrapperCache
 {
 public:
   StyleSheetList()
   {
@@ -29,18 +30,18 @@ public:
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(StyleSheetList)
   NS_DECL_NSIDOMSTYLESHEETLIST
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE MOZ_FINAL;
 
   virtual nsINode* GetParentObject() const = 0;
 
   virtual uint32_t Length() = 0;
-  virtual nsCSSStyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) = 0;
-  nsCSSStyleSheet* Item(uint32_t aIndex)
+  virtual CSSStyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) = 0;
+  CSSStyleSheet* Item(uint32_t aIndex)
   {
     bool dummy = false;
     return IndexedGetter(aIndex, dummy);
   }
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -860,24 +860,21 @@ WebSocket::CreateAndDispatchMessageEvent
                                          bool isBinary)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv))
     return NS_OK;
 
-  nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(GetOwner());
-  if (NS_WARN_IF(!globalObject)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) {
     return NS_ERROR_FAILURE;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject());
 
   // Create appropriate JS object for message
   JS::Rooted<JS::Value> jsData(cx);
   if (isBinary) {
     if (mBinaryType == dom::BinaryType::Blob) {
       rv = nsContentUtils::CreateBlobBuffer(cx, aData, &jsData);
       NS_ENSURE_SUCCESS(rv, rv);
     } else if (mBinaryType == dom::BinaryType::Arraybuffer) {
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -202,17 +202,17 @@ nsContentSink::Init(nsIDocument* aDoc,
     mDynamicLowerValue = sEnablePerfMode == 1;
     FavorPerformanceHint(!mDynamicLowerValue, 0);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsContentSink::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
+nsContentSink::StyleSheetLoaded(CSSStyleSheet* aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus)
 {
   NS_ASSERTION(!mRunsToCompletion, "How come a fragment parser observed sheets?");
   if (!aWasAlternate) {
     NS_ASSERTION(mPendingSheetCount > 0, "How'd that happen?");
     --mPendingSheetCount;
 
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -81,17 +81,18 @@ class nsContentSink : public nsICSSLoade
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink,
                                            nsICSSLoaderObserver)
     // nsITimerCallback
   NS_DECL_NSITIMERCALLBACK
 
   // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, bool aWasAlternate,
+  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+                              bool aWasAlternate,
                               nsresult aStatus) MOZ_OVERRIDE;
 
   virtual nsresult ProcessMETATag(nsIContent* aContent);
 
   // nsIContentSink implementation helpers
   nsresult WillParseImpl(void);
   nsresult WillInterruptImpl(void);
   nsresult WillResumeImpl(void);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6406,25 +6406,22 @@ nsContentUtils::GetContentSecurityPolicy
 }
 
 // static
 bool
 nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
                                   nsIDocument* aDocument)
 {
   NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
-  nsCOMPtr<nsIGlobalObject> globalObject =
-    do_QueryInterface(aDocument->GetWindow());
-  if (NS_WARN_IF(!globalObject)) {
-    return true;
-  }
 
   AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(aDocument->GetWindow()))) {
+    return true;
+  }
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject());
 
   // The pattern has to match the entire value.
   aPattern.Insert(NS_LITERAL_STRING("^(?:"), 0);
   aPattern.AppendLiteral(")$");
 
   JS::Rooted<JSObject*> re(cx,
     JS_NewUCRegExpObjectNoStatics(cx,
                                   static_cast<jschar*>(aPattern.BeginWriting()),
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -378,24 +378,21 @@ nsDOMDataChannel::DoOnMessageAvailable(c
 
   LOG(("DoOnMessageAvailable%s\n",aBinary ? ((mBinaryType == DC_BINARY_TYPE_BLOB) ? " (blob)" : " (binary)") : ""));
 
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(GetOwner());
-  if (NS_WARN_IF(!globalObject)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) {
     return NS_ERROR_FAILURE;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject());
 
   JS::Rooted<JS::Value> jsData(cx);
 
   if (aBinary) {
     if (mBinaryType == DC_BINARY_TYPE_BLOB) {
       rv = nsContentUtils::CreateBlobBuffer(cx, aData, &jsData);
       NS_ENSURE_SUCCESS(rv, rv);
     } else if (mBinaryType == DC_BINARY_TYPE_ARRAYBUFFER) {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -213,16 +213,17 @@
 #include "nsIEditor.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "mozilla/css/Rule.h"
 #include "nsIDOMLocation.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsISecurityConsoleMessage.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "mozilla/dom/XPathEvaluator.h"
+#include "mozilla/dom/XPathResult.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDocumentActivity.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsIMutableArray.h"
 #include "nsContentPermissionHelper.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "nsWindowMemoryReporter.h"
 
@@ -756,29 +757,29 @@ nsDOMStyleSheetList::Length()
       nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(sheet));
       NS_ASSERTION(domss, "All \"normal\" sheets implement nsIDOMStyleSheet");
     }
 #endif
   }
   return mLength;
 }
 
-nsCSSStyleSheet*
+CSSStyleSheet*
 nsDOMStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   if (!mDocument || aIndex >= (uint32_t)mDocument->GetNumberOfStyleSheets()) {
     aFound = false;
     return nullptr;
   }
 
   aFound = true;
   nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(aIndex);
   NS_ASSERTION(sheet, "Must have a sheet");
 
-  return static_cast<nsCSSStyleSheet*>(sheet);
+  return static_cast<CSSStyleSheet*>(sheet);
 }
 
 void
 nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
 {
   mDocument = nullptr;
 }
 
@@ -3965,29 +3966,29 @@ nsDocument::RemoveChildAt(uint32_t aInde
     DestroyElementMaps();
   }
 
   doRemoveChildAt(aIndex, aNotify, oldKid, mChildren);
   mCachedRootElement = nullptr;
 }
 
 void
-nsDocument::EnsureOnDemandBuiltInUASheet(nsCSSStyleSheet* aSheet)
+nsDocument::EnsureOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
 {
   // Contains() takes nsISupport*, so annoyingly we have to cast here
   if (mOnDemandBuiltInUASheets.Contains(static_cast<nsIStyleSheet*>(aSheet))) {
     return;
   }
   BeginUpdate(UPDATE_STYLE);
   AddOnDemandBuiltInUASheet(aSheet);
   EndUpdate(UPDATE_STYLE);
 }
 
 void
-nsDocument::AddOnDemandBuiltInUASheet(nsCSSStyleSheet* aSheet)
+nsDocument::AddOnDemandBuiltInUASheet(CSSStyleSheet* aSheet)
 {
   // Contains() takes nsISupport*, so annoyingly we have to cast here
   MOZ_ASSERT(!mOnDemandBuiltInUASheets.Contains(static_cast<nsIStyleSheet*>(aSheet)));
 
   // Prepend here so that we store the sheets in mOnDemandBuiltInUASheets in
   // the same order that they should end up in the style set.
   mOnDemandBuiltInUASheets.InsertElementAt(0, aSheet);
 
@@ -4275,17 +4276,17 @@ nsDocument::LoadAdditionalStyleSheet(add
 
   // Checking if we have loaded this one already.
   if (FindSheet(mAdditionalSheets[aType], aSheetURI) >= 0)
     return NS_ERROR_INVALID_ARG;
 
   // Loading the sheet sync.
   nsRefPtr<mozilla::css::Loader> loader = new mozilla::css::Loader();
 
-  nsRefPtr<nsCSSStyleSheet> sheet;
+  nsRefPtr<CSSStyleSheet> sheet;
   nsresult rv = loader->LoadSheetSync(aSheetURI, aType == eAgentSheet,
     true, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mAdditionalSheets[aType].AppendObject(sheet);
   sheet->SetOwningDocument(this);
   MOZ_ASSERT(sheet->IsApplicable());
 
@@ -9326,17 +9327,17 @@ namespace {
 
 /**
  * Stub for LoadSheet(), since all we want is to get the sheet into
  * the CSSLoader's style cache
  */
 class StubCSSLoaderObserver MOZ_FINAL : public nsICSSLoaderObserver {
 public:
   NS_IMETHOD
-  StyleSheetLoaded(nsCSSStyleSheet*, bool, nsresult)
+  StyleSheetLoaded(CSSStyleSheet*, bool, nsresult)
   {
     return NS_OK;
   }
   NS_DECL_ISUPPORTS
 };
 NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
 
 }
@@ -9352,17 +9353,17 @@ nsDocument::PreloadStyle(nsIURI* uri, co
   CSSLoader()->LoadSheet(uri, NodePrincipal(),
                          NS_LossyConvertUTF16toASCII(charset),
                          obs,
                          Element::StringToCORSMode(aCrossOriginAttr));
 }
 
 nsresult
 nsDocument::LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
-                                nsCSSStyleSheet** sheet)
+                                CSSStyleSheet** sheet)
 {
   return CSSLoader()->LoadSheetSync(uri, isAgentSheet, isAgentSheet, sheet);
 }
 
 class nsDelayedEventDispatcher : public nsRunnable
 {
 public:
   nsDelayedEventDispatcher(nsTArray<nsCOMPtr<nsIDocument> >& aDocuments)
@@ -9701,37 +9702,37 @@ nsIDocument::CreateStaticClone(nsIDocShe
       clonedDoc = static_cast<nsDocument*>(tmp.get());
       if (IsStaticDocument()) {
         clonedDoc->mOriginalDocument = mOriginalDocument;
       } else {
         clonedDoc->mOriginalDocument = this;
       }
       int32_t sheetsCount = GetNumberOfStyleSheets();
       for (int32_t i = 0; i < sheetsCount; ++i) {
-        nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i));
+        nsRefPtr<CSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i));
         if (sheet) {
           if (sheet->IsApplicable()) {
-            nsRefPtr<nsCSSStyleSheet> clonedSheet =
+            nsRefPtr<CSSStyleSheet> clonedSheet =
               sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
             NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
             if (clonedSheet) {
               clonedDoc->AddStyleSheet(clonedSheet);
             }
           }
         }
       }
 
       sheetsCount = thisAsDoc->mOnDemandBuiltInUASheets.Count();
       // Iterate backwards to maintain order
       for (int32_t i = sheetsCount - 1; i >= 0; --i) {
-        nsRefPtr<nsCSSStyleSheet> sheet =
+        nsRefPtr<CSSStyleSheet> sheet =
           do_QueryObject(thisAsDoc->mOnDemandBuiltInUASheets[i]);
         if (sheet) {
           if (sheet->IsApplicable()) {
-            nsRefPtr<nsCSSStyleSheet> clonedSheet =
+            nsRefPtr<CSSStyleSheet> clonedSheet =
               sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
             NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
             if (clonedSheet) {
               clonedDoc->AddOnDemandBuiltInUASheet(clonedSheet);
             }
           }
         }
       }
@@ -12099,23 +12100,24 @@ nsIDocument::CreateExpression(const nsAS
 
 already_AddRefed<nsIDOMXPathNSResolver>
 nsIDocument::CreateNSResolver(nsINode* aNodeResolver,
                               ErrorResult& rv)
 {
   return XPathEvaluator()->CreateNSResolver(aNodeResolver, rv);
 }
 
-already_AddRefed<nsISupports>
-nsIDocument::Evaluate(const nsAString& aExpression, nsINode* aContextNode,
-                      nsIDOMXPathNSResolver* aResolver, uint16_t aType,
-                      nsISupports* aResult, ErrorResult& rv)
-{
-  return XPathEvaluator()->Evaluate(aExpression, aContextNode, aResolver, aType,
-                                    aResult, rv);
+already_AddRefed<XPathResult>
+nsIDocument::Evaluate(JSContext* aCx, const nsAString& aExpression,
+                      nsINode* aContextNode, nsIDOMXPathNSResolver* aResolver,
+                      uint16_t aType, JS::Handle<JSObject*> aResult,
+                      ErrorResult& rv)
+{
+  return XPathEvaluator()->Evaluate(aCx, aExpression, aContextNode, aResolver,
+                                    aType, aResult, rv);
 }
 
 NS_IMETHODIMP
 nsDocument::CreateExpression(const nsAString& aExpression,
                              nsIDOMXPathNSResolver* aResolver,
                              nsIDOMXPathExpression** aResult)
 {
   return XPathEvaluator()->CreateExpression(aExpression, aResolver, aResult);
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -452,17 +452,18 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
   virtual nsINode* GetParentObject() const MOZ_OVERRIDE
   {
     return mDocument;
   }
 
   virtual uint32_t Length() MOZ_OVERRIDE;
-  virtual nsCSSStyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
+  virtual mozilla::CSSStyleSheet*
+  IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
 
 protected:
   int32_t       mLength;
   nsIDocument*  mDocument;
 };
 
 class nsOnloadBlocker MOZ_FINAL : public nsIRequest
 {
@@ -775,17 +776,17 @@ public:
   virtual mozilla::dom::AnimationTimeline* Timeline() MOZ_OVERRIDE;
 
   virtual nsresult SetSubDocumentFor(Element* aContent,
                                      nsIDocument* aSubDoc) MOZ_OVERRIDE;
   virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const MOZ_OVERRIDE;
   virtual Element* FindContentForSubDocument(nsIDocument *aDocument) const MOZ_OVERRIDE;
   virtual Element* GetRootElementInternal() const MOZ_OVERRIDE;
 
-  virtual void EnsureOnDemandBuiltInUASheet(nsCSSStyleSheet* aSheet) MOZ_OVERRIDE;
+  virtual void EnsureOnDemandBuiltInUASheet(mozilla::CSSStyleSheet* aSheet) MOZ_OVERRIDE;
 
   /**
    * Get the (document) style sheets owned by this document.
    * These are ordered, highest priority last
    */
   virtual int32_t GetNumberOfStyleSheets() const MOZ_OVERRIDE;
   virtual nsIStyleSheet* GetStyleSheetAt(int32_t aIndex) const MOZ_OVERRIDE;
   virtual int32_t GetIndexOfStyleSheet(nsIStyleSheet* aSheet) const MOZ_OVERRIDE;
@@ -927,17 +928,17 @@ public:
 
   // for radio group
   nsRadioGroupStruct* GetRadioGroup(const nsAString& aName) const;
   nsRadioGroupStruct* GetOrCreateRadioGroup(const nsAString& aName);
 
   virtual nsViewportInfo GetViewportInfo(const mozilla::ScreenIntSize& aDisplaySize) MOZ_OVERRIDE;
 
 private:
-  void AddOnDemandBuiltInUASheet(nsCSSStyleSheet* aSheet);
+  void AddOnDemandBuiltInUASheet(mozilla::CSSStyleSheet* aSheet);
   nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
   void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
 
 public:
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE
 
   // nsIDOMDocument
@@ -1075,17 +1076,17 @@ public:
 
   virtual void MaybePreLoadImage(nsIURI* uri,
                                  const nsAString &aCrossOriginAttr) MOZ_OVERRIDE;
 
   virtual void PreloadStyle(nsIURI* uri, const nsAString& charset,
                             const nsAString& aCrossOriginAttr) MOZ_OVERRIDE;
 
   virtual nsresult LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
-                                       nsCSSStyleSheet** sheet) MOZ_OVERRIDE;
+                                       mozilla::CSSStyleSheet** sheet) MOZ_OVERRIDE;
 
   virtual nsISupports* GetCurrentContentSink() MOZ_OVERRIDE;
 
   virtual mozilla::EventStates GetDocumentState() MOZ_OVERRIDE;
 
   virtual void RegisterHostObjectUri(const nsACString& aUri) MOZ_OVERRIDE;
   virtual void UnregisterHostObjectUri(const nsACString& aUri) MOZ_OVERRIDE;
 
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -2064,24 +2064,33 @@ nsFrameLoader::TryRemoteBrowser()
     return false;
   }
 
   nsCOMPtr<nsPIDOMWindow> parentWin = doc->GetWindow();
   if (!parentWin) {
     return false;
   }
 
-  nsCOMPtr<nsIDocShellTreeItem> parentAsItem(parentWin->GetDocShell());
-  if (!parentAsItem) {
+  nsCOMPtr<nsIDocShell> parentDocShell = parentWin->GetDocShell();
+  if (!parentDocShell) {
     return false;
   }
 
+  TabParent* openingTab = static_cast<TabParent*>(parentDocShell->GetOpener());
+  ContentParent* openerContentParent = nullptr;
+
+  if (openingTab &&
+      openingTab->Manager() &&
+      openingTab->Manager()->IsContentParent()) {
+    openerContentParent = openingTab->Manager()->AsContentParent();
+  }
+
   // <iframe mozbrowser> gets to skip these checks.
   if (!OwnerIsBrowserOrAppFrame()) {
-    if (parentAsItem->ItemType() != nsIDocShellTreeItem::typeChrome) {
+    if (parentDocShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
       return false;
     }
 
     if (!mOwnerContent->IsXUL()) {
       return false;
     }
 
     nsAutoString value;
@@ -2091,17 +2100,17 @@ nsFrameLoader::TryRemoteBrowser()
         !StringBeginsWith(value, NS_LITERAL_STRING("content-"),
                           nsCaseInsensitiveStringComparator())) {
       return false;
     }
   }
 
   uint32_t chromeFlags = 0;
   nsCOMPtr<nsIDocShellTreeOwner> parentOwner;
-  if (NS_FAILED(parentAsItem->GetTreeOwner(getter_AddRefs(parentOwner))) ||
+  if (NS_FAILED(parentDocShell->GetTreeOwner(getter_AddRefs(parentOwner))) ||
       !parentOwner) {
     return false;
   }
   nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
   if (window && NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
     return false;
   }
 
@@ -2128,21 +2137,21 @@ nsFrameLoader::TryRemoteBrowser()
     // The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp.
     rv = context.SetTabContextForBrowserFrame(containingApp, scrollingBehavior);
   } else {
     rv = context.SetTabContextForNormalFrame(scrollingBehavior);
   }
   NS_ENSURE_TRUE(rv, false);
 
   nsCOMPtr<Element> ownerElement = mOwnerContent;
-  mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement);
+  mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement, openerContentParent);
   if (mRemoteBrowser) {
     mChildID = mRemoteBrowser->Manager()->ChildID();
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
-    parentAsItem->GetRootTreeItem(getter_AddRefs(rootItem));
+    parentDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
     nsCOMPtr<nsIDOMWindow> rootWin = rootItem->GetWindow();
     nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
 
     if (rootChromeWin) {
       nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
       rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
       mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
     }
@@ -2150,16 +2159,17 @@ nsFrameLoader::TryRemoteBrowser()
     mContentParent = mRemoteBrowser->Manager();
 
     if (mOwnerContent->AttrValueIs(kNameSpaceID_None,
                                    nsGkAtoms::mozpasspointerevents,
                                    nsGkAtoms::_true,
                                    eCaseMatters)) {
       unused << mRemoteBrowser->SendSetUpdateHitRegion(true);
     }
+    parentDocShell->SetOpenedRemote(mRemoteBrowser);
   }
   return true;
 }
 
 mozilla::dom::PBrowserParent*
 nsFrameLoader::GetRemoteBrowser()
 {
   return mRemoteBrowser;
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -882,26 +882,23 @@ nsScriptLoader::AttemptAsyncScriptParse(
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> globalObject = GetScriptGlobalObject();
   if (!globalObject) {
     return NS_ERROR_FAILURE;
   }
 
-  nsCOMPtr<nsIScriptContext> context = globalObject->GetScriptContext();
-  if (!context) {
+  AutoJSAPI jsapi;
+  if (!jsapi.InitWithLegacyErrorReporting(globalObject)) {
     return NS_ERROR_FAILURE;
   }
 
-  AutoJSAPIWithErrorsReportedToWindow jsapi(context);
   JSContext* cx = jsapi.cx();
   JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
-  JSAutoCompartment ac(cx, global);
-
   JS::CompileOptions options(cx);
   FillCompileOptionsForRequest(aRequest, global, &options);
 
   if (!JS::CanCompileOffThread(cx, options, aRequest->mScriptTextLength)) {
     return NS_ERROR_FAILURE;
   }
 
   nsRefPtr<NotifyOffThreadScriptLoadCompletedRunnable> runnable =
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -7,22 +7,22 @@
 /*
  * A base class which implements nsIStyleSheetLinkingElement and can
  * be subclassed by various content nodes that want to load
  * stylesheets (<style>, <link>, processing instructions, etc).
  */
 
 #include "nsStyleLinkElement.h"
 
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FragmentOrElement.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/Preferences.h"
-#include "nsCSSStyleSheet.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsNetUtil.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
@@ -55,17 +55,17 @@ nsStyleLinkElement::Unlink()
 void
 nsStyleLinkElement::Traverse(nsCycleCollectionTraversalCallback &cb)
 {
   nsStyleLinkElement* tmp = this;
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheet);
 }
 
 NS_IMETHODIMP 
-nsStyleLinkElement::SetStyleSheet(nsCSSStyleSheet* aStyleSheet)
+nsStyleLinkElement::SetStyleSheet(CSSStyleSheet* aStyleSheet)
 {
   if (mStyleSheet) {
     mStyleSheet->SetOwningNode(nullptr);
   }
 
   mStyleSheet = aStyleSheet;
   if (mStyleSheet) {
     nsCOMPtr<nsINode> node = do_QueryObject(this);
@@ -257,17 +257,17 @@ UpdateIsElementInStyleScopeFlagOnSubtree
       n = n->GetNextNode(aElement);
     }
   }
 }
 
 static Element*
 GetScopeElement(nsIStyleSheet* aSheet)
 {
-  nsRefPtr<nsCSSStyleSheet> cssStyleSheet = do_QueryObject(aSheet);
+  nsRefPtr<CSSStyleSheet> cssStyleSheet = do_QueryObject(aSheet);
   if (!cssStyleSheet) {
     return nullptr;
   }
 
   return cssStyleSheet->GetScopeElement();
 }
 
 nsresult
--- a/content/base/src/nsStyleLinkElement.h
+++ b/content/base/src/nsStyleLinkElement.h
@@ -9,21 +9,21 @@
  * be subclassed by various content nodes that want to load
  * stylesheets (<style>, <link>, processing instructions, etc).
  */
 
 #ifndef nsStyleLinkElement_h___
 #define nsStyleLinkElement_h___
 
 #include "mozilla/Attributes.h"
+#include "mozilla/CORSMode.h"
+#include "mozilla/CSSStyleSheet.h"
 #include "nsCOMPtr.h"
 #include "nsIStyleSheetLinkingElement.h"
-#include "nsCSSStyleSheet.h"
 #include "nsTArray.h"
-#include "mozilla/CORSMode.h"
 
 class nsIDocument;
 class nsIURI;
 
 namespace mozilla {
 namespace dom {
 class ShadowRoot;
 } // namespace dom
@@ -32,20 +32,20 @@ class ShadowRoot;
 class nsStyleLinkElement : public nsIStyleSheetLinkingElement
 {
 public:
   nsStyleLinkElement();
   virtual ~nsStyleLinkElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) MOZ_OVERRIDE = 0;
 
-  nsCSSStyleSheet* GetSheet() const { return mStyleSheet; }
+  mozilla::CSSStyleSheet* GetSheet() const { return mStyleSheet; }
 
   // nsIStyleSheetLinkingElement  
-  NS_IMETHOD SetStyleSheet(nsCSSStyleSheet* aStyleSheet) MOZ_OVERRIDE;
+  NS_IMETHOD SetStyleSheet(mozilla::CSSStyleSheet* aStyleSheet) MOZ_OVERRIDE;
   NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aStyleSheet) MOZ_OVERRIDE;
   NS_IMETHOD InitStyleLinkElement(bool aDontLoadStyle) MOZ_OVERRIDE;
   NS_IMETHOD UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
                               bool* aWillNotify,
                               bool* aIsAlternate) MOZ_OVERRIDE;
   NS_IMETHOD SetEnableUpdates(bool aEnableUpdates) MOZ_OVERRIDE;
   NS_IMETHOD GetCharset(nsAString& aCharset) MOZ_OVERRIDE;
 
@@ -117,17 +117,17 @@ private:
    */
   nsresult DoUpdateStyleSheet(nsIDocument* aOldDocument,
                               mozilla::dom::ShadowRoot* aOldShadowRoot,
                               nsICSSLoaderObserver* aObserver,
                               bool* aWillNotify,
                               bool* aIsAlternate,
                               bool aForceUpdate);
 
-  nsRefPtr<nsCSSStyleSheet> mStyleSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mStyleSheet;
 protected:
   bool mDontLoadStyle;
   bool mUpdatesEnabled;
   uint32_t mLineNumber;
 };
 
 #endif /* nsStyleLinkElement_h___ */
 
--- a/content/base/src/nsTreeSanitizer.cpp
+++ b/content/base/src/nsTreeSanitizer.cpp
@@ -1,24 +1,24 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=2 et tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/ArrayUtils.h"
+#include "nsTreeSanitizer.h"
 
-#include "nsTreeSanitizer.h"
-#include "nsCSSParser.h"
-#include "nsCSSProperty.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Declaration.h"
 #include "mozilla/css/StyleRule.h"
 #include "mozilla/css/Rule.h"
+#include "nsCSSParser.h"
+#include "nsCSSProperty.h"
 #include "nsUnicharInputStream.h"
-#include "nsCSSStyleSheet.h"
 #include "nsIDOMCSSRule.h"
 #include "nsAttrName.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 #include "nsComponentManagerUtils.h"
 #include "nsNullPrincipal.h"
 #include "nsContentUtils.h"
 #include "nsIParserUtils.h"
@@ -1093,17 +1093,17 @@ nsTreeSanitizer::SanitizeStyleSheet(cons
                                     nsIURI* aBaseURI)
 {
   nsresult rv;
   aSanitized.Truncate();
   // aSanitized will hold the permitted CSS text.
   // -moz-binding is blacklisted.
   bool didSanitize = false;
   // Create a sheet to hold the parsed CSS
-  nsRefPtr<nsCSSStyleSheet> sheet = new nsCSSStyleSheet(CORS_NONE);
+  nsRefPtr<CSSStyleSheet> sheet = new CSSStyleSheet(CORS_NONE);
   sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
   sheet->SetPrincipal(aDocument->NodePrincipal());
   // Create the CSS parser, and parse the CSS text.
   nsCSSParser parser(nullptr, sheet);
   rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
                          aDocument->NodePrincipal(), 0, false);
   NS_ENSURE_SUCCESS(rv, true);
   // Mark the sheet as complete.
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -2320,17 +2320,16 @@ CanvasRenderingContext2D::SetFont(const 
   gfxFontStyle style(fontStyle->mFont.style,
                      fontStyle->mFont.weight,
                      fontStyle->mFont.stretch,
                      NSAppUnitsToFloatPixels(fontStyle->mSize, float(aupcp)),
                      language,
                      fontStyle->mFont.sizeAdjust,
                      fontStyle->mFont.systemFont,
                      printerFont,
-                     fontStyle->mFont.variant == NS_STYLE_FONT_VARIANT_SMALL_CAPS,
                      fontStyle->mFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
                      fontStyle->mFont.synthesis & NS_FONT_SYNTHESIS_STYLE,
                      fontStyle->mFont.languageOverride);
 
   fontStyle->mFont.AddFontFeaturesToStyle(&style);
 
   nsPresContext *c = presShell->GetPresContext();
   CurrentState().fontGroup =
--- a/content/canvas/src/ImageEncoder.cpp
+++ b/content/canvas/src/ImageEncoder.cpp
@@ -258,16 +258,20 @@ ImageEncoder::ExtractDataInternal(const 
                                   const nsAString& aOptions,
                                   uint8_t* aImageBuffer,
                                   int32_t aFormat,
                                   const nsIntSize aSize,
                                   nsICanvasRenderingContextInternal* aContext,
                                   nsIInputStream** aStream,
                                   imgIEncoder* aEncoder)
 {
+  if (aSize.IsEmpty()) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
   nsCOMPtr<nsIInputStream> imgStream;
 
   // get image bytes
   nsresult rv;
   if (aImageBuffer) {
     rv = ImageEncoder::GetInputStream(
       aSize.width,
       aSize.height,
--- a/content/canvas/src/WebGLElementArrayCache.cpp
+++ b/content/canvas/src/WebGLElementArrayCache.cpp
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLElementArrayCache.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/MathAlgorithms.h"
 
 #include <cstdlib>
 #include <cstring>
 #include <limits>
 #include <algorithm>
 
 namespace mozilla {
 
@@ -288,26 +289,16 @@ public:
       }
 
       // walk up 1 level
       firstTreeIndex = ParentNode(firstTreeIndex);
       lastTreeIndex = ParentNode(lastTreeIndex);
     }
   }
 
-  template<typename U>
-  static U NextPowerOfTwo(U x) {
-    U result = 1;
-    while (result < x)
-      result <<= 1;
-    MOZ_ASSERT(result >= x);
-    MOZ_ASSERT((result & (result - 1)) == 0);
-    return result;
-  }
-
   // Updates the tree from the parent's buffer contents. Fallible, as it
   // may have to resize the tree storage.
   bool Update(size_t firstByte, size_t lastByte);
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   {
     return aMallocSizeOf(this) + mTreeData.SizeOfExcludingThis(aMallocSizeOf);
   }
@@ -360,17 +351,17 @@ bool WebGLElementArrayCacheTree<T>::Upda
     // it would just be equal to
     //
     //    ceil(numberOfElements / sElementsPerLeaf)
     //
     // The way we implement this (division+ceil) operation in integer arithmetic
     // is as follows:
     size_t numLeavesNonPOT = (numberOfElements + sElementsPerLeaf - 1) / sElementsPerLeaf;
     // It only remains to round that up to the next power of two:
-    requiredNumLeaves = NextPowerOfTwo(numLeavesNonPOT);
+    requiredNumLeaves = RoundUpPow2(numLeavesNonPOT);
   }
 
   // Step #0: if needed, resize our tree data storage.
   if (requiredNumLeaves != NumLeaves()) {
     // see class comment for why we the tree storage size is 2 * numLeaves
     if (!mTreeData.SetLength(2 * requiredNumLeaves)) {
       mTreeData.SetLength(0);
       return false;
--- a/content/html/content/src/HTMLLinkElement.cpp
+++ b/content/html/content/src/HTMLLinkElement.cpp
@@ -76,35 +76,34 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION
 NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
 
 
 NS_IMPL_ELEMENT_CLONE(HTMLLinkElement)
 
 bool
 HTMLLinkElement::Disabled()
 {
-  nsCSSStyleSheet* ss = GetSheet();
+  CSSStyleSheet* ss = GetSheet();
   return ss && ss->Disabled();
 }
 
 NS_IMETHODIMP
 HTMLLinkElement::GetMozDisabled(bool* aDisabled)
 {
   *aDisabled = Disabled();
   return NS_OK;
 }
 
 void
 HTMLLinkElement::SetDisabled(bool aDisabled)
 {
-  nsCSSStyleSheet* ss = GetSheet();
+  CSSStyleSheet* ss = GetSheet();
   if (ss) {
     ss->SetDisabled(aDisabled);
   }
-
 }
 
 NS_IMETHODIMP
 HTMLLinkElement::SetMozDisabled(bool aDisabled)
 {
   SetDisabled(aDisabled);
   return NS_OK;
 }
--- a/content/html/content/src/HTMLStyleElement.cpp
+++ b/content/html/content/src/HTMLStyleElement.cpp
@@ -64,31 +64,31 @@ HTMLStyleElement::GetMozDisabled(bool* a
 
   *aDisabled = Disabled();
   return NS_OK;
 }
 
 bool
 HTMLStyleElement::Disabled()
 {
-  nsCSSStyleSheet* ss = GetSheet();
+  CSSStyleSheet* ss = GetSheet();
   return ss && ss->Disabled();
 }
 
 NS_IMETHODIMP
 HTMLStyleElement::SetMozDisabled(bool aDisabled)
 {
   SetDisabled(aDisabled);
   return NS_OK;
 }
 
 void
 HTMLStyleElement::SetDisabled(bool aDisabled)
 {
-  nsCSSStyleSheet* ss = GetSheet();
+  CSSStyleSheet* ss = GetSheet();
   if (ss) {
     ss->SetDisabled(aDisabled);
   }
 }
 
 NS_IMPL_STRING_ATTR(HTMLStyleElement, Media, media)
 NS_IMPL_BOOL_ATTR(HTMLStyleElement, Scoped, scoped)
 NS_IMPL_STRING_ATTR(HTMLStyleElement, Type, type)
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -185,16 +185,21 @@ HTML_TAG("object", "Object", [],
 HTML_TAG("ol", "OList");
 HTML_TAG("optgroup", "OptGroup");
 HTML_TAG("option", "Option");
 HTML_TAG("p", "Paragraph");
 HTML_TAG("param", "Param");
 HTML_TAG("plaintext", "");
 HTML_TAG("pre", "Pre");
 HTML_TAG("q", "Quote");
+HTML_TAG("rb", "");
+HTML_TAG("rp", "");
+HTML_TAG("rt", "");
+HTML_TAG("rtc", "");
+HTML_TAG("ruby", "");
 HTML_TAG("s", "");
 HTML_TAG("samp", "");
 HTML_TAG("script", "Script", [ "nsIScriptLoaderObserver" ], []);
 HTML_TAG("section", "")
 HTML_TAG("select", "Select", ["nsIDOMHTMLSelectElement"]);
 HTML_TAG("small", "");
 HTML_TAG("span", "Span");
 HTML_TAG("strike", "");
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2751,17 +2751,17 @@ nsHTMLDocument::EditingStateChanged()
     nsCOMArray<nsIStyleSheet> agentSheets;
     rv = presShell->GetAgentStyleSheets(agentSheets);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIURI> uri;
     rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("resource://gre/res/contenteditable.css"));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsRefPtr<nsCSSStyleSheet> sheet;
+    nsRefPtr<CSSStyleSheet> sheet;
     rv = LoadChromeSheetSync(uri, true, getter_AddRefs(sheet));
     NS_ENSURE_TRUE(sheet, rv);
 
     bool result = agentSheets.AppendObject(sheet);
     NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
 
     // Should we update the editable state of all the nodes in the document? We
     // need to do this when the designMode value changes, as that overrides
--- a/content/media/AudioNodeEngine.h
+++ b/content/media/AudioNodeEngine.h
@@ -355,18 +355,20 @@ public:
   {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
   void SizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
                            AudioNodeSizes& aUsage) const
   {
     aUsage.mEngine = SizeOfIncludingThis(aMallocSizeOf);
-    aUsage.mDomNode = mNode->SizeOfIncludingThis(aMallocSizeOf);
-    aUsage.mNodeType = mNode->NodeType();
+    if (HasNode()) {
+      aUsage.mDomNode = mNode->SizeOfIncludingThis(aMallocSizeOf);
+      aUsage.mNodeType = mNode->NodeType();
+    }
   }
 
 private:
   dom::AudioNode* mNode;
   Mutex mNodeMutex;
   const uint16_t mInputCount;
   const uint16_t mOutputCount;
 };
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -424,16 +424,17 @@ MediaDecoder::MediaDecoder() :
   mIsDormant(false),
   mIsExitingDormant(false),
   mPlayState(PLAY_STATE_PAUSED),
   mNextState(PLAY_STATE_PAUSED),
   mCalledResourceLoaded(false),
   mIgnoreProgressData(false),
   mInfiniteStream(false),
   mOwner(nullptr),
+  mPlaybackStatistics(new MediaChannelStatistics()),
   mPinnedForSeek(false),
   mShuttingDown(false),
   mPausedForPlaybackRateNull(false),
   mMinimizePreroll(false)
 {
   MOZ_COUNT_CTOR(MediaDecoder);
   MOZ_ASSERT(NS_IsMainThread());
   MediaMemoryTracker::AddMediaDecoder(this);
@@ -935,17 +936,17 @@ double MediaDecoder::ComputePlaybackRate
   GetReentrantMonitor().AssertCurrentThreadIn();
   MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread() || OnDecodeThread());
 
   int64_t length = mResource ? mResource->GetLength() : -1;
   if (mDuration >= 0 && length >= 0) {
     *aReliable = true;
     return length * static_cast<double>(USECS_PER_S) / mDuration;
   }
-  return mPlaybackStatistics.GetRateAtLastStop(aReliable);
+  return mPlaybackStatistics->GetRateAtLastStop(aReliable);
 }
 
 void MediaDecoder::UpdatePlaybackRate()
 {
   MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
   if (!mResource)
     return;
@@ -1027,17 +1028,17 @@ void MediaDecoder::NotifyBytesConsumed(i
   }
 
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   MOZ_ASSERT(mDecoderStateMachine);
   if (mIgnoreProgressData) {
     return;
   }
   if (aOffset >= mDecoderPosition) {
-    mPlaybackStatistics.AddBytes(aBytes);
+    mPlaybackStatistics->AddBytes(aBytes);
   }
   mDecoderPosition = aOffset + aBytes;
 }
 
 void MediaDecoder::UpdateReadyStateForData()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!mOwner || mShuttingDown || !mDecoderStateMachine)
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -713,24 +713,24 @@ public:
   // Something has changed that could affect the computed playback rate,
   // so recompute it. The monitor must be held.
   virtual void UpdatePlaybackRate();
 
   // Used to estimate rates of data passing through the decoder's channel.
   // Records activity stopping on the channel. The monitor must be held.
   virtual void NotifyPlaybackStarted() {
     GetReentrantMonitor().AssertCurrentThreadIn();
-    mPlaybackStatistics.Start();
+    mPlaybackStatistics->Start();
   }
 
   // Used to estimate rates of data passing through the decoder's channel.
   // Records activity stopping on the channel. The monitor must be held.
   virtual void NotifyPlaybackStopped() {
     GetReentrantMonitor().AssertCurrentThreadIn();
-    mPlaybackStatistics.Stop();
+    mPlaybackStatistics->Stop();
   }
 
   // The actual playback rate computation. The monitor must be held.
   virtual double ComputePlaybackRate(bool* aReliable);
 
   // Return true when the media is same-origin with the element. The monitor
   // must be held.
   bool IsSameOriginMedia();
@@ -1189,17 +1189,17 @@ protected:
   // when data is arriving slower than PROGRESS_MS. A value of null indicates
   // that a stall event has already fired and not to fire another one until
   // more data is received. Read/Write from the main thread only.
   TimeStamp mDataTime;
 
   // Data needed to estimate playback data rate. The timeline used for
   // this estimate is "decode time" (where the "current time" is the
   // time of the last decoded video frame).
-  MediaChannelStatistics mPlaybackStatistics;
+  nsRefPtr<MediaChannelStatistics> mPlaybackStatistics;
 
   // True when our media stream has been pinned. We pin the stream
   // while seeking.
   bool mPinnedForSeek;
 
   // True if the decoder is being shutdown. At this point all events that
   // are currently queued need to return immediately to prevent javascript
   // being run that operates on the element and decoder during shutdown.
--- a/content/media/MediaDecoderReader.h
+++ b/content/media/MediaDecoderReader.h
@@ -16,34 +16,27 @@ namespace mozilla {
 
 namespace dom {
 class TimeRanges;
 }
 
 class RequestSampleCallback;
 class MediaDecoderReader;
 
-template <>
-struct HasDangerousPublicDestructor<MediaDecoderReader>
-{
-  static const bool value = true;
-};
-
 // Encapsulates the decoding and reading of media data. Reading can either
 // synchronous and done on the calling "decode" thread, or asynchronous and
 // performed on a background thread, with the result being returned by
 // callback. Never hold the decoder monitor when calling into this class.
 // Unless otherwise specified, methods and fields of this class can only
 // be accessed on the decode task queue.
 class MediaDecoderReader {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
 
   MediaDecoderReader(AbstractMediaDecoder* aDecoder);
-  virtual ~MediaDecoderReader();
 
   // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
   // on failure.
   virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0;
 
   // True if this reader is waiting media resource allocation
   virtual bool IsWaitingMediaResources() { return false; }
   // True when this reader need to become dormant state
@@ -176,16 +169,17 @@ public:
   }
 
   AudioData* DecodeToFirstAudioData();
   VideoData* DecodeToFirstVideoData();
 
   MediaInfo GetMediaInfo() { return mInfo; }
 
 protected:
+  virtual ~MediaDecoderReader();
 
   // Overrides of this function should decodes an unspecified amount of
   // audio data, enqueuing the audio data in mAudioQueue. Returns true
   // when there's more audio to decode, false if the audio is finished,
   // end of file has been reached, or an un-recoverable read error has
   // occured. This function blocks until the decode is complete.
   virtual bool DecodeAudioData() {
     return false;
--- a/content/media/MediaResource.h
+++ b/content/media/MediaResource.h
@@ -33,22 +33,16 @@ static const int64_t RELIABLE_DATA_THRES
 class nsIHttpChannel;
 class nsIPrincipal;
 
 namespace mozilla {
 
 class MediaDecoder;
 class MediaChannelStatistics;
 
-template<>
-struct HasDangerousPublicDestructor<MediaChannelStatistics>
-{
-  static const bool value = true;
-};
-
 /**
  * This class is useful for estimating rates of data passing through
  * some channel. The idea is that activity on the channel "starts"
  * and "stops" over time. At certain times data passes through the
  * channel (usually while the channel is active; data passing through
  * an inactive channel is ignored). The GetRate() function computes
  * an estimate of the "current rate" of the channel, which is some
  * kind of average of the data passing through over the time the
@@ -114,16 +108,17 @@ public:
     double seconds = time.ToSeconds();
     *aReliable = (seconds >= 3.0) ||
                  (mAccumulatedBytes >= RELIABLE_DATA_THRESHOLD);
     if (seconds <= 0.0)
       return 0.0;
     return static_cast<double>(mAccumulatedBytes)/seconds;
   }
 private:
+  ~MediaChannelStatistics() {}
   int64_t      mAccumulatedBytes;
   TimeDuration mAccumulatedTime;
   TimeStamp    mLastStartTime;
   bool         mIsStarted;
 };
 
 // Forward declaration for use in MediaByteRange.
 class TimestampedMediaByteRange;
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -2781,17 +2781,18 @@ MediaStreamGraphImpl::CollectReports(nsI
     rv = aHandleReport->Callback(EmptyCString(), _path,                     \
                                  KIND_HEAP, UNITS_BYTES, _amount,           \
                                  NS_LITERAL_CSTRING(_desc), aData);         \
     NS_ENSURE_SUCCESS(rv, rv);                                              \
   } while (0)
 
   for (size_t i = 0; i < mAudioStreamSizes.Length(); i++) {
     const AudioNodeSizes& usage = mAudioStreamSizes[i];
-    const char* const nodeType =  usage.mNodeType.get();
+    const char* const nodeType =  usage.mNodeType.IsEmpty() ?
+                                  "<unknown>" : usage.mNodeType.get();
 
     nsPrintfCString domNodePath("explicit/webaudio/audio-node/%s/dom-nodes",
                                 nodeType);
     REPORT(domNodePath, usage.mDomNode,
            "Memory used by AudioNode DOM objects (Web Audio).");
 
     nsPrintfCString enginePath("explicit/webaudio/audio-node/%s/engine-objects",
                                nodeType);
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -227,16 +227,17 @@ public:
   virtual void NotifyMainThreadStateChanged() = 0;
 };
 
 /**
  * Helper struct used to keep track of memory usage by AudioNodes.
  */
 struct AudioNodeSizes
 {
+  AudioNodeSizes() : mDomNode(0), mStream(0), mEngine(0), mNodeType() {}
   size_t mDomNode;
   size_t mStream;
   size_t mEngine;
   nsCString mNodeType;
 };
 
 class MediaStreamGraphImpl;
 class SourceMediaStream;
--- a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp
+++ b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp
@@ -82,16 +82,19 @@ FFmpegDataDecoder::Init()
   mCodecContext.opaque = this;
 
   // FFmpeg takes this as a suggestion for what format to use for audio samples.
   mCodecContext.request_sample_fmt = AV_SAMPLE_FMT_FLT;
 
   // FFmpeg will call back to this to negotiate a video pixel format.
   mCodecContext.get_format = ChoosePixelFormat;
 
+  mCodecContext.extradata = mExtraData.begin();
+  mCodecContext.extradata_size = mExtraData.length();
+
   AVDictionary* opts = nullptr;
   if (avcodec_open2(&mCodecContext, codec, &opts) < 0) {
     NS_WARNING("Couldn't initialise ffmpeg decoder");
     return NS_ERROR_FAILURE;
   }
 
   if (mCodecContext.codec_type == AVMEDIA_TYPE_AUDIO &&
       mCodecContext.sample_fmt != AV_SAMPLE_FMT_FLT &&
--- a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.h
+++ b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __FFmpegDataDecoder_h__
 #define __FFmpegDataDecoder_h__
 
 #include "FFmpegDecoderModule.h"
 #include "FFmpegRuntimeLinker.h"
 #include "FFmpegCompat.h"
+#include "mozilla/Vector.h"
 
 namespace mozilla
 {
 
 class FFmpegDataDecoder : public MediaDataDecoder
 {
 public:
   FFmpegDataDecoder(MediaTaskQueue* aTaskQueue, AVCodecID aCodecID);
@@ -26,16 +27,17 @@ public:
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
   virtual nsresult Flush() MOZ_OVERRIDE;
   virtual nsresult Drain() = 0;
   virtual nsresult Shutdown() MOZ_OVERRIDE;
 
 protected:
   MediaTaskQueue* mTaskQueue;
   AVCodecContext mCodecContext;
+  Vector<uint8_t> mExtraData;
 
 private:
   static bool sFFmpegInitDone;
 
   AVCodecID mCodecID;
 };
 
 } // namespace mozilla
--- a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
+++ b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
@@ -28,16 +28,17 @@ FFmpegH264Decoder::FFmpegH264Decoder(
   MediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
   const mp4_demuxer::VideoDecoderConfig &aConfig,
   ImageContainer* aImageContainer)
   : FFmpegDataDecoder(aTaskQueue, AV_CODEC_ID_H264)
   , mCallback(aCallback)
   , mImageContainer(aImageContainer)
 {
   MOZ_COUNT_CTOR(FFmpegH264Decoder);
+  mExtraData.append(aConfig.extra_data.begin(), aConfig.extra_data.length());
 }
 
 nsresult
 FFmpegH264Decoder::Init()
 {
   nsresult rv = FFmpegDataDecoder::Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/media/fmp4/wmf/WMFAudioOutputSource.cpp
+++ b/content/media/fmp4/wmf/WMFAudioOutputSource.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WMFAudioOutputSource.h"
+#include "mp4_demuxer/DecoderData.h"
 #include "VideoUtils.h"
 #include "WMFUtils.h"
 #include "nsTArray.h"
 
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* GetDemuxerLog();
@@ -123,16 +124,24 @@ WMFAudioOutputSource::Init()
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   mDecoder = decoder;
 
   return decoder.forget();
 }
 
 HRESULT
+WMFAudioOutputSource::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
+  uint32_t length = aSample->size;
+  return mDecoder->Input(data, length, aSample->composition_timestamp);
+}
+
+HRESULT
 WMFAudioOutputSource::Output(int64_t aStreamOffset,
                         nsAutoPtr<MediaData>& aOutData)
 {
   aOutData = nullptr;
   RefPtr<IMFSample> sample;
   HRESULT hr = mDecoder->Output(&sample);
   if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
     return MF_E_TRANSFORM_NEED_MORE_INPUT;
--- a/content/media/fmp4/wmf/WMFAudioOutputSource.h
+++ b/content/media/fmp4/wmf/WMFAudioOutputSource.h
@@ -17,16 +17,18 @@ namespace mozilla {
 
 class WMFAudioOutputSource : public WMFOutputSource {
 public:
   WMFAudioOutputSource(const mp4_demuxer::AudioDecoderConfig& aConfig);
   ~WMFAudioOutputSource();
 
   virtual TemporaryRef<MFTDecoder> Init() MOZ_OVERRIDE;
 
+  virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
   // Note WMF's AAC decoder sometimes output negatively timestamped samples,
   // presumably they're the preroll samples, and we strip them. We may return
   // a null aOutput in this case.
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 private:
 
   // IMFTransform wrapper that performs the decoding.
--- a/content/media/fmp4/wmf/WMFDecoderModule.cpp
+++ b/content/media/fmp4/wmf/WMFDecoderModule.cpp
@@ -65,17 +65,18 @@ WMFDecoderModule::Shutdown()
 
 MediaDataDecoder*
 WMFDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
                                     mozilla::layers::LayersBackend aLayersBackend,
                                     mozilla::layers::ImageContainer* aImageContainer,
                                     MediaTaskQueue* aVideoTaskQueue,
                                     MediaDataDecoderCallback* aCallback)
 {
-  return new WMFMediaDataDecoder(new WMFVideoOutputSource(aLayersBackend,
+  return new WMFMediaDataDecoder(new WMFVideoOutputSource(aConfig,
+                                                          aLayersBackend,
                                                           aImageContainer,
                                                           sDXVAEnabled),
                                  aVideoTaskQueue,
                                  aCallback);
 }
 
 MediaDataDecoder*
 WMFDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
--- a/content/media/fmp4/wmf/WMFMediaDataDecoder.cpp
+++ b/content/media/fmp4/wmf/WMFMediaDataDecoder.cpp
@@ -62,21 +62,19 @@ WMFMediaDataDecoder::Input(mp4_demuxer::
       &WMFMediaDataDecoder::ProcessDecode,
       nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
   return NS_OK;
 }
 
 void
 WMFMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample)
 {
-  const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
-  uint32_t length = aSample->size;
-  HRESULT hr = mDecoder->Input(data, length, aSample->composition_timestamp);
+  HRESULT hr = mSource->Input(aSample);
   if (FAILED(hr)) {
-    NS_WARNING("WMFAudioDecoder failed to input data");
+    NS_WARNING("WMFOutputSource rejected sample");
     mCallback->Error();
     return;
   }
 
   mLastStreamOffset = aSample->byte_offset;
 
   ProcessOutput();
 }
--- a/content/media/fmp4/wmf/WMFMediaDataDecoder.h
+++ b/content/media/fmp4/wmf/WMFMediaDataDecoder.h
@@ -8,29 +8,36 @@
 #define WMFMediaDataDecoder_h_
 
 
 #include "WMF.h"
 #include "MP4Reader.h"
 #include "MFTDecoder.h"
 #include "mozilla/RefPtr.h"
 
+class mp4_demuxer::MP4Sample;
+
 namespace mozilla {
 
 // Encapsulates the initialization of the MFTDecoder appropriate for decoding
 // a given stream, and the process of converting the IMFSample produced
 // by the MFT into a MediaData object.
 class WMFOutputSource {
 public:
   virtual ~WMFOutputSource() {}
 
   // Creates an initializs the MFTDecoder.
   // Returns nullptr on failure.
   virtual TemporaryRef<MFTDecoder> Init() = 0;
 
+  // Submit a compressed sample for decoding.
+  // This should forward to the MFTDecoder after performing
+  // any required sample formatting.
+  virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) = 0;
+
   // Produces decoded output, if possible. Blocks until output can be produced,
   // or until no more is able to be produced.
   // Returns S_OK on success, or MF_E_TRANSFORM_NEED_MORE_INPUT if there's not
   // enough data to produce more output. If this returns a failure code other
   // than MF_E_TRANSFORM_NEED_MORE_INPUT, an error will be reported to the
   // MP4Reader.
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsAutoPtr<MediaData>& aOutput) = 0;
--- a/content/media/fmp4/wmf/WMFVideoOutputSource.cpp
+++ b/content/media/fmp4/wmf/WMFVideoOutputSource.cpp
@@ -8,16 +8,18 @@
 #include "MediaDecoderReader.h"
 #include "WMFUtils.h"
 #include "ImageContainer.h"
 #include "VideoUtils.h"
 #include "DXVA2Manager.h"
 #include "nsThreadUtils.h"
 #include "Layers.h"
 #include "mozilla/layers/LayersTypes.h"
+#include "mp4_demuxer/AnnexB.h"
+#include "mp4_demuxer/DecoderData.h"
 #include "prlog.h"
 #include "gfx2DGlue.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* GetDemuxerLog();
 #define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
 #else
 #define LOG(...)
@@ -25,22 +27,25 @@ PRLogModuleInfo* GetDemuxerLog();
 
 using mozilla::gfx::ToIntRect;
 using mozilla::layers::Image;
 using mozilla::layers::LayerManager;
 using mozilla::layers::LayersBackend;
 
 namespace mozilla {
 
-WMFVideoOutputSource::WMFVideoOutputSource(mozilla::layers::LayersBackend aLayersBackend,
-                                 mozilla::layers::ImageContainer* aImageContainer,
-                                 bool aDXVAEnabled)
+WMFVideoOutputSource::WMFVideoOutputSource(
+                            const mp4_demuxer::VideoDecoderConfig& aConfig,
+                            mozilla::layers::LayersBackend aLayersBackend,
+                            mozilla::layers::ImageContainer* aImageContainer,
+                            bool aDXVAEnabled)
   : mVideoStride(0)
   , mVideoWidth(0)
   , mVideoHeight(0)
+  , mConfig(aConfig)
   , mImageContainer(aImageContainer)
   , mDXVAEnabled(aDXVAEnabled)
   , mLayersBackend(aLayersBackend)
   , mUseHwAccel(false)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
   MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(WMFVideoOutputSource);
@@ -134,16 +139,27 @@ WMFVideoOutputSource::Init()
 
   mDecoder = decoder;
   LOG("Video Decoder initialized, Using DXVA: %s", (mUseHwAccel ? "Yes" : "No"));
 
   return decoder.forget();
 }
 
 HRESULT
+WMFVideoOutputSource::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  // We must prepare samples in AVC Annex B.
+  mp4_demuxer::AnnexB::ConvertSample(aSample, mConfig.annex_b);
+  // Forward sample data to the decoder.
+  const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
+  uint32_t length = aSample->size;
+  return mDecoder->Input(data, length, aSample->composition_timestamp);
+}
+
+HRESULT
 WMFVideoOutputSource::ConfigureVideoFrameGeometry()
 {
   RefPtr<IMFMediaType> mediaType;
   HRESULT hr = mDecoder->GetOutputMediaType(mediaType);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   // Verify that the video subtype is what we expect it to be.
   // When using hardware acceleration/DXVA2 the video format should
--- a/content/media/fmp4/wmf/WMFVideoOutputSource.h
+++ b/content/media/fmp4/wmf/WMFVideoOutputSource.h
@@ -15,23 +15,26 @@
 #include "mozilla/RefPtr.h"
 
 namespace mozilla {
 
 class DXVA2Manager;
 
 class WMFVideoOutputSource : public WMFOutputSource {
 public:
-  WMFVideoOutputSource(mozilla::layers::LayersBackend aLayersBackend,
+  WMFVideoOutputSource(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                       mozilla::layers::LayersBackend aLayersBackend,
                        mozilla::layers::ImageContainer* aImageContainer,
                        bool aDXVAEnabled);
   ~WMFVideoOutputSource();
 
   virtual TemporaryRef<MFTDecoder> Init() MOZ_OVERRIDE;
 
+  virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
   virtual HRESULT Output(int64_t aStreamOffset,
                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
 private:
 
   bool InitializeDXVA();
 
   HRESULT ConfigureVideoFrameGeometry();
@@ -46,16 +49,18 @@ private:
 
   // Video frame geometry.
   VideoInfo mVideoInfo;
   uint32_t mVideoStride;
   uint32_t mVideoWidth;
   uint32_t mVideoHeight;
   nsIntRect mPictureRegion;
 
+  const mp4_demuxer::VideoDecoderConfig& mConfig;
+
   RefPtr<MFTDecoder> mDecoder;
   RefPtr<layers::ImageContainer> mImageContainer;
   nsAutoPtr<DXVA2Manager> mDXVA2Manager;
   RefPtr<MediaTaskQueue> mTaskQueue;
   MediaDataDecoderCallback* mCallback;
 
   const bool mDXVAEnabled;
   const layers::LayersBackend mLayersBackend;
--- a/content/media/mediasource/MediaSource.h
+++ b/content/media/mediasource/MediaSource.h
@@ -9,17 +9,16 @@
 
 #include "MediaSourceDecoder.h"
 #include "js/RootingAPI.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/MediaSourceBinding.h"
 #include "mozilla/Monitor.h"
-#include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionNoteChild.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsID.h"
 #include "nsISupports.h"
 #include "nscore.h"
 
 struct JSContext;
--- a/content/media/mediasource/MediaSourceDecoder.cpp
+++ b/content/media/mediasource/MediaSourceDecoder.cpp
@@ -9,16 +9,17 @@
 #include "AbstractMediaDecoder.h"
 #include "MediaDecoderReader.h"
 #include "MediaDecoderStateMachine.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "mozilla/mozalloc.h"
+#include "nsAutoPtr.h"
 #include "nsISupports.h"
 #include "nsIThread.h"
 #include "prlog.h"
 #include "MediaSource.h"
 #include "SubBufferDecoder.h"
 #include "SourceBufferResource.h"
 #include "SourceBufferList.h"
 #include "VideoUtils.h"
@@ -409,31 +410,31 @@ MediaSourceReader::InitializePendingDeco
 already_AddRefed<SubBufferDecoder>
 MediaSourceReader::CreateSubDecoder(const nsACString& aType,
                                     MediaSourceDecoder* aParentDecoder,
                                     MediaTaskQueue* aTaskQueue)
 {
   // XXX: Why/when is mDecoder null here, since it should be equal to aParentDecoder?!
   nsRefPtr<SubBufferDecoder> decoder =
     new SubBufferDecoder(new SourceBufferResource(nullptr, aType), aParentDecoder);
-  nsAutoPtr<MediaDecoderReader> reader(DecoderTraits::CreateReader(aType, decoder));
+  nsRefPtr<MediaDecoderReader> reader(DecoderTraits::CreateReader(aType, decoder));
   if (!reader) {
     return nullptr;
   }
   // Set a callback on the subreader that forwards calls to this reader.
   // This reader will then forward them onto the state machine via this
   // reader's callback.
   RefPtr<MediaDataDecodedListener<MediaSourceReader>> callback =
     new MediaDataDecodedListener<MediaSourceReader>(this, aTaskQueue);
   reader->SetCallback(callback);
   reader->SetTaskQueue(aTaskQueue);
   reader->Init(nullptr);
   ReentrantMonitorAutoEnter mon(aParentDecoder->GetReentrantMonitor());
   MSE_DEBUG("Registered subdecoder %p subreader %p", decoder.get(), reader.get());
-  decoder->SetReader(reader.forget());
+  decoder->SetReader(reader);
   mPendingDecoders.AppendElement(decoder);
   if (NS_FAILED(static_cast<MediaSourceDecoder*>(mDecoder)->EnqueueDecoderInitialization())) {
     MSE_DEBUG("%p: Failed to enqueue decoder initialization task", this);
     return nullptr;
   }
   mDecoder->NotifyWaitingForResourcesStatusChanged();
   return decoder.forget();
 }
--- a/content/media/mediasource/SourceBufferList.h
+++ b/content/media/mediasource/SourceBufferList.h
@@ -7,17 +7,16 @@
 #ifndef mozilla_dom_SourceBufferList_h_
 #define mozilla_dom_SourceBufferList_h_
 
 #include "SourceBuffer.h"
 #include "js/RootingAPI.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
-#include "nsAutoPtr.h"
 #include "nsCycleCollectionNoteChild.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupports.h"
 #include "nsTArray.h"
 
 struct JSContext;
 class JSObject;
 
--- a/content/media/mediasource/SubBufferDecoder.h
+++ b/content/media/mediasource/SubBufferDecoder.h
@@ -81,16 +81,16 @@ public:
 
   void SetMediaStartTime(int64_t aMediaStartTime)
   {
     mMediaStartTime = aMediaStartTime;
   }
 
 private:
   MediaSourceDecoder* mParentDecoder;
-  nsAutoPtr<MediaDecoderReader> mReader;
+  nsRefPtr<MediaDecoderReader> mReader;
   int64_t mMediaDuration;
   int64_t mMediaStartTime;
 };
 
 } // namespace mozilla
 
 #endif /* MOZILLA_SUBBUFFERDECODER_H_ */
--- a/content/media/plugins/MediaResourceServer.cpp
+++ b/content/media/plugins/MediaResourceServer.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "mozilla/Assertions.h"
 #include "mozilla/Base64.h"
+#include "mozilla/IntegerPrintfMacros.h"
 #include "nsThreadUtils.h"
 #include "nsIServiceManager.h"
 #include "nsISocketTransport.h"
 #include "nsIOutputStream.h"
 #include "nsIInputStream.h"
 #include "nsIRandomGenerator.h"
 #include "nsReadLine.h"
 #include "nsNetCID.h"
@@ -223,17 +224,17 @@ ServeResourceEvent::Run() {
     // the end of the resource and the client is informed of this via
     // the content-range header.
     NS_NAMED_LITERAL_CSTRING(byteRange, "Range: bytes=");
     const char* s = strstr(line.get(), byteRange.get());
     if (s) {
       start = strtoll(s+byteRange.Length(), nullptr, 10);
 
       // Clamp 'start' to be between 0 and the resource length.
-      start = std::max(0ll, std::min(resource->GetLength(), start));
+      start = std::max(int64_t(0), std::min(resource->GetLength(), start));
     }
   }
 
   // HTTP response to use if this is a non byte range request
   const char* response_normal = "HTTP/1.1 200 OK\r\n";
 
   // HTTP response to use if this is a byte range request
   const char* response_range = "HTTP/1.1 206 Partial Content\r\n";
@@ -263,28 +264,29 @@ ServeResourceEvent::Run() {
   nsAutoArrayPtr<char> b(new char[buffer_size]);
 
   // If we know the length of the resource, send a Content-Length header.
   int64_t contentlength = resource->GetLength() - start;
   if (contentlength > 0) {
     static_assert (buffer_size > 1024,
                    "buffer_size must be large enough "
                    "to hold response headers");
-    snprintf(b, buffer_size, "Content-Length: %lld\r\n", contentlength);
+    snprintf(b, buffer_size, "Content-Length: %" PRId64 "\r\n", contentlength);
     rv = WriteAll(b, strlen(b));
     if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
   }
 
   // If the request was a byte range request, respond with a Content-Range
   // header which details the extent of the data returned.
   if (start > 0) {
     static_assert (buffer_size > 1024,
                    "buffer_size must be large enough "
                    "to hold response headers");
-    snprintf(b, buffer_size, "Content-Range: bytes %lld-%lld/%lld\r\n",
+    snprintf(b, buffer_size, "Content-Range: "
+             "bytes %" PRId64 "-%" PRId64 "/%" PRId64 "\r\n",
              start, resource->GetLength() - 1, resource->GetLength());
     rv = WriteAll(b, strlen(b));
     if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
   }
 
   rv = WriteAll(response_end, strlen(response_end));
   if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
 
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -432,16 +432,17 @@ AudioContext::Listener()
 }
 
 void
 AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
                               DecodeSuccessCallback& aSuccessCallback,
                               const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback)
 {
   AutoJSAPI jsapi;
+  jsapi.Init();
   JSContext* cx = jsapi.cx();
   JSAutoCompartment ac(cx, aBuffer.Obj());
 
   aBuffer.ComputeLengthAndData();
 
   // Neuter the array buffer
   size_t length = aBuffer.Length();
   JS::RootedObject obj(cx, aBuffer.Obj());
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -121,25 +121,21 @@ public:
   void FireOfflineCompletionEvent(AudioDestinationNode* aNode)
   {
     AudioContext* context = aNode->Context();
     context->Shutdown();
     // Shutdown drops self reference, but the context is still referenced by aNode,
     // which is strongly referenced by the runnable that called
     // AudioDestinationNode::FireOfflineCompletionEvent.
 
-    // We need the global for the context so that we can enter its compartment.
-    JSObject* global = context->GetGlobalJSObject();
-    if (NS_WARN_IF(!global)) {
+    AutoJSAPI jsapi;
+    if (NS_WARN_IF(!jsapi.InitUsingWin(aNode->GetOwner()))) {
       return;
     }
-
-    AutoJSAPI jsapi;
     JSContext* cx = jsapi.cx();
-    JSAutoCompartment ac(cx, global);
 
     // Create the input buffer
     ErrorResult rv;
     nsRefPtr<AudioBuffer> renderedBuffer =
       AudioBuffer::Create(context, mInputChannels.Length(),
                           mLength, mSampleRate, cx, rv);
     if (rv.Failed()) {
       return;
--- a/content/media/webaudio/AudioProcessingEvent.cpp
+++ b/content/media/webaudio/AudioProcessingEvent.cpp
@@ -36,26 +36,22 @@ AudioProcessingEvent::WrapObject(JSConte
 {
   return AudioProcessingEventBinding::Wrap(aCx, this);
 }
 
 already_AddRefed<AudioBuffer>
 AudioProcessingEvent::LazilyCreateBuffer(uint32_t aNumberOfChannels,
                                          ErrorResult& aRv)
 {
-  // We need the global for the context so that we can enter its compartment.
-  JSObject* global = mNode->Context()->GetGlobalJSObject();
-  if (NS_WARN_IF(!global)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(mNode->GetOwner()))) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, global);
 
   nsRefPtr<AudioBuffer> buffer =
     AudioBuffer::Create(mNode->Context(), aNumberOfChannels,
                         mNode->BufferSize(),
                         mNode->Context()->SampleRate(), cx, aRv);
   MOZ_ASSERT(buffer || aRv.ErrorCode() == NS_ERROR_OUT_OF_MEMORY);
   return buffer.forget();
 }
--- a/content/media/webaudio/MediaBufferDecoder.cpp
+++ b/content/media/webaudio/MediaBufferDecoder.cpp
@@ -11,16 +11,17 @@
 #include <speex/speex_resampler.h>
 #include "nsXPCOMCIDInternal.h"
 #include "nsComponentManagerUtils.h"
 #include "MediaDecoderReader.h"
 #include "BufferMediaResource.h"
 #include "DecoderTraits.h"
 #include "AudioContext.h"
 #include "AudioBuffer.h"
+#include "nsAutoPtr.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsMimeTypes.h"
 #include "WebAudioUtils.h"
 
 namespace mozilla {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(WebAudioDecodeJob)
@@ -146,17 +147,17 @@ private:
   nsCString mContentType;
   uint8_t* mBuffer;
   uint32_t mLength;
   WebAudioDecodeJob& mDecodeJob;
   PhaseEnum mPhase;
   nsCOMPtr<nsIThreadPool> mThreadPool;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsRefPtr<BufferDecoder> mBufferDecoder;
-  nsAutoPtr<MediaDecoderReader> mDecoderReader;
+  nsRefPtr<MediaDecoderReader> mDecoderReader;
 };
 
 NS_IMETHODIMP
 MediaDecodeTask::Run()
 {
   MOZ_ASSERT(mBufferDecoder);
   MOZ_ASSERT(mDecoderReader);
   switch (mPhase) {
@@ -407,25 +408,21 @@ MediaDecodeTask::CallbackTheResult()
 }
 
 bool
 WebAudioDecodeJob::AllocateBuffer()
 {
   MOZ_ASSERT(!mOutput);
   MOZ_ASSERT(NS_IsMainThread());
 
-  // We need the global for the context so that we can enter its compartment.
-  JSObject* global = mContext->GetGlobalJSObject();
-  if (NS_WARN_IF(!global)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(mContext->GetOwner()))) {
     return false;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, global);
 
   // Now create the AudioBuffer
   ErrorResult rv;
   mOutput = AudioBuffer::Create(mContext, mChannelBuffers.Length(),
                                 mWriteIndex, mContext->SampleRate(), cx, rv);
   if (rv.Failed()) {
     return false;
   }
@@ -445,25 +442,27 @@ MediaBufferDecoder::AsyncDecodeMedia(con
   // Do not attempt to decode the media if we were not successful at sniffing
   // the content type.
   if (!*aContentType ||
       strcmp(aContentType, APPLICATION_OCTET_STREAM) == 0) {
     nsCOMPtr<nsIRunnable> event =
       new ReportResultTask(aDecodeJob,
                            &WebAudioDecodeJob::OnFailure,
                            WebAudioDecodeJob::UnknownContent);
+    JS_free(nullptr, aBuffer);
     NS_DispatchToMainThread(event);
     return;
   }
 
   if (!EnsureThreadPoolInitialized()) {
     nsCOMPtr<nsIRunnable> event =
       new ReportResultTask(aDecodeJob,
                            &WebAudioDecodeJob::OnFailure,
                            WebAudioDecodeJob::UnknownError);
+    JS_free(nullptr, aBuffer);
     NS_DispatchToMainThread(event);
     return;
   }
 
   MOZ_ASSERT(mThreadPool);
 
   nsRefPtr<MediaDecodeTask> task =
     new MediaDecodeTask(aContentType, aBuffer, aLength, aDecodeJob, mThreadPool);
--- a/content/media/webaudio/MediaBufferDecoder.h
+++ b/content/media/webaudio/MediaBufferDecoder.h
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MediaBufferDecoder_h_
 #define MediaBufferDecoder_h_
 
 #include "nsWrapperCache.h"
 #include "nsCOMPtr.h"
-#include "nsAutoPtr.h"
 #include "nsIThreadPool.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/MemoryReporting.h"
 
 namespace mozilla {
 
--- a/content/media/webaudio/ScriptProcessorNode.cpp
+++ b/content/media/webaudio/ScriptProcessorNode.cpp
@@ -397,25 +397,21 @@ private:
           // this function.
           MutexAutoLock lock(mStream->Engine()->NodeMutex());
           node = static_cast<ScriptProcessorNode*>(mStream->Engine()->Node());
         }
         if (!node || !node->Context()) {
           return NS_OK;
         }
 
-        // Get the global for the context so that we can enter its compartment.
-        JSObject* global = node->Context()->GetGlobalJSObject();
-        if (NS_WARN_IF(!global)) {
+        AutoJSAPI jsapi;
+        if (NS_WARN_IF(!jsapi.InitUsingWin(node->GetOwner()))) {
           return NS_OK;
         }
-
-        AutoJSAPI jsapi;
         JSContext* cx = jsapi.cx();
-        JSAutoCompartment ac(cx, global);
 
         // Create the input buffer
         nsRefPtr<AudioBuffer> inputBuffer;
         if (!mNullInput) {
           ErrorResult rv;
           inputBuffer =
             AudioBuffer::Create(node->Context(), mInputChannels.Length(),
                                 node->BufferSize(),
--- a/content/media/webrtc/LoadManager.cpp
+++ b/content/media/webrtc/LoadManager.cpp
@@ -35,25 +35,25 @@ namespace mozilla {
 
 NS_IMPL_ISUPPORTS(LoadManagerSingleton, nsIObserver)
 
 
 LoadManagerSingleton::LoadManagerSingleton(int aLoadMeasurementInterval,
                                            int aAveragingMeasurements,
                                            float aHighLoadThreshold,
                                            float aLowLoadThreshold)
-  : mLoadSum(0.0f),
+  : mLock("LoadManager"),
+    mCurrentState(webrtc::kLoadNormal),
+    mOveruseActive(false),
+    mLoadSum(0.0f),
     mLoadSumMeasurements(0),
-    mOveruseActive(false),
     mLoadMeasurementInterval(aLoadMeasurementInterval),
     mAveragingMeasurements(aAveragingMeasurements),
     mHighLoadThreshold(aHighLoadThreshold),
-    mLowLoadThreshold(aLowLoadThreshold),
-    mCurrentState(webrtc::kLoadNormal),
-    mLock("LoadManager")
+    mLowLoadThreshold(aLowLoadThreshold)
 {
 #if defined(PR_LOGGING)
   if (!gLoadManagerLog)
     gLoadManagerLog = PR_NewLogModule("LoadManager");
 #endif
   LOG(("LoadManager - Initializing (%dms x %d, %f, %f)",
        mLoadMeasurementInterval, mAveragingMeasurements,
        mHighLoadThreshold, mLowLoadThreshold));
--- a/content/media/webrtc/LoadManager.h
+++ b/content/media/webrtc/LoadManager.h
@@ -49,18 +49,18 @@ private:
                          float aHighLoadThreshold,
                          float aLowLoadThreshold);
     ~LoadManagerSingleton();
 
     void LoadHasChanged();
 
     nsRefPtr<LoadMonitor> mLoadMonitor;
 
-    // This protexts access to the mObservers list, the current state, pretty much all
-    // the other members (below)
+    // This protects access to the mObservers list, the current state, and
+    // pretty much all the other members (below).
     Mutex mLock;
     nsTArray<webrtc::CPULoadStateObserver*> mObservers;
     webrtc::CPULoadState mCurrentState;
     // Set when overuse was signaled to us, and hasn't been un-signaled yet.
     bool  mOveruseActive;
     float mLoadSum;
     int   mLoadSumMeasurements;
     // Load measurement settings
--- a/content/media/webrtc/LoadManagerFactory.cpp
+++ b/content/media/webrtc/LoadManagerFactory.cpp
@@ -24,19 +24,19 @@ LoadManagerSingleton::Get() {
   if (!sSingleton) {
     MOZ_ASSERT(NS_IsMainThread());
 
     int loadMeasurementInterval =
       mozilla::Preferences::GetInt("media.navigator.load_adapt.measure_interval", 1000);
     int averagingSeconds =
       mozilla::Preferences::GetInt("media.navigator.load_adapt.avg_seconds", 3);
     float highLoadThreshold =
-      mozilla::Preferences::GetFloat("media.navigator.load_adapt.high_load", 0.90);
+      mozilla::Preferences::GetFloat("media.navigator.load_adapt.high_load", 0.90f);
     float lowLoadThreshold =
-      mozilla::Preferences::GetFloat("media.navigator.load_adapt.low_load", 0.40);
+      mozilla::Preferences::GetFloat("media.navigator.load_adapt.low_load", 0.40f);
 
     sSingleton = new LoadManagerSingleton(loadMeasurementInterval,
                                           averagingSeconds,
                                           highLoadThreshold,
                                           lowLoadThreshold);
 
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     if (obs) {
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -262,23 +262,23 @@ private:
 };
 
 class MediaEngineWebRTCAudioSource : public MediaEngineAudioSource,
                                      public webrtc::VoEMediaProcess
 {
 public:
   MediaEngineWebRTCAudioSource(webrtc::VoiceEngine* aVoiceEnginePtr, int aIndex,
     const char* name, const char* uuid)
-    : mVoiceEngine(aVoiceEnginePtr)
+    : mSamples(0)
+    , mVoiceEngine(aVoiceEnginePtr)
     , mMonitor("WebRTCMic.Monitor")
     , mCapIndex(aIndex)
     , mChannel(-1)
     , mInitDone(false)
     , mStarted(false)
-    , mSamples(0)
     , mEchoOn(false), mAgcOn(false), mNoiseOn(false)
     , mEchoCancel(webrtc::kEcDefault)
     , mAGC(webrtc::kAgcDefault)
     , mNoiseSuppress(webrtc::kNsDefault)
     , mPlayoutDelay(0)
     , mNullTransport(nullptr) {
     MOZ_ASSERT(aVoiceEnginePtr);
     mState = kReleased;
@@ -314,16 +314,23 @@ public:
 
   // VoEMediaProcess.
   void Process(int channel, webrtc::ProcessingTypes type,
                int16_t audio10ms[], int length,
                int samplingFreq, bool isStereo);
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
+protected:
+  // mSamples is an int to avoid conversions when comparing/etc to
+  // samplingFreq & length. Making mSamples protected instead of private is a
+  // silly way to avoid -Wunused-private-field warnings when PR_LOGGING is not
+  // #defined. mSamples is not actually expected to be used by a derived class.
+  int mSamples;
+
 private:
   static const unsigned int KMaxDeviceNameLength = 128;
   static const unsigned int KMaxUniqueIdLength = 256;
 
   void Init();
   void Shutdown();
 
   webrtc::VoiceEngine* mVoiceEngine;
@@ -339,17 +346,16 @@ private:
   Monitor mMonitor;
   nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW
 
   int mCapIndex;
   int mChannel;
   TrackID mTrackID;
   bool mInitDone;
   bool mStarted;
-  int mSamples; // int to avoid conversions when comparing/etc to samplingFreq & length
 
   nsString mDeviceName;
   nsString mDeviceUUID;
 
   bool mEchoOn, mAgcOn, mNoiseOn;
   webrtc::EcModes  mEchoCancel;
   webrtc::AgcModes mAGC;
   webrtc::NsModes  mNoiseSuppress;
--- a/content/media/webrtc/PeerIdentity.cpp
+++ b/content/media/webrtc/PeerIdentity.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=2 sts=2 expandtab
  * 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 "PeerIdentity.h"
 
+#include "mozilla/DebugOnly.h"
 #include "nsCOMPtr.h"
 #include "nsIIDNService.h"
 #include "nsNetCID.h"
 #include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 
 bool
@@ -71,14 +72,14 @@ PeerIdentity::GetHost(const nsAString& a
   }
 }
 
 /* static */ void
 PeerIdentity::GetNormalizedHost(const nsCOMPtr<nsIIDNService>& aIdnService,
                                 const nsAString& aHost,
                                 nsACString& aNormalizedHost)
 {
-  nsCString chost = NS_ConvertUTF16toUTF8(aHost);
-  nsresult rv = aIdnService->ConvertUTF8toACE(chost, aNormalizedHost);
-  NS_WARN_IF(NS_FAILED(rv));
+  const nsCString chost = NS_ConvertUTF16toUTF8(aHost);
+  DebugOnly<nsresult> rv = aIdnService->ConvertUTF8toACE(chost, aNormalizedHost);
+  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to convert UTF-8 host to ASCII");
 }
 
 } /* namespace mozilla */
--- a/content/media/webrtc/moz.build
+++ b/content/media/webrtc/moz.build
@@ -52,8 +52,16 @@ EXPORTS.mozilla += [
     'PeerIdentity.h',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 if CONFIG['OS_ARCH'] == 'WINNT':
     DEFINES['NOMINMAX'] = True
+
+
+if CONFIG['_MSC_VER']:
+  CXXFLAGS += [
+    '-wd4275', # non dll-interface class used as base for dll-interface class
+  ]
+
+FAIL_ON_WARNINGS = True
--- a/content/svg/document/src/SVGDocument.cpp
+++ b/content/svg/document/src/SVGDocument.cpp
@@ -138,29 +138,29 @@ SVGDocument::EnsureNonSVGUserAgentStyleS
           catMan->GetCategoryEntry("agent-style-sheets", name.get(),
                                    getter_Copies(spec));
 
           mozilla::css::Loader* cssLoader = CSSLoader();
           if (cssLoader->GetEnabled()) {
             nsCOMPtr<nsIURI> uri;
             NS_NewURI(getter_AddRefs(uri), spec);
             if (uri) {
-              nsRefPtr<nsCSSStyleSheet> cssSheet;
+              nsRefPtr<CSSStyleSheet> cssSheet;
               cssLoader->LoadSheetSync(uri, true, true, getter_AddRefs(cssSheet));
               if (cssSheet) {
                 EnsureOnDemandBuiltInUASheet(cssSheet);
               }
             }
           }
         }
       }
     }
   }
 
-  nsCSSStyleSheet* sheet = nsLayoutStylesheetCache::NumberControlSheet();
+  CSSStyleSheet* sheet = nsLayoutStylesheetCache::NumberControlSheet();
   if (sheet) {
     // number-control.css can be behind a pref
     EnsureOnDemandBuiltInUASheet(sheet);
   }
   EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::FormsSheet());
   EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::CounterStylesSheet());
   EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::HTMLSheet());
   EnsureOnDemandBuiltInUASheet(nsLayoutStylesheetCache::UASheet());
--- a/content/test/unit/test_range.js
+++ b/content/test/unit/test_range.js
@@ -132,17 +132,16 @@ function evalXPathInDocumentFragment(aCo
                  targetType,
                  filter);
   var targetNode = walker.nextNode();
   do_check_neq(targetNode, null);
 
   // Apply our remaining xpath to the found node.
   var expr = aContextNode.ownerDocument.createExpression(realPath, null);
   var result = expr.evaluate(targetNode, UNORDERED_TYPE, null);
-  do_check_true(result instanceof C_i.nsIDOMXPathResult);
   return result.singleNodeValue;
 }
 
 /**
  * Get a DOM range corresponding to the test's source node.
  *
  * @param aSourceNode <source/> element with range information.
  * @param aFragment   DocumentFragment generated with getFragment().
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -15,17 +15,17 @@
 #include "nsNetUtil.h"
 #include "nsIDocShell.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMCDATASection.h"
 #include "DocumentType.h"
 #include "nsHTMLParts.h"
 #include "nsCRT.h"
-#include "nsCSSStyleSheet.h"
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Loader.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsIScriptContext.h"
 #include "nsNameSpaceManager.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIContentViewer.h"
@@ -58,16 +58,17 @@
 #include "nsHtml5SVGLoadDispatcher.h"
 #include "nsTextNode.h"
 #include "mozilla/dom/CDATASection.h"
 #include "mozilla/dom/Comment.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/ProcessingInstruction.h"
 
+using namespace mozilla;
 using namespace mozilla::dom;
 
 // XXX Open Issues:
 // 1) what's not allowed - We need to figure out which HTML tags
 //    (prefixed with a HTML namespace qualifier) are explicitly not
 //    allowed (if any).
 // 2) factoring code with nsHTMLContentSink - There's some amount of
 //    common code between this and the HTML content sink. This will
@@ -409,17 +410,17 @@ nsXMLContentSink::OnTransformDone(nsresu
   ScrollToRef();
 
   originalDocument->EndLoad();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXMLContentSink::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
+nsXMLContentSink::StyleSheetLoaded(CSSStyleSheet* aSheet,
                                    bool aWasAlternate,
                                    nsresult aStatus)
 {
   if (!mPrettyPrinting) {
     return nsContentSink::StyleSheetLoaded(aSheet, aWasAlternate, aStatus);
   }
 
   if (!mDocument->CSSLoader()->HasPendingLoads()) {
--- a/content/xml/document/src/nsXMLContentSink.h
+++ b/content/xml/document/src/nsXMLContentSink.h
@@ -78,17 +78,18 @@ public:
   virtual bool IsScriptExecuting() MOZ_OVERRIDE;
   virtual void ContinueInterruptedParsingAsync() MOZ_OVERRIDE;
 
   // nsITransformObserver
   NS_IMETHOD OnDocumentCreated(nsIDocument *aResultDocument) MOZ_OVERRIDE;
   NS_IMETHOD OnTransformDone(nsresult aResult, nsIDocument *aResultDocument) MOZ_OVERRIDE;
 
   // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, bool aWasAlternate,
+  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+                              bool aWasAlternate,
                               nsresult aStatus) MOZ_OVERRIDE;
   static bool ParsePIData(const nsString &aData, nsString &aHref,
                           nsString &aTitle, nsString &aMedia,
                           bool &aIsAlternate);
 
 protected:
 
   nsIParser* GetParser();
--- a/content/xul/document/src/XULDocument.cpp
+++ b/content/xul/document/src/XULDocument.cpp
@@ -66,27 +66,28 @@
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsIParser.h"
 #include "nsCharsetSource.h"
 #include "nsIParserService.h"
-#include "nsCSSStyleSheet.h"
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Loader.h"
 #include "nsIScriptError.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIObserverService.h"
 #include "nsNodeUtils.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIXULWindow.h"
 #include "nsXULPopupManager.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsURILoader.h"
+#include "mozilla/AddonPathService.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/NodeInfoInlines.h"
 #include "mozilla/dom/ProcessingInstruction.h"
 #include "mozilla/dom/XULDocumentBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/Preferences.h"
 #include "nsTextNode.h"
@@ -3283,17 +3284,17 @@ XULDocument::DoneWalking()
             }
         }
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-XULDocument::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
+XULDocument::StyleSheetLoaded(CSSStyleSheet* aSheet,
                               bool aWasAlternate,
                               nsresult aStatus)
 {
     if (!aWasAlternate) {
         // Don't care about when alternate sheets finish loading
 
         NS_ASSERTION(mPendingSheets > 0,
             "Unexpected StyleSheetLoaded notification");
@@ -3686,19 +3687,24 @@ XULDocument::ExecuteScript(nsIScriptCont
         return NS_ERROR_NULL_POINTER;
 
     NS_ENSURE_TRUE(mScriptGlobalObject, NS_ERROR_NOT_INITIALIZED);
 
     // Execute the precompiled script with the given version
     nsAutoMicroTask mt;
     JSContext *cx = aContext->GetNativeContext();
     AutoCxPusher pusher(cx);
-    JS::Rooted<JSObject*> global(cx, mScriptGlobalObject->GetGlobalJSObject());
+    JS::Rooted<JSObject*> baseGlobal(cx, mScriptGlobalObject->GetGlobalJSObject());
+    NS_ENSURE_TRUE(baseGlobal, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(nsContentUtils::GetSecurityManager()->ScriptAllowed(baseGlobal), NS_OK);
+
+    JSAddonId *addonId = MapURIToAddonID(mCurrentPrototype->GetURI());
+    JS::Rooted<JSObject*> global(cx, xpc::GetAddonScope(cx, baseGlobal, addonId));
     NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
-    NS_ENSURE_TRUE(nsContentUtils::GetSecurityManager()->ScriptAllowed(global), NS_OK);
+
     JS::ExposeObjectToActiveJS(global);
     xpc_UnmarkGrayScript(aScriptObject);
     JSAutoCompartment ac(cx, global);
 
     // The script is in the compilation scope. Clone it into the target scope
     // and execute it.
     if (!JS::CloneAndExecuteScript(cx, global, aScriptObject))
         nsJSUtils::ReportPendingException(cx);
@@ -3934,17 +3940,17 @@ XULDocument::AddPrototypeSheets()
 {
     nsresult rv;
 
     const nsCOMArray<nsIURI>& sheets = mCurrentPrototype->GetStyleSheetReferences();
 
     for (int32_t i = 0; i < sheets.Count(); i++) {
         nsCOMPtr<nsIURI> uri = sheets[i];
 
-        nsRefPtr<nsCSSStyleSheet> incompleteSheet;
+        nsRefPtr<CSSStyleSheet> incompleteSheet;
         rv = CSSLoader()->LoadSheet(uri,
                                     mCurrentPrototype->DocumentPrincipal(),
                                     EmptyCString(), this,
                                     getter_AddRefs(incompleteSheet));
 
         // XXXldb We need to prevent bogus sheets from being held in the
         // prototype's list, but until then, don't propagate the failure
         // from LoadSheet (and thus exit the loop).
--- a/content/xul/document/src/XULDocument.h
+++ b/content/xul/document/src/XULDocument.h
@@ -158,17 +158,17 @@ public:
 
     // nsDocument interface overrides
     virtual Element* GetElementById(const nsAString & elementId) MOZ_OVERRIDE;
 
     // nsIDOMXULDocument interface
     NS_DECL_NSIDOMXULDOCUMENT
 
     // nsICSSLoaderObserver
-    NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet,
+    NS_IMETHOD StyleSheetLoaded(CSSStyleSheet* aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus) MOZ_OVERRIDE;
 
     virtual void EndUpdate(nsUpdateType aUpdateType) MOZ_OVERRIDE;
 
     virtual bool IsDocumentRightToLeft() MOZ_OVERRIDE;
 
     virtual void ResetDocumentDirection() MOZ_OVERRIDE;
@@ -331,17 +331,17 @@ protected:
      */
     bool                           mRestrictPersistence;
     nsTHashtable<nsStringHashKey>  mPersistenceIds;
 
     /**
      * An array of style sheets, that will be added (preserving order) to the
      * document after all of them are loaded (in DoneWalking).
      */
-    nsTArray<nsRefPtr<nsCSSStyleSheet> > mOverlaySheets;
+    nsTArray<nsRefPtr<CSSStyleSheet>> mOverlaySheets;
 
     nsCOMPtr<nsIDOMXULCommandDispatcher>     mCommandDispatcher; // [OWNER] of the focus tracker
 
     // Maintains the template builders that have been attached to
     // content elements
     typedef nsInterfaceHashtable<nsISupportsHashKey, nsIXULTemplateBuilder>
         BuilderTable;
     BuilderTable* mTemplateBuilderTable;
--- a/content/xul/document/src/nsXULPrototypeCache.cpp
+++ b/content/xul/document/src/nsXULPrototypeCache.cpp
@@ -2,33 +2,33 @@
 /* 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 "nsXULPrototypeCache.h"
 
 #include "plstr.h"
 #include "nsXULPrototypeDocument.h"
-#include "nsCSSStyleSheet.h"
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
 
 #include "nsIChromeRegistry.h"
 #include "nsIFile.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIObserverService.h"
 #include "nsIStringStream.h"
 #include "nsIStorageStream.h"
 
 #include "nsNetUtil.h"
 #include "nsAppDirectoryServiceDefs.h"
 
 #include "js/TracingAPI.h"
 
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 using namespace mozilla::scache;
 
@@ -167,17 +167,17 @@ nsXULPrototypeCache::PutPrototype(nsXULP
     nsCOMPtr<nsIURI> uri = aDocument->GetURI();
     // Put() releases any old value and addrefs the new one
     mPrototypeTable.Put(uri, aDocument);
 
     return NS_OK;
 }
 
 nsresult
-nsXULPrototypeCache::PutStyleSheet(nsCSSStyleSheet* aStyleSheet)
+nsXULPrototypeCache::PutStyleSheet(CSSStyleSheet* aStyleSheet)
 {
     nsIURI* uri = aStyleSheet->GetSheetURI();
 
     mStyleSheetTable.Put(uri, aStyleSheet);
 
     return NS_OK;
 }
 
@@ -234,17 +234,17 @@ FlushSkinXBL(nsIURI* aKey, nsRefPtr<nsXB
   if (!strncmp(str.get(), "/skin", 5)) {
     ret = PL_DHASH_REMOVE;
   }
 
   return ret;
 }
 
 static PLDHashOperator
-FlushSkinSheets(nsIURI* aKey, nsRefPtr<nsCSSStyleSheet>& aSheet, void* aClosure)
+FlushSkinSheets(nsIURI* aKey, nsRefPtr<CSSStyleSheet>& aSheet, void* aClosure)
 {
   nsAutoCString str;
   aSheet->GetSheetURI()->GetPath(str);
 
   PLDHashOperator ret = PL_DHASH_NEXT;
 
   if (!strncmp(str.get(), "/skin", 5)) {
     // This is a skin binding. Add the key to the list.
--- a/content/xul/document/src/nsXULPrototypeCache.h
+++ b/content/xul/document/src/nsXULPrototypeCache.h
@@ -14,17 +14,19 @@
 #include "nsRefPtrHashtable.h"
 #include "nsURIHashKey.h"
 #include "nsXULPrototypeDocument.h"
 #include "nsIInputStream.h"
 #include "nsIStorageStream.h"
 
 #include "mozilla/scache/StartupCache.h"
 
-class nsCSSStyleSheet;
+namespace mozilla {
+class CSSStyleSheet;
+} // namespace mozilla
 
 /**
  * The XUL prototype cache can be used to store and retrieve shared data for
  * XUL documents, style sheets, XBL, and scripts.
  *
  * The cache has two levels:
  *  1. In-memory hashtables
  *  2. The on-disk cache file.
@@ -67,25 +69,25 @@ public:
         return mXBLDocTable.GetWeak(aURL);
     }
     nsresult PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo);
 
     /**
      * Get a style sheet by URI. If the style sheet is not in the cache,
      * returns nullptr.
      */
-    nsCSSStyleSheet* GetStyleSheet(nsIURI* aURI) {
+    mozilla::CSSStyleSheet* GetStyleSheet(nsIURI* aURI) {
         return mStyleSheetTable.GetWeak(aURI);
     }
 
     /**
      * Store a style sheet in the cache. The key, style sheet's URI is obtained
      * from the style sheet itself.
      */
-    nsresult PutStyleSheet(nsCSSStyleSheet* aStyleSheet);
+    nsresult PutStyleSheet(mozilla::CSSStyleSheet* aStyleSheet);
 
     /**
      * Write the XUL prototype document to a cache file. The proto must be
      * fully loaded.
      */
     nsresult WritePrototype(nsXULPrototypeDocument* aPrototypeDocument);
 
     /**
@@ -116,17 +118,17 @@ protected:
     nsXULPrototypeCache();
     virtual ~nsXULPrototypeCache();
 
     static nsXULPrototypeCache* sInstance;
 
     void FlushSkinFiles();
 
     nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument>   mPrototypeTable; // owns the prototypes
-    nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet>          mStyleSheetTable;
+    nsRefPtrHashtable<nsURIHashKey,mozilla::CSSStyleSheet>   mStyleSheetTable;
     nsJSThingHashtable<nsURIHashKey, JSScript*>              mScriptTable;
     nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo>        mXBLDocTable;
 
     nsTHashtable<nsURIHashKey>                               mCacheURITable;
 
     nsInterfaceHashtable<nsURIHashKey, nsIStorageStream>     mOutputStreamTable;
     nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable;
 
--- a/content/xul/templates/src/nsXMLBinding.cpp
+++ b/content/xul/templates/src/nsXMLBinding.cpp
@@ -1,16 +1,21 @@
 /* -*- 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 "nsXULTemplateQueryProcessorXML.h"
 #include "nsXULTemplateResultXML.h"
 #include "nsXMLBinding.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/XPathResult.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(nsXMLBindingSet)
 NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(nsXMLBindingSet)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLBindingSet)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLBindingSet)
   nsXMLBinding* binding = tmp->mFirst;
@@ -78,66 +83,70 @@ nsXMLBindingSet::LookupTargetIndex(nsIAt
     idx++;
     binding = binding->mNext;
   }
 
   *aBinding = nullptr;
   return -1;
 }
 
-void
+XPathResult*
 nsXMLBindingValues::GetAssignmentFor(nsXULTemplateResultXML* aResult,
                                      nsXMLBinding* aBinding,
                                      int32_t aIndex,
-                                     uint16_t aType,
-                                     nsIDOMXPathResult** aValue)
+                                     uint16_t aType)
 {
-  *aValue = mValues.SafeObjectAt(aIndex);
-
-  if (!*aValue) {
-    nsCOMPtr<nsIDOMNode> contextNode;
-    aResult->GetNode(getter_AddRefs(contextNode));
-    if (contextNode) {
-      nsCOMPtr<nsISupports> resultsupports;
-      aBinding->mExpr->Evaluate(contextNode, aType,
-                                nullptr, getter_AddRefs(resultsupports));
-
-      nsCOMPtr<nsIDOMXPathResult> result = do_QueryInterface(resultsupports);
-      if (result && mValues.ReplaceObjectAt(result, aIndex))
-        *aValue = result;
-    }
+  XPathResult* value = mValues.SafeElementAt(aIndex);
+  if (value) {
+    return value;
   }
 
-  NS_IF_ADDREF(*aValue);
+  nsCOMPtr<nsIDOMNode> contextNode;
+  aResult->GetNode(getter_AddRefs(contextNode));
+  if (!contextNode) {
+    return nullptr;
+  }
+
+  mValues.EnsureLengthAtLeast(aIndex + 1);
+
+  nsCOMPtr<nsISupports> resultsupports;
+  aBinding->mExpr->Evaluate(contextNode, aType,
+                            nullptr, getter_AddRefs(resultsupports));
+
+  mValues.ReplaceElementAt(aIndex, XPathResult::FromSupports(resultsupports));
+
+  return mValues[aIndex];
 }
 
 void
 nsXMLBindingValues::GetNodeAssignmentFor(nsXULTemplateResultXML* aResult,
                                          nsXMLBinding* aBinding,
                                          int32_t aIndex,
                                          nsIDOMNode** aNode)
 {
-  nsCOMPtr<nsIDOMXPathResult> result;
-  GetAssignmentFor(aResult, aBinding, aIndex,
-                   nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
-                   getter_AddRefs(result));
+  XPathResult* result = GetAssignmentFor(aResult, aBinding, aIndex,
+                                         XPathResult::FIRST_ORDERED_NODE_TYPE);
 
-  if (result)
-    result->GetSingleNodeValue(aNode);
-  else
+  nsINode* node;
+  ErrorResult rv;
+  if (result && (node = result->GetSingleNodeValue(rv))) {
+    CallQueryInterface(node, aNode);
+  } else {
     *aNode = nullptr;
+  }
 }
 
 void
 nsXMLBindingValues::GetStringAssignmentFor(nsXULTemplateResultXML* aResult,
                                            nsXMLBinding* aBinding,
                                            int32_t aIndex,
                                            nsAString& aValue)
 {
-  nsCOMPtr<nsIDOMXPathResult> result;
-  GetAssignmentFor(aResult, aBinding, aIndex,
-                   nsIDOMXPathResult::STRING_TYPE, getter_AddRefs(result));
+  XPathResult* result = GetAssignmentFor(aResult, aBinding, aIndex,
+                                         XPathResult::STRING_TYPE);
 
-  if (result)
-    result->GetStringValue(aValue);
-  else
+  if (result) {
+    ErrorResult rv;
+    result->GetStringValue(aValue, rv);
+  } else {
     aValue.Truncate();
+  }
 }
--- a/content/xul/templates/src/nsXMLBinding.h
+++ b/content/xul/templates/src/nsXMLBinding.h
@@ -8,16 +8,21 @@
 
 #include "nsAutoPtr.h"
 #include "nsIAtom.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 
 class nsXULTemplateResultXML;
 class nsXMLBindingValues;
+namespace mozilla {
+namespace dom {
+class XPathResult;
+}
+}
 
 /**
  * Classes related to storing bindings for XML handling.
  */
 
 /**
  * a <binding> description
  */
@@ -87,17 +92,17 @@ protected:
   // the binding set
   nsRefPtr<nsXMLBindingSet> mBindings;
 
   /**
    * A set of values for variable bindings. To look up a binding value,
    * scan through the binding set in mBindings for the right target atom.
    * Its index will correspond to the index in this array.
    */
-  nsCOMArray<nsIDOMXPathResult> mValues;
+  nsTArray<nsRefPtr<mozilla::dom::XPathResult> > mValues;
 
 public:
 
   nsXMLBindingValues() { MOZ_COUNT_CTOR(nsXMLBindingValues); }
   ~nsXMLBindingValues() { MOZ_COUNT_DTOR(nsXMLBindingValues); }
 
   nsXMLBindingSet* GetBindingSet() { return mBindings; }
 
@@ -112,24 +117,22 @@ public:
 
   /**
    * Retrieve the assignment for a particular variable
    *
    * aResult the result generated from the template
    * aBinding the binding looked up using LookupTargetIndex
    * aIndex the index of the assignment to retrieve
    * aType the type of result expected
-   * aValue the value of the assignment
    */
-  void
+  mozilla::dom::XPathResult*
   GetAssignmentFor(nsXULTemplateResultXML* aResult,
                    nsXMLBinding* aBinding,
                    int32_t idx,
-                   uint16_t type,
-                   nsIDOMXPathResult** aValue);
+                   uint16_t type);
 
   void
   GetNodeAssignmentFor(nsXULTemplateResultXML* aResult,
                        nsXMLBinding* aBinding,
                        int32_t idx,
                        nsIDOMNode** aValue);
 
   void
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -21,47 +21,48 @@
 #include "nsPIDOMWindow.h"
 #include "nsXULContentUtils.h"
 #include "nsXMLHttpRequest.h"
 
 #include "nsXULTemplateQueryProcessorXML.h"
 #include "nsXULTemplateResultXML.h"
 #include "nsXULSortService.h"
 
+using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_ISUPPORTS(nsXMLQuery, nsXMLQuery)
 
 //----------------------------------------------------------------------
 //
 // nsXULTemplateResultSetXML
 //
 
 NS_IMPL_ISUPPORTS(nsXULTemplateResultSetXML, nsISimpleEnumerator)
 
 NS_IMETHODIMP
 nsXULTemplateResultSetXML::HasMoreElements(bool *aResult)
 {
     // if GetSnapshotLength failed, then the return type was not a set of
     // nodes, so just return false in this case.
-    uint32_t length;
-    if (NS_SUCCEEDED(mResults->GetSnapshotLength(&length)))
-        *aResult = (mPosition < length);
-    else
-        *aResult = false;
-
+    ErrorResult rv;
+    uint32_t length = mResults->GetSnapshotLength(rv);
+    *aResult = !rv.Failed() && mPosition < length;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
 {
-    nsCOMPtr<nsIDOMNode> node;
-    nsresult rv = mResults->SnapshotItem(mPosition, getter_AddRefs(node));
-    NS_ENSURE_SUCCESS(rv, rv);
+    ErrorResult rv;
+    nsCOMPtr<nsIDOMNode> node =
+        do_QueryInterface(mResults->SnapshotItem(mPosition, rv));
+    if (rv.Failed()) {
+        return rv.ErrorCode();
+    }
 
     nsXULTemplateResultXML* result =
         new nsXULTemplateResultXML(mQuery, node, mBindingSet);
     NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
 
     ++mPosition;
     *aResult = result;
     NS_ADDREF(result);
@@ -326,23 +327,21 @@ nsXULTemplateQueryProcessorXML::Generate
         context = mRoot;
 
     nsIDOMXPathExpression* expr = xmlquery->GetResultsExpression();
     if (!expr)
         return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsISupports> exprsupportsresults;
     nsresult rv = expr->Evaluate(context,
-                                 nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
+                                 XPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
                                  nullptr, getter_AddRefs(exprsupportsresults));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIDOMXPathResult> exprresults =
-        do_QueryInterface(exprsupportsresults);
-
+    XPathResult* exprresults = XPathResult::FromSupports(exprsupportsresults);
     nsXULTemplateResultSetXML* results =
         new nsXULTemplateResultSetXML(xmlquery, exprresults,
                                       xmlquery->GetBindingSet());
     NS_ENSURE_TRUE(results, NS_ERROR_OUT_OF_MEMORY);
 
     *aResults = results;
     NS_ADDREF(*aResults);
 
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h
@@ -12,21 +12,21 @@
 #include "nsISimpleEnumerator.h"
 #include "nsString.h"
 #include "nsCOMArray.h"
 #include "nsRefPtrHashtable.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMXPathExpression.h"
 #include "nsIDOMXPathEvaluator.h"
-#include "nsIDOMXPathResult.h"
 #include "nsXMLBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIXMLHttpRequest.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/XPathResult.h"
 
 class nsXULTemplateQueryProcessorXML;
 
 #define NS_IXMLQUERY_IID \
   {0x0358d692, 0xccce, 0x4a97, \
     { 0xb2, 0x51, 0xba, 0x8f, 0x17, 0x0f, 0x3b, 0x6f }}
  
 class nsXMLQuery MOZ_FINAL : public nsISupports
@@ -86,31 +86,31 @@ private:
 
     // reference back to the query
     nsCOMPtr<nsXMLQuery> mQuery;
 
     // the binding set created from <assign> nodes
     nsRefPtr<nsXMLBindingSet> mBindingSet;
 
     // set of results contained in this enumerator
-    nsCOMPtr<nsIDOMXPathResult> mResults;
+    nsRefPtr<mozilla::dom::XPathResult> mResults;
 
     // current position within the list of results
     uint32_t mPosition;
 
 public:
 
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
     // nsISimpleEnumerator interface
     NS_DECL_NSISIMPLEENUMERATOR
 
     nsXULTemplateResultSetXML(nsXMLQuery* aQuery,
-                              nsIDOMXPathResult* aResults,
+                              mozilla::dom::XPathResult* aResults,
                               nsXMLBindingSet* aBindingSet)
         : mQuery(aQuery),
           mBindingSet(aBindingSet),
           mResults(aResults),
           mPosition(0)
     {}
 };
 
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -947,17 +947,17 @@ this.DOMApplicationRegistry = {
           // If we can't load the manifest, we probably have a corrupted
           // registry. We delete the app since we can't do anything with it.
           delete this.webapps[aResult.id];
           return;
         }
 
         let localeManifest = new ManifestHelper(manifest, app.origin);
 
-        app.name = localeManifest.name;
+        app.name = manifest.name;
         app.csp = manifest.csp || "";
         app.role = localeManifest.role;
         if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
           app.redirects = this.sanitizeRedirects(manifest.redirects);
         }
         this._registerSystemMessages(manifest, app);
         this._registerInterAppConnections(manifest, app);
         appsToRegister.push({ manifest: manifest, app: app });
@@ -1966,17 +1966,17 @@ this.DOMApplicationRegistry = {
           origin: aApp.origin,
           manifestURL: aData.manifestURL
         }, true);
       }
 
       this.updateDataStore(this.webapps[aId].localId, aApp.origin,
                            aApp.manifestURL, aApp.manifest);
 
-      aApp.name = manifest.name;
+      aApp.name = aNewManifest.name;
       aApp.csp = manifest.csp || "";
       aApp.role = manifest.role || "";
       aApp.updateTime = Date.now();
     } else {
       manifest = new ManifestHelper(aOldManifest, aApp.origin);
     }
 
     // Update the registry.
@@ -2331,45 +2331,45 @@ this.DOMApplicationRegistry = {
 
     app.id = aId;
     app.installTime = Date.now();
     app.lastUpdateCheck = Date.now();
 
     return app;
   },
 
-  _cloneApp: function(aData, aNewApp, aManifest, aId, aLocalId) {
+  _cloneApp: function(aData, aNewApp, aLocaleManifest, aManifest, aId, aLocalId) {
     let appObject = AppsUtils.cloneAppObject(aNewApp);
     appObject.appStatus =
       aNewApp.appStatus || Ci.nsIPrincipal.APP_STATUS_INSTALLED;
 
-    if (aManifest.appcache_path) {
+    if (aLocaleManifest.appcache_path) {
       appObject.installState = "pending";
       appObject.downloadAvailable = true;
       appObject.downloading = true;
       appObject.downloadSize = 0;
       appObject.readyToApplyDownload = false;
-    } else if (aManifest.package_path) {
+    } else if (aLocaleManifest.package_path) {
       appObject.installState = "pending";
       appObject.downloadAvailable = true;
       appObject.downloading = true;
-      appObject.downloadSize = aManifest.size;
+      appObject.downloadSize = aLocaleManifest.size;
       appObject.readyToApplyDownload = false;
     } else {
       appObject.installState = "installed";
       appObject.downloadAvailable = false;
       appObject.downloading = false;
       appObject.readyToApplyDownload = false;
     }
 
     appObject.localId = aLocalId;
     appObject.basePath = OS.Path.dirname(this.appsFile);
     appObject.name = aManifest.name;
-    appObject.csp = aManifest.csp || "";
-    appObject.role = aManifest.role || "";
+    appObject.csp = aLocaleManifest.csp || "";
+    appObject.role = aLocaleManifest.role;
     appObject.installerAppId = aData.appId;
     appObject.installerIsBrowser = aData.isBrowser;
 
     return appObject;
   },
 
   _writeManifestFile: function(aId, aIsPackage, aJsonManifest) {
     debug("_writeManifestFile");
@@ -2477,17 +2477,17 @@ this.DOMApplicationRegistry = {
     let app = this._setupApp(aData, id);
 
     let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
     yield this._writeManifestFile(id, aData.isPackage, jsonManifest);
 
     debug("app.origin: " + app.origin);
     let manifest = new ManifestHelper(jsonManifest, app.origin);
 
-    let appObject = this._cloneApp(aData, app, manifest, id, localId);
+    let appObject = this._cloneApp(aData, app, manifest, jsonManifest, id, localId);
 
     this.webapps[id] = appObject;
 
     // For package apps, the permissions are not in the mini-manifest, so
     // don't update the permissions yet.
     if (!aData.isPackage) {
       if (supportUseCurrentProfile()) {
         PermissionsInstaller.installPermissions(
--- a/dom/archivereader/ArchiveRequest.cpp
+++ b/dom/archivereader/ArchiveRequest.cpp
@@ -126,29 +126,22 @@ ArchiveRequest::ReaderReady(nsTArray<nsC
 {
   if (NS_FAILED(aStatus)) {
     FireError(aStatus);
     return NS_OK;
   }
 
   nsresult rv;
 
-  nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(GetOwner());
-  if (NS_WARN_IF(!globalObject)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) {
     return NS_ERROR_UNEXPECTED;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
 
-  JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
-  NS_ASSERTION(global, "Failed to get global object!");
-
-  JSAutoCompartment ac(cx, global);
-
   JS::Rooted<JS::Value> result(cx);
   switch (mOperation) {
     case GetFilenames:
       rv = GetFilenamesResult(cx, result.address(), aFileList);
       break;
 
     case GetFile:
       rv = GetFileResult(cx, &result, aFileList);
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -319,27 +319,28 @@ private:
   RunConsole() MOZ_OVERRIDE
   {
     // Walk up to our containing page
     WorkerPrivate* wp = mWorkerPrivate;
     while (wp->GetParent()) {
       wp = wp->GetParent();
     }
 
-    AutoJSAPI jsapi;
-    JSContext* cx = jsapi.cx();
-    ClearException ce(cx);
-
     nsPIDOMWindow* window = wp->GetWindow();
     NS_ENSURE_TRUE_VOID(window);
 
     nsRefPtr<nsGlobalWindow> win = static_cast<nsGlobalWindow*>(window);
     NS_ENSURE_TRUE_VOID(win);
 
-    JSAutoCompartment ac(cx, win->GetWrapperPreserveColor());
+    AutoJSAPI jsapi;
+    if (NS_WARN_IF(!jsapi.Init(win))) {
+      return;
+    }
+    JSContext* cx = jsapi.cx();
+    ClearException ce(cx);
 
     ErrorResult error;
     nsRefPtr<Console> console = win->GetConsole(error);
     if (error.Failed()) {
       NS_WARNING("Failed to get console from the window.");
       return;
     }
 
@@ -431,27 +432,28 @@ private:
   RunConsole() MOZ_OVERRIDE
   {
     // Walk up to our containing page
     WorkerPrivate* wp = mWorkerPrivate;
     while (wp->GetParent()) {
       wp = wp->GetParent();
     }
 
-    AutoJSAPI jsapi;
-    JSContext* cx = jsapi.cx();
-    ClearException ce(cx);
-
     nsPIDOMWindow* window = wp->GetWindow();
     NS_ENSURE_TRUE_VOID(window);
 
     nsRefPtr<nsGlobalWindow> win = static_cast<nsGlobalWindow*>(window);
     NS_ENSURE_TRUE_VOID(win);
 
-    JSAutoCompartment ac(cx, win->GetWrapperPreserveColor());
+    AutoJSAPI jsapi;
+    if (NS_WARN_IF(!jsapi.Init(win))) {
+      return;
+    }
+    JSContext* cx = jsapi.cx();
+    ClearException ce(cx);
 
     ErrorResult error;
     nsRefPtr<Console> console = win->GetConsole(error);
     if (error.Failed()) {
       NS_WARNING("Failed to get console from the window.");
       return;
     }
 
--- a/dom/base/MessagePort.cpp
+++ b/dom/base/MessagePort.cpp
@@ -267,24 +267,21 @@ PopulateMessagePortList(MessagePortBase*
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
 PostMessageRunnable::Run()
 {
   MOZ_ASSERT(mPort);
 
-  nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(mPort->GetOwner());
-  if (NS_WARN_IF(!globalObject)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.Init(mPort->GetParentObject()))) {
     return NS_ERROR_UNEXPECTED;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject());
 
   // Deserialize the structured clone data
   JS::Rooted<JS::Value> messageData(cx);
   StructuredCloneInfo scInfo;
   scInfo.mEvent = this;
   scInfo.mPort = mPort;
 
   if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) {
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -9,16 +9,18 @@
 #include "mozilla/Assertions.h"
 
 #include "jsapi.h"
 #include "xpcpublic.h"
 #include "nsIGlobalObject.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsContentUtils.h"
+#include "nsGlobalWindow.h"
+#include "nsPIDOMWindow.h"
 #include "nsTArray.h"
 #include "nsJSUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 static mozilla::ThreadLocal<ScriptSettingsStackEntry*> sScriptSettingsTLS;
 
@@ -216,57 +218,110 @@ FindJSContext(nsIGlobalObject* aGlobalOb
   }
   if (!cx) {
     cx = nsContentUtils::GetSafeJSContext();
   }
   return cx;
 }
 
 AutoJSAPI::AutoJSAPI()
-  : mCx(nsContentUtils::GetDefaultJSContextForThread())
+  : mCx(nullptr)
 {
-  if (NS_IsMainThread()) {
-    mCxPusher.construct(mCx);
-  }
-
-  // Leave the cx in a null compartment.
-  mNullAc.construct(mCx);
 }
 
-AutoJSAPI::AutoJSAPI(JSContext *aCx, bool aIsMainThread, bool aSkipNullAc)
-  : mCx(aCx)
+void
+AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
 {
-  MOZ_ASSERT_IF(aIsMainThread, NS_IsMainThread());
+  mCx = aCx;
   if (aIsMainThread) {
     mCxPusher.construct(mCx);
   }
 
-  // In general we want to leave the cx in a null compartment, but we let
-  // subclasses skip this if they plan to immediately enter a compartment.
-  if (!aSkipNullAc) {
-    mNullAc.construct(mCx);
-  }
+  mAutoNullableCompartment.construct(mCx, aGlobal);
+}
+
+AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject,
+                     bool aIsMainThread,
+                     JSContext* aCx)
+{
+  MOZ_ASSERT(aGlobalObject);
+  MOZ_ASSERT(aGlobalObject->GetGlobalJSObject(), "Must have a JS global");
+  MOZ_ASSERT(aCx);
+  MOZ_ASSERT_IF(aIsMainThread, NS_IsMainThread());
+
+  InitInternal(aGlobalObject->GetGlobalJSObject(), aCx, aIsMainThread);
+}
+
+void
+AutoJSAPI::Init()
+{
+  MOZ_ASSERT(!mCx, "An AutoJSAPI should only be initialised once");
+
+  InitInternal(/* aGlobal */ nullptr,
+               nsContentUtils::GetDefaultJSContextForThread(),
+               NS_IsMainThread());
 }
 
-AutoJSAPIWithErrorsReportedToWindow::AutoJSAPIWithErrorsReportedToWindow(nsIScriptContext* aScx)
-  : AutoJSAPI(aScx->GetNativeContext(), /* aIsMainThread = */ true)
+bool
+AutoJSAPI::Init(nsIGlobalObject* aGlobalObject, JSContext* aCx)
 {
+  MOZ_ASSERT(!mCx, "An AutoJSAPI should only be initialised once");
+  MOZ_ASSERT(aCx);
+
+  if (NS_WARN_IF(!aGlobalObject)) {
+    return false;
+  }
+
+  JSObject* global = aGlobalObject->GetGlobalJSObject();
+  if (NS_WARN_IF(!global)) {
+    return false;
+  }
+
+  InitInternal(global, aCx, NS_IsMainThread());
+  return true;
+}
+
+bool
+AutoJSAPI::Init(nsIGlobalObject* aGlobalObject)
+{
+  return Init(aGlobalObject, nsContentUtils::GetDefaultJSContextForThread());
 }
 
-AutoJSAPIWithErrorsReportedToWindow::AutoJSAPIWithErrorsReportedToWindow(nsIGlobalObject* aGlobalObject)
-  : AutoJSAPI(FindJSContext(aGlobalObject), /* aIsMainThread = */ true)
+bool
+AutoJSAPI::InitWithLegacyErrorReporting(nsIGlobalObject* aGlobalObject)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  return Init(aGlobalObject, FindJSContext(aGlobalObject));
+}
+
+bool
+AutoJSAPI::InitUsingWin(nsPIDOMWindow* aWindow, JSContext* aCx)
 {
+  return Init(static_cast<nsGlobalWindow*>(aWindow), aCx);
+}
+
+bool
+AutoJSAPI::InitUsingWin(nsPIDOMWindow* aWindow)
+{
+  return Init(static_cast<nsGlobalWindow*>(aWindow));
+}
+
+bool
+AutoJSAPI::InitWithLegacyErrorReportingUsingWin(nsPIDOMWindow* aWindow)
+{
+  return InitWithLegacyErrorReporting(static_cast<nsGlobalWindow*>(aWindow));
 }
 
 AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
                                  bool aIsMainThread,
                                  JSContext* aCx)
-  : AutoJSAPI(aCx ? aCx : FindJSContext(aGlobalObject), aIsMainThread, /* aSkipNullAc = */ true)
+  : AutoJSAPI(aGlobalObject, aIsMainThread,
+              aCx ? aCx : FindJSContext(aGlobalObject))
   , ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
-  , mAc(cx(), aGlobalObject->GetGlobalJSObject())
   , mWebIDLCallerPrincipal(nullptr)
 {
   MOZ_ASSERT(aGlobalObject);
   MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread.
   MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject));
 }
 
 AutoIncumbentScript::AutoIncumbentScript(nsIGlobalObject* aGlobalObject)
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -11,17 +11,17 @@
 
 #include "nsCxPusher.h"
 #include "MainThreadUtils.h"
 #include "nsIGlobalObject.h"
 #include "nsIPrincipal.h"
 
 #include "mozilla/Maybe.h"
 
-class nsIGlobalObject;
+class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 /*
  * System-wide setup/teardown routines. Init and Destroy should be invoked
  * once each, at startup and shutdown (respectively).
  */
@@ -87,22 +87,24 @@ private:
   ScriptSettingsStackEntry *mOlder;
 };
 
 /*
  * For any interaction with JSAPI, an AutoJSAPI (or one of its subclasses)
  * must be on the stack.
  *
  * This base class should be instantiated as-is when the caller wants to use
- * JSAPI but doesn't expect to run script. Its current duties are as-follows:
+ * JSAPI but doesn't expect to run script. The caller must then call one of its
+ * Init functions before being able to access the JSContext through cx().
+ * Its current duties are as-follows (see individual Init comments for details):
  *
  * * Grabbing an appropriate JSContext, and, on the main thread, pushing it onto
  *   the JSContext stack.
- * * Entering a null compartment, so that the consumer is forced to select a
- *   compartment to enter before manipulating objects.
+ * * Entering an initial (possibly null) compartment, to ensure that the
+ *   previously entered compartment for that JSContext is not used by mistake.
  *
  * Additionally, the following duties are planned, but not yet implemented:
  *
  * * De-poisoning the JSRuntime to allow manipulation of JSAPI. We can't
  *   actually implement this poisoning until all the JSContext pushing in the
  *   system goes through AutoJSAPI (see bug 951991). For now, this de-poisoning
  *   effectively corresponds to having a non-null cx on the stack.
  * * Reporting any exceptions left on the JSRuntime, unless the caller steals
@@ -116,47 +118,74 @@ private:
  * should be used, which does additional manipulation of the script settings
  * stack. In bug 991758, we'll add hard invariants to SpiderMonkey, such that
  * any attempt to run script without an AutoEntryScript on the stack will
  * fail. This prevents system code from accidentally triggering script
  * execution at inopportune moments via surreptitious getters and proxies.
  */
 class AutoJSAPI {
 public:
-  // Public constructor for use when the base class is constructed as-is. It
-  // uses the SafeJSContext (or worker equivalent), and enters a null
-  // compartment.
+  // Trivial constructor. One of the Init functions must be called before
+  // accessing the JSContext through cx().
   AutoJSAPI();
-  JSContext* cx() const { return mCx; }
+
+  // This uses the SafeJSContext (or worker equivalent), and enters a null
+  // compartment, so that the consumer is forced to select a compartment to
+  // enter before manipulating objects.
+  void Init();
+
+  // This uses the SafeJSContext (or worker equivalent), and enters the
+  // compartment of aGlobalObject.
+  // If aGlobalObject or its associated JS global are null then it returns
+  // false and use of cx() will cause an assertion.
+  bool Init(nsIGlobalObject* aGlobalObject);
+
+  // Unsurprisingly, this uses aCx and enters the compartment of aGlobalObject.
+  // If aGlobalObject or its associated JS global are null then it returns
+  // false and use of cx() will cause an assertion.
+  // If aCx is null it will cause an assertion.
+  bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx);
+
+  // This may only be used on the main thread.
+  // This attempts to use the JSContext associated with aGlobalObject, otherwise
+  // it uses the SafeJSContext. It then enters the compartment of aGlobalObject.
+  // This means that existing error reporting mechanisms that use the JSContext
+  // to find the JSErrorReporter should still work as before.
+  // We should be able to remove this around bug 981198.
+  // If aGlobalObject or its associated JS global are null then it returns
+  // false and use of cx() will cause an assertion.
+  bool InitWithLegacyErrorReporting(nsIGlobalObject* aGlobalObject);
+
+  // Convenience functions to take an nsPIDOMWindow*, when it is more easily
+  // available than an nsIGlobalObject.
+  bool InitUsingWin(nsPIDOMWindow* aWindow);
+  bool InitUsingWin(nsPIDOMWindow* aWindow, JSContext* aCx);
+  bool InitWithLegacyErrorReportingUsingWin(nsPIDOMWindow* aWindow);
+
+  JSContext* cx() const {
+    MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
+    return mCx;
+  }
 
   bool CxPusherIsStackTop() { return mCxPusher.ref().IsStackTop(); }
 
 protected:
   // Protected constructor, allowing subclasses to specify a particular cx to
-  // be used.
-  AutoJSAPI(JSContext *aCx, bool aIsMainThread, bool aSkipNullAC = false);
+  // be used. This constructor initialises the AutoJSAPI, so Init must NOT be
+  // called on subclasses that use this.
+  // If aGlobalObject, its associated JS global or aCx are null this will cause
+  // an assertion, as will setting aIsMainThread incorrectly.
+  AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx);
 
 private:
   mozilla::Maybe<AutoCxPusher> mCxPusher;
-  mozilla::Maybe<JSAutoNullCompartment> mNullAc;
+  mozilla::Maybe<JSAutoNullableCompartment> mAutoNullableCompartment;
   JSContext *mCx;
-};
 
-// Note - the ideal way to implement this is with an accessor on AutoJSAPI
-// that lets us select the error reporting target. But at present,
-// implementing it that way would require us to destroy and reconstruct
-// mCxPusher, which is pretty wasteful. So we do this for now, since it should
-// be pretty easy to switch things over later.
-//
-// This should only be used on the main thread.
-class AutoJSAPIWithErrorsReportedToWindow : public AutoJSAPI {
-  public:
-    AutoJSAPIWithErrorsReportedToWindow(nsIScriptContext* aScx);
-    // Equivalent to AutoJSAPI if aGlobal is not a Window.
-    AutoJSAPIWithErrorsReportedToWindow(nsIGlobalObject* aGlobalObject);
+  void InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread);
 };
 
 /*
  * A class that represents a new script entry point.
  */
 class AutoEntryScript : public AutoJSAPI,
                         protected ScriptSettingsStackEntry {
 public:
@@ -165,17 +194,16 @@ public:
                   // Note: aCx is mandatory off-main-thread.
                   JSContext* aCx = nullptr);
 
   void SetWebIDLCallerPrincipal(nsIPrincipal *aPrincipal) {
     mWebIDLCallerPrincipal = aPrincipal;
   }
 
 private:
-  JSAutoCompartment mAc;
   // It's safe to make this a weak pointer, since it's the subject principal
   // when we go on the stack, so can't go away until after we're gone.  In
   // particular, this is only used from the CallSetup constructor, and only in
   // the aIsJSImplementedWebIDL case.  And in that case, the subject principal
   // is the principal of the callee function that is part of the CallArgs just a
   // bit up the stack, and which will outlive us.  So we know the principal
   // can't go away until then either.
   nsIPrincipal* mWebIDLCallerPrincipal;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -109,17 +109,16 @@
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsITreeColumns.h"
 #endif
 #include "nsIDOMXPathExpression.h"
 #include "nsIDOMNSXPathExpression.h"
 #include "nsIDOMXPathNSResolver.h"
-#include "nsIDOMXPathResult.h"
 
 // Storage includes
 #include "nsIDOMStorage.h"
 #include "nsPIDOMStorage.h"
 
 // Drag and drop
 #include "nsIDOMFile.h"
 #include "nsDOMBlobBuilder.h" // nsDOMMultipartFile
@@ -345,18 +344,16 @@ static nsDOMClassInfoData sClassInfoData
 
   NS_DEFINE_CLASSINFO_DATA(XSLTProcessor, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(XPathExpression, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(XPathNSResolver, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(XPathResult, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // WhatWG Storage
 
   // mrbkap says we don't need WANT_ADDPROPERTY on Storage objects
   // since a call to addProperty() is always followed by a call to
   // setProperty(), except in the case when a getter or setter is set
   // for a property. But we don't care about getters or setters here.
   NS_DEFINE_CLASSINFO_DATA(Storage, nsStorage2SH,
@@ -953,20 +950,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathExpression)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSXPathExpression)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(XPathNSResolver, nsIDOMXPathNSResolver)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathNSResolver)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(XPathResult, nsIDOMXPathResult)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathResult)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(Storage, nsIDOMStorage)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorage)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -43,17 +43,16 @@ DOMCI_CLASS(CSSMozDocumentRule)
 DOMCI_CLASS(CSSSupportsRule)
 
 // XSLTProcessor
 DOMCI_CLASS(XSLTProcessor)
 
 // DOM Level 3 XPath objects
 DOMCI_CLASS(XPathExpression)
 DOMCI_CLASS(XPathNSResolver)
-DOMCI_CLASS(XPathResult)
 
 // WhatWG WebApps Objects
 DOMCI_CLASS(Storage)
 
 DOMCI_CLASS(Blob)
 DOMCI_CLASS(File)
 
 // DOM modal content window class, almost identical to Window
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2354,16 +2354,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   // clear smartcard events, our document has gone away.
   if (mCrypto && XRE_GetProcessType() != GeckoProcessType_Content) {
     nsresult rv = mCrypto->SetEnableSmartCardEvents(false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 #endif
 
   AutoJSAPI jsapi;
+  jsapi.Init();
   JSContext *cx = jsapi.cx();
 
   if (!mDoc) {
     // First document load.
 
     // Get our private root. If it is equal to us, then we need to
     // attach our global key bindings that handles browser scrolling
     // and other browser commands.
@@ -8000,16 +8001,17 @@ NS_IMETHODIMP
 PostMessageEvent::Run()
 {
   NS_ABORT_IF_FALSE(mTargetWindow->IsOuterWindow(),
                     "should have been passed an outer window!");
   NS_ABORT_IF_FALSE(!mSource || mSource->IsOuterWindow(),
                     "should have been passed an outer window!");
 
   AutoJSAPI jsapi;
+  jsapi.Init();
   JSContext* cx = jsapi.cx();
 
   // If we bailed before this point we're going to leak mMessage, but
   // that's probably better than crashing.
 
   nsRefPtr<nsGlobalWindow> targetWindow;
   if (mTargetWindow->IsClosedOrClosing() ||
       !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1590,16 +1590,17 @@ static const JSFunctionSpec JProfFunctio
 
 #endif /* defined(MOZ_JPROF) */
 
 nsresult
 nsJSContext::InitClasses(JS::Handle<JSObject*> aGlobalObj)
 {
   JSOptionChangedCallback(js_options_dot_str, this);
   AutoJSAPI jsapi;
+  jsapi.Init();
   JSContext* cx = jsapi.cx();
   JSAutoCompartment ac(cx, aGlobalObj);
 
   // Attempt to initialize profiling functions
   ::JS_DefineProfilingFunctions(cx, aGlobalObj);
 
 #ifdef NS_TRACE_MALLOC
   if (nsContentUtils::IsCallerChrome()) {
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -258,17 +258,17 @@ DOMInterfaces = {
     'resultNotAddRefed': ['getRGBColorValue', 'getRectValue']
 },
 
 'CSSStyleDeclaration': {
     'nativeType': 'nsICSSDeclaration'
 },
 
 'CSSStyleSheet': {
-    'nativeType': 'nsCSSStyleSheet',
+    'nativeType': 'mozilla::CSSStyleSheet',
     'binaryNames': { 'ownerRule': 'DOMOwnerRule' },
 },
 
 'CSSValue': {
     'concrete': False
 },
 
 'CSSValueList': {
@@ -1061,17 +1061,17 @@ DOMInterfaces = {
     'workers': True,
 },
 
 'SourceBufferList': {
     'resultNotAddRefed': [ '__indexedGetter' ],
 },
 
 'StyleSheet': {
-    'nativeType': 'nsCSSStyleSheet',
+    'nativeType': 'mozilla::CSSStyleSheet',
 },
 
 'SVGAnimatedLengthList': {
     'nativeType': 'mozilla::DOMSVGAnimatedLengthList',
     'headerFile': 'DOMSVGAnimatedLengthList.h',
 },
 
 'SVGAnimatedNumberList': {
@@ -1654,16 +1654,20 @@ DOMInterfaces = {
 'XMLStylesheetProcessingInstruction': {
     'resultNotAddRefed': [ 'sheet' ]
 },
 
 'XPathEvaluator': {
     'wrapperCache': False
 },
 
+'XPathResult': {
+    'resultNotAddRefed': ['singleNodeValue', 'iterateNext', 'snapshotItem']
+},
+
 'XULDocument': {
     'headerFile': 'XULDocument.h'
 },
 
 'XULElement': {
     'nativeType': 'nsXULElement',
     'resultNotAddRefed': [ 'controllers', 'style' ]
 },
@@ -1991,12 +1995,11 @@ addExternalIface('OutputStream', nativeT
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
 addExternalIface('StackFrame', nativeType='nsIStackFrame',
                  headerFile='nsIException.h', notflattened=True)
 addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
                  notflattened=True)
 addExternalIface('UserDataHandler')
-addExternalIface('XPathResult', nativeType='nsISupports')
 addExternalIface('XPathExpression')
 addExternalIface('XPathNSResolver')
 addExternalIface('XULCommandDispatcher')
--- a/dom/browser-element/BrowserElementParent.jsm
+++ b/dom/browser-element/BrowserElementParent.jsm
@@ -60,20 +60,16 @@ function visibilityChangeHandler(e) {
 }
 
 this.BrowserElementParentBuilder = {
   create: function create(frameLoader, hasRemoteFrame, isPendingFrame) {
     return new BrowserElementParent(frameLoader, hasRemoteFrame);
   }
 }
 
-
-// The active input method iframe.
-let activeInputFrame = null;
-
 function BrowserElementParent(frameLoader, hasRemoteFrame, isPendingFrame) {
   debug("Creating new BrowserElementParent object for " + frameLoader);
   this._domRequestCounter = 0;
   this._pendingDOMRequests = {};
   this._pendingSetInputMethodActive = [];
   this._hasRemoteFrame = hasRemoteFrame;
   this._nextPaintListeners = [];
 
@@ -108,22 +104,17 @@ function BrowserElementParent(frameLoade
       if (self._isAlive()) {
         fn.apply(self, arguments);
       }
     };
   };
 
   let defineDOMRequestMethod = function(domName, msgName) {
     XPCNativeWrapper.unwrap(self._frameElement)[domName] = function() {
-      if (!self._mm) {
-        return self._queueDOMRequest;
-      }
-      if (self._isAlive()) {
-        return self._sendDOMRequest(msgName);
-      }
+      return self._sendDOMRequest(msgName);
     };
   }
 
   // Define methods on the frame element.
   defineNoReturnMethod('setVisible', this._setVisible);
   defineDOMRequestMethod('getVisible', 'get-visible');
   defineNoReturnMethod('sendMouseEvent', this._sendMouseEvent);
 
@@ -337,23 +328,16 @@ BrowserElementParent.prototype = {
       return false;
     }
     return true;
   },
 
   _recvHello: function() {
     debug("recvHello");
 
-    this._ready = true;
-
-    // Handle pending SetInputMethodActive request.
-    while (this._pendingSetInputMethodActive.length > 0) {
-      this._setInputMethodActive(this._pendingSetInputMethodActive.shift());
-    }
-
     // Inform our child if our owner element's document is invisible.  Note
     // that we must do so here, rather than in the BrowserElementParent
     // constructor, because the BrowserElementChild may not be initialized when
     // we run our constructor.
     if (this._window.document.hidden) {
       this._ownerVisibilityChange();
     }
 
@@ -477,60 +461,46 @@ BrowserElementParent.prototype = {
     }
 
     return new this._window.Event('mozbrowser' + evtName,
                                   { bubbles: true,
                                     cancelable: cancelable });
   },
 
   /**
-   * If remote frame haven't been set up, we enqueue a function that get a
-   * DOMRequest until the remote frame is ready and return another DOMRequest
-   * to caller. When we get the real DOMRequest, we will help forward the
-   * success/error callback to the DOMRequest that caller got.
-   */
-  _queueDOMRequest: function(msgName, args) {
-    if (!this._pendingAPICalls) {
-      return;
-    }
-
-    let req = Services.DOMRequest.createRequest(this._window);
-    let self = this;
-    let getRealDOMRequest = function() {
-      let realReq = self._sendDOMRequest(msgName, args);
-      realReq.onsuccess = function(v) {
-        Services.DOMRequest.fireSuccess(req, v);
-      };
-      realReq.onerror = function(v) {
-        Services.DOMRequest.fireError(req, v);
-      };
-    };
-    this._pendingAPICalls.push(getRealDOMRequest);
-    return req;
-  },
-
-  /**
    * Kick off a DOMRequest in the child process.
    *
    * We'll fire an event called |msgName| on the child process, passing along
    * an object with two fields:
    *
    *  - id:  the ID of this request.
    *  - arg: arguments to pass to the child along with this request.
    *
    * We expect the child to pass the ID back to us upon completion of the
    * request.  See _gotDOMRequestResult.
    */
   _sendDOMRequest: function(msgName, args) {
     let id = 'req_' + this._domRequestCounter++;
     let req = Services.DOMRequest.createRequest(this._window);
-    if (this._sendAsyncMsg(msgName, {id: id, args: args})) {
-      this._pendingDOMRequests[id] = req;
+    let self = this;
+    let send = function() {
+      if (!self._isAlive()) {
+        return;
+      }
+      if (self._sendAsyncMsg(msgName, {id: id, args: args})) {
+        self._pendingDOMRequests[id] = req;
+      } else {
+        Services.DOMRequest.fireErrorAsync(req, "fail");
+      }
+    };
+    if (this._mm) {
+      send();
     } else {
-      Services.DOMRequest.fireErrorAsync(req, "fail");
+      // Child haven't been loaded.
+      this._pendingAPICalls.push(send);
     }
     return req;
   },
 
   /**
    * Called when the child process finishes handling a DOMRequest.  data.json
    * must have the fields [id, successRv], if the DOMRequest was successful, or
    * [id, errorMsg], if the request was not successful.
@@ -726,23 +696,16 @@ BrowserElementParent.prototype = {
     let height = parseInt(_height);
     let mimeType = (typeof _mimeType === 'string') ?
       _mimeType.trim().toLowerCase() : 'image/jpeg';
     if (isNaN(width) || isNaN(height) || width < 0 || height < 0) {
       throw Components.Exception("Invalid argument",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
 
-    if (!this._mm) {
-      // Child haven't been loaded.
-      return this._queueDOMRequest('get-screenshot',
-                                   {width: width, height: height,
-                                    mimeType: mimeType});
-    }
-
     return this._sendDOMRequest('get-screenshot',
                                 {width: width, height: height,
                                  mimeType: mimeType});
   },
 
   _recvNextPaint: function(data) {
     let listeners = this._nextPaintListeners;
     this._nextPaintListeners = [];
@@ -795,60 +758,18 @@ BrowserElementParent.prototype = {
   },
 
   _setInputMethodActive: function(isActive) {
     if (typeof isActive !== 'boolean') {
       throw Components.Exception("Invalid argument",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
 
-    // Wait until browserElementChild is initialized.
-    if (!this._ready) {
-      this._pendingSetInputMethodActive.push(isActive);
-      return;
-    }
-
-    let req = Services.DOMRequest.createRequest(this._window);
-
-    // Deactivate the old input method if needed.
-    if (activeInputFrame && isActive) {
-      if (Cu.isDeadWrapper(activeInputFrame)) {
-        // If the activeInputFrame is already a dead object,
-        // we should simply set it to null directly.
-        activeInputFrame = null;
-        this._sendSetInputMethodActiveDOMRequest(req, isActive);
-        return req;
-      }
-
-      let reqOld = XPCNativeWrapper.unwrap(activeInputFrame)
-                                   .setInputMethodActive(false);
-
-      // We wan't to continue regardless whether this req succeeded
-      reqOld.onsuccess = reqOld.onerror = function() {
-        activeInputFrame = null;
-        this._sendSetInputMethodActiveDOMRequest(req, isActive);
-      }.bind(this);
-    } else {
-      this._sendSetInputMethodActiveDOMRequest(req, isActive);
-    }
-    return req;
-  },
-
-  _sendSetInputMethodActiveDOMRequest: function(req, isActive) {
-    let id = 'req_' + this._domRequestCounter++;
-    let data = {
-      id : id,
-      args: { isActive: isActive }
-    };
-    if (this._sendAsyncMsg('set-input-method-active', data)) {
-      activeInputFrame = this._frameElement;
-      this._pendingDOMRequests[id] = req;
-    } else {
-      Services.DOMRequest.fireErrorAsync(req, 'fail');
-    }
+    return this._sendDOMRequest('set-input-method-active',
+                                {isActive: isActive});
   },
 
   _fireKeyEvent: function(data) {
     let evt = this._window.document.createEvent("KeyboardEvent");
     evt.initKeyEvent(data.json.type, true, true, this._window,
                      false, false, false, false, // modifiers
                      data.json.keyCode,
                      data.json.charCode);
--- a/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js
+++ b/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js
@@ -167,16 +167,23 @@ function next(msg) {
       // Do nothing and wait for the input to show up in input frame.
       break;
 
     case 2:
       is(from, 'input', 'Message sequence unexpected (2).');
       is(value, '#0hello',
          'Failed to get correct input from the first iframe.');
 
+      let req0 = gFrames[0].setInputMethodActive(false);
+      req0.onsuccess = function() {
+        ok(true, 'setInputMethodActive succeeded (0).');
+      };
+      req0.onerror = function() {
+        ok(false, 'setInputMethodActive failed (0): ' + this.error.name);
+      };
       let req1 = gFrames[1].setInputMethodActive(true);
       req1.onsuccess = function() {
        ok(true, 'setInputMethodActive succeeded (1).');
       };
       req1.onerror = function() {
        ok(false, 'setInputMethodActive failed (1): ' + this.error.name);
       };
       break;
--- a/dom/camera/CameraPreferences.cpp
+++ b/dom/camera/CameraPreferences.cpp
@@ -1,15 +1,16 @@
 /* -*- 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 "CameraPreferences.h"
 #include "CameraCommon.h"
+#include "mozilla/ArrayUtils.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 /* statics */
 static StaticAutoPtr<Monitor> sPrefMonitor;
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -261,16 +261,20 @@ public:
       AesCbcParams params;
       nsresult rv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(rv) || !params.mIv.WasPassed()) {
         mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
         return;
       }
 
       ATTEMPT_BUFFER_INIT(mIv, params.mIv.Value())
+      if (mIv.Length() != 16) {
+        mEarlyRv = NS_ERROR_DOM_DATA_ERR;
+        return;
+      }
     } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
       mMechanism = CKM_AES_CTR;
       telemetryAlg = TA_AES_CTR;
       AesCtrParams params;
       nsresult rv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(rv) || !params.mCounter.WasPassed() ||
           !params.mLength.WasPassed()) {
         mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
@@ -1160,21 +1164,27 @@ public:
         hashName.Assign(hashAlg.mName.Value());
       }
 
       if (params.mLength.WasPassed()) {
         mLength = params.mLength.Value();
       } else {
         KeyAlgorithm hashAlg(global, hashName);
         switch (hashAlg.Mechanism()) {
-          case CKM_SHA_1: mLength = 128; break;
-          case CKM_SHA256: mLength = 256; break;
-          case CKM_SHA384: mLength = 384; break;
-          case CKM_SHA512: mLength = 512; break;
-          default: mLength = 0; break;
+          case CKM_SHA_1:
+          case CKM_SHA256:
+            mLength = 512;
+            break;
+          case CKM_SHA384:
+          case CKM_SHA512:
+            mLength = 1024;
+            break;
+          default:
+            mLength = 0;
+            break;
         }
       }
 
       if (mLength == 0) {
         mEarlyRv = NS_ERROR_DOM_DATA_ERR;
         return;
       }
 
--- a/dom/crypto/test/tests.js
+++ b/dom/crypto/test/tests.js
@@ -327,17 +327,32 @@ TestArray.addTest(
 // -----------------------------------------------------------------------------
 TestArray.addTest(
   "Generate a 256-bit HMAC-SHA-256 key without specifying a key length",
   function() {
     var that = this;
     var alg = { name: "HMAC", hash: {name: "SHA-256"} };
     crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then(
       complete(that, function(x) {
-        return hasKeyFields(x) && x.algorithm.length == 256;
+        return hasKeyFields(x) && x.algorithm.length == 512;
+      }),
+      error(that)
+    );
+  }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
+  "Generate a 256-bit HMAC-SHA-512 key without specifying a key length",
+  function() {
+    var that = this;
+    var alg = { name: "HMAC", hash: {name: "SHA-512"} };
+    crypto.subtle.generateKey(alg, true, ["sign", "verify"]).then(
+      complete(that, function(x) {
+        return hasKeyFields(x) && x.algorithm.length == 1024;
       }),
       error(that)
     );
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
@@ -455,16 +470,46 @@ TestArray.addTest(
         memcmp_complete(that, tv.aes_cbc_enc.result),
         error(that)
       );
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
+  "AES-CBC encrypt with wrong IV size",
+  function () {
+    var that = this;
+
+    function encrypt(x, iv) {
+      console.log(x);
+      return crypto.subtle.encrypt(
+        { name: "AES-CBC", iv: iv },
+        x, tv.aes_cbc_enc.data);
+    }
+
+    function doEncrypt(x) {
+      return encrypt(x, new Uint8Array(15))
+        .then(
+          null,
+          function () { return encrypt(new Uint8Array(17)); }
+        );
+    }
+
+    crypto.subtle.importKey("raw", tv.aes_cbc_enc.key, "AES-CBC", false, ['encrypt'])
+      .then(doEncrypt)
+      .then(
+        error(that),
+        complete(that)
+      );
+  }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
   "AES-CBC decrypt",
   function () {
     var that = this;
 
     function doDecrypt(x) {
       return crypto.subtle.decrypt(
         { name: "AES-CBC", iv: tv.aes_cbc_dec.iv },
         x, tv.aes_cbc_dec.data);
@@ -476,16 +521,45 @@ TestArray.addTest(
         memcmp_complete(that, tv.aes_cbc_dec.result),
         error(that)
       );
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
+  "AES-CBC decrypt with wrong IV size",
+  function () {
+    var that = this;
+
+    function decrypt(x, iv) {
+      return crypto.subtle.decrypt(
+        { name: "AES-CBC", iv: iv },
+        x, tv.aes_cbc_dec.data);
+    }
+
+    function doDecrypt(x) {
+      return decrypt(x, new Uint8Array(15))
+        .then(
+          null,
+          function () { return decrypt(x, new Uint8Array(17)); }
+        );
+    }
+
+    crypto.subtle.importKey("raw", tv.aes_cbc_dec.key, "AES-CBC", false, ['decrypt'])
+      .then(doDecrypt)
+      .then(
+        error(that),
+        complete(that)
+      );
+  }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
   "AES-CTR encryption",
   function () {
     var that = this;
 
     function doEncrypt(x) {
       return crypto.subtle.encrypt(
         { name: "AES-CTR", counter: tv.aes_ctr_enc.iv, length: 32 },
         x, tv.aes_ctr_enc.data);
@@ -497,16 +571,45 @@ TestArray.addTest(
         memcmp_complete(that, tv.aes_ctr_enc.result),
         error(that)
       );
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
+  "AES-CTR encryption with wrong IV size",
+  function () {
+    var that = this;
+
+    function encrypt(x, iv) {
+      return crypto.subtle.encrypt(
+        { name: "AES-CTR", counter: iv, length: 32 },
+        x, tv.aes_ctr_enc.data);
+    }
+
+    function doEncrypt(x) {
+      return encrypt(x, new Uint8Array(15))
+        .then(
+          null,
+          function () { return encrypt(x, new Uint8Array(17)); }
+        );
+    }
+
+    crypto.subtle.importKey("raw", tv.aes_ctr_enc.key, "AES-CTR", false, ['encrypt'])
+      .then(doEncrypt)
+      .then(
+        error(that),
+        complete(that)
+      );
+  }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
   "AES-CTR decryption",
   function () {
     var that = this;
 
     function doDecrypt(x) {
       return crypto.subtle.decrypt(
         { name: "AES-CTR", counter: tv.aes_ctr_dec.iv, length: 32 },
         x, tv.aes_ctr_dec.data);
@@ -518,16 +621,45 @@ TestArray.addTest(
         memcmp_complete(that, tv.aes_ctr_dec.result),
         error(that)
       );
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
+  "AES-CTR decryption with wrong IV size",
+  function () {
+    var that = this;
+
+    function doDecrypt(x, iv) {
+      return crypto.subtle.decrypt(
+        { name: "AES-CTR", counter: iv, length: 32 },
+        x, tv.aes_ctr_dec.data);
+    }
+
+    function decrypt(x) {
+      return decrypt(x, new Uint8Array(15))
+        .then(
+          null,
+          function () { return decrypt(x, new Uint8Array(17)); }
+        );
+    }
+
+    crypto.subtle.importKey("raw", tv.aes_ctr_dec.key, "AES-CTR", false, ['decrypt'])
+      .then(doDecrypt)
+      .then(
+        error(that),
+        complete(that)
+      );
+  }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
   "AES-GCM encryption",
   function () {
     var that = this;
 
     function doEncrypt(x) {
       return crypto.subtle.encrypt(
         {
           name: "AES-GCM",
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -1719,25 +1719,21 @@ nsIFileToJsval(nsPIDOMWindow* aWindow, D
   return InterfaceToJsval(aWindow, blob, &NS_GET_IID(nsIDOMBlob));
 }
 
 JS::Value StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWindow);
 
-  JSObject* global =
-    static_cast<nsGlobalWindow*>(aWindow)->GetWrapperPreserveColor();
-  if (NS_WARN_IF(!global)) {
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitUsingWin(aWindow))) {
     return JSVAL_NULL;
   }
-
-  AutoJSAPI jsapi;
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, global);
 
   JS::Rooted<JS::Value> result(cx);
   if (!xpc::StringToJsval(cx, aString, &result)) {
     return JSVAL_NULL;
   }
 
   return result;
 }
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -1,16 +1,17 @@
 /* -*- 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/. */
 
 // Microsoft's API Name hackery sucks
 #undef CreateEvent
 
+#include "mozilla/AddonPathService.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #ifdef MOZ_B2G
 #include "mozilla/Hal.h"
 #endif // #ifdef MOZ_B2G
 #include "mozilla/HalSensor.h"
@@ -769,22 +770,22 @@ EventListenerManager::CompileEventHandle
              "What is there to compile?");
 
   nsresult result = NS_OK;
   nsCOMPtr<nsIDocument> doc;
   nsCOMPtr<nsIScriptGlobalObject> global =
     GetScriptGlobalAndDocument(getter_AddRefs(doc));
   NS_ENSURE_STATE(global);
 
-  nsIScriptContext* context = global->GetScriptContext();
-  NS_ENSURE_STATE(context);
-
   // Activate JSAPI, and make sure that exceptions are reported on the right
   // Window.
-  AutoJSAPIWithErrorsReportedToWindow jsapi(context);
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(global))) {
+    return NS_ERROR_UNEXPECTED;
+  }
   JSContext* cx = jsapi.cx();
 
   nsCOMPtr<nsIAtom> typeAtom = aListener->mTypeAtom;
   nsIAtom* attrName = typeAtom;
 
   // Flag us as not a string so we don't keep trying to compile strings which
   // can't be compiled.
   aListener->mHandlerIsString = false;
@@ -837,32 +838,45 @@ EventListenerManager::CompileEventHandle
 
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
   uint32_t argCount;
   const char **argNames;
   nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
                                    typeAtom, win,
                                    &argCount, &argNames);
 
+  JSAddonId *addonId = MapURIToAddonID(uri);
+
   // Wrap the event target, so that we can use it as the scope for the event
   // handler. Note that mTarget is different from aElement in the <body> case,
   // where mTarget is a Window.
   //
   // The wrapScope doesn't really matter here, because the target will create
   // its reflector in the proper scope, and then we'll enter that compartment.
-  JS::Rooted<JSObject*> wrapScope(cx, context->GetWindowProxy());
+  JS::Rooted<JSObject*> wrapScope(cx, global->GetGlobalJSObject());
   JS::Rooted<JS::Value> v(cx);
   {
     JSAutoCompartment ac(cx, wrapScope);
     nsresult rv = nsContentUtils::WrapNative(cx, mTarget, &v,
                                              /* aAllowWrapping = */ false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
+  if (addonId) {
+    JS::Rooted<JSObject*> vObj(cx, &v.toObject());
+    JS::Rooted<JSObject*> addonScope(cx, xpc::GetAddonScope(cx, vObj, addonId));
+    if (!addonScope) {
+      return NS_ERROR_FAILURE;
+    }
+    JSAutoCompartment ac(cx, addonScope);
+    if (!JS_WrapValue(cx, &v)) {
+      return NS_ERROR_FAILURE;
+    }
+  }
   JS::Rooted<JSObject*> target(cx, &v.toObject());
   JSAutoCompartment ac(cx, target);
 
   nsDependentAtomString str(attrName);
   // Most of our names are short enough that we don't even have to malloc
   // the JS string stuff, so don't worry about playing games with
   // refcounting XPCOM stringbuffers.
   JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
--- a/dom/icc/src/Icc.cpp
+++ b/dom/icc/src/Icc.cpp
@@ -43,23 +43,21 @@ nsresult
 Icc::NotifyEvent(const nsAString& aName)
 {
   return DispatchTrustedEvent(aName);
 }
 
 nsresult
 Icc::NotifyStkEvent(const nsAString& aName, const nsAString& aMessage)
 {
-  nsresult rv;
-  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  AutoJSAPIWithErrorsReportedToWindow jsapi(sc);
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReportingUsingWin(GetOwner()))) {
+    return NS_ERROR_UNEXPECTED;
+  }
   JSContext* cx = jsapi.cx();
-  JSAutoCompartment ac(cx, sc->GetWindowProxyPreserveColor());
   JS::Rooted<JS::Value> value(cx);
 
   if (!aMessage.IsEmpty()) {
     nsCOMPtr<nsIJSON> json(new nsJSON());
     nsresult rv = json->DecodeToJSVal(aMessage, cx, &value);
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
     value = JS::NullValue();
--- a/dom/imptests/failures/editing/conformancetest/test_runtest.html.json
+++ b/dom/imptests/failures/editing/conformancetest/test_runtest.html.json
@@ -3867,19 +3867,16 @@
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo<b>b[a]r</b>baz</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo<b>b[a]r</b>baz</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<address>foo[bar]baz</address>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<bdi>foo[bar]baz</bdi>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<blink>foo[bar]baz</blink>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<table><caption>foo[bar]baz</caption><tr><td>quz</table>\": execCommand(\"inserthorizontalrule\", false, \"\") return value":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<table><caption>foo[bar]baz</caption><tr><td>quz</table>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<dl><dt>foo[bar]baz</dt></dl>\" compare innerHTML":true,
-  "[[\"inserthorizontalrule\",\"\"]] \"<ruby>foo[bar]baz<rt>quz</rt></ruby>\" compare innerHTML":true,
-  "[[\"inserthorizontalrule\",\"\"]] \"<ruby>foo<rt>bar[baz]quz</rt></ruby>\" compare innerHTML":true,
-  "[[\"inserthorizontalrule\",\"\"]] \"<ruby>foo<rp>bar[baz]quz</rp><rt>qoz</rt><rp>qiz</rp></ruby>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"fo[o<span contenteditable=false>bar</span>b]az\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
   "[[\"inserthtml\",\"\"]] \"foo[bar]baz\": execCommand(\"inserthtml\", false, \"\") return value":true,
--- a/dom/interfaces/xpath/nsIDOMNSXPathExpression.idl
+++ b/dom/interfaces/xpath/nsIDOMNSXPathExpression.idl
@@ -1,16 +1,15 @@
 /* -*- 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"
 
-interface nsIDOMXPathResult;
 interface XPathException;
 
 /**
  * Interface for Mozilla specific XPathExpression functions.
  */
 [scriptable, uuid(ce600ca8-e98a-4419-ad61-2f6d0cb0ecc8)]
 interface nsIDOMNSXPathExpression : nsISupports
 {
--- a/dom/interfaces/xpath/nsIDOMXPathEvaluator.idl
+++ b/dom/interfaces/xpath/nsIDOMXPathEvaluator.idl
@@ -5,17 +5,16 @@
 
 /**
  * Corresponds to http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020208
  */
 
 #include "domstubs.idl"
 
 interface nsIDOMXPathNSResolver;
-interface nsIDOMXPathResult;
 interface nsIDOMXPathExpression;
 interface XPathException;
 
 [uuid(75506f8a-b504-11d5-a7f2-ca108ab8b6fc)]
 interface nsIDOMXPathEvaluator : nsISupports
 {
   nsIDOMXPathExpression    createExpression(in DOMString expression, 
                                             in nsIDOMXPathNSResolver resolver)
--- a/dom/interfaces/xpath/nsIDOMXPathExpression.idl
+++ b/dom/interfaces/xpath/nsIDOMXPathExpression.idl
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Corresponds to http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020208
  */
 
 #include "domstubs.idl"
 
-interface nsIDOMXPathResult;
 interface XPathException;
 
 [scriptable, uuid(75506f82-b504-11d5-a7f2-ca108ab8b6fc)]
 interface nsIDOMXPathExpression : nsISupports
 {
   nsISupports              evaluate(in nsIDOMNode contextNode, 
                                     in unsigned short type, 
                                     in nsISupports result)
--- a/dom/interfaces/xpath/nsIDOMXPathResult.idl
+++ b/dom/interfaces/xpath/nsIDOMXPathResult.idl
@@ -2,50 +2,25 @@
 /* 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/. */
 
 /**
  * Corresponds to http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020208
  */
 
-#include "domstubs.idl"
+#include "nsISupports.idl"
 
-interface XPathException;
-
-[scriptable, uuid(75506f84-b504-11d5-a7f2-ca108ab8b6fc)]
+[uuid(75506f84-b504-11d5-a7f2-ca108ab8b6fc)]
 interface nsIDOMXPathResult : nsISupports
 {
   // XPathResultType
   const unsigned short      ANY_TYPE                       = 0;
   const unsigned short      NUMBER_TYPE                    = 1;
   const unsigned short      STRING_TYPE                    = 2;
   const unsigned short      BOOLEAN_TYPE                   = 3;
   const unsigned short      UNORDERED_NODE_ITERATOR_TYPE   = 4;
   const unsigned short      ORDERED_NODE_ITERATOR_TYPE     = 5;
   const unsigned short      UNORDERED_NODE_SNAPSHOT_TYPE   = 6;
   const unsigned short      ORDERED_NODE_SNAPSHOT_TYPE     = 7;
   const unsigned short      ANY_UNORDERED_NODE_TYPE        = 8;
   const unsigned short      FIRST_ORDERED_NODE_TYPE        = 9;
-
-  readonly attribute unsigned short   resultType;
-  readonly attribute double           numberValue;
-                                      // raises(XPathException) on retrieval
-
-  readonly attribute DOMString        stringValue;
-                                      // raises(XPathException) on retrieval
-
-  readonly attribute boolean          booleanValue;
-                                      // raises(XPathException) on retrieval
-
-  readonly attribute nsIDOMNode       singleNodeValue;
-                                      // raises(XPathException) on retrieval
-
-  readonly attribute boolean          invalidIteratorState;
-  readonly attribute unsigned long    snapshotLength;
-                                      // raises(XPathException) on retrieval
-
-  nsIDOMNode               iterateNext()
-                                      raises(XPathException, 
-                                             DOMException);
-  nsIDOMNode               snapshotItem(in unsigned long index)
-                                      raises(XPathException);
 };
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -826,17 +826,18 @@ ContentParent::AnswerBridgeToChildProces
         // You can't bridge to a process you didn't open!
         KillHard();
         return false;
     }
 }
 
 /*static*/ TabParent*
 ContentParent::CreateBrowserOrApp(const TabContext& aContext,
-                                  Element* aFrameElement)
+                                  Element* aFrameElement,
+                                  ContentParent* aOpenerContentParent)
 {
     if (!sCanLaunchSubprocesses) {
         return nullptr;
     }
 
     ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
 
     if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
@@ -858,19 +859,22 @@ ContentParent::CreateBrowserOrApp(const 
             if (!child->CallBridgeToChildProcess(id)) {
                 return nullptr;
             }
             ContentBridgeParent* parent = child->GetLastBridge();
             parent->SetChildID(id);
             parent->SetIsForApp(isForApp);
             parent->SetIsForBrowser(isForBrowser);
             constructorSender = parent;
-        } else if (nsRefPtr<ContentParent> cp =
-                   GetNewOrUsed(aContext.IsBrowserElement(), initialPriority)) {
-            constructorSender = cp;
+        } else {
+          if (aOpenerContentParent) {
+            constructorSender = aOpenerContentParent;
+          } else {
+            constructorSender = GetNewOrUsed(aContext.IsBrowserElement(), initialPriority);
+          }
         }
         if (constructorSender) {
             uint32_t chromeFlags = 0;
 
             // Propagate the private-browsing status of the element's parent
             // docshell to the remote docshell, via the chrome flags.
             nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
             MOZ_ASSERT(frameElement);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -110,17 +110,18 @@ public:
 
     /**
      * Get or create a content process for the given TabContext.  aFrameElement
      * should be the frame/iframe element with which this process will
      * associated.
      */
     static TabParent*
     CreateBrowserOrApp(const TabContext& aContext,
-                       Element* aFrameElement);
+                       Element* aFrameElement,
+                       ContentParent* aOpenerContentParent);
 
     static void GetAll(nsTArray<ContentParent*>& aArray);
     static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
 
     static bool IgnoreIPCPrincipal();
 
     virtual bool RecvCreateChildProcess(const IPCTabContext& aContext,
                                         const hal::ProcessPriority& aPriority,
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -89,17 +89,25 @@ parent:
     /**
      * When child sends this message, parent should move focus to
      * the next or previous focusable element.
      */
     MoveFocus(bool forward);
 
     Event(RemoteDOMEvent aEvent);
 
-    intr CreateWindow() returns (PBrowser window);
+    intr CreateWindow(uint32_t aChromeFlags,
+                      bool aCalledFromJS,
+                      bool aPositionSpecified,
+                      bool aSizeSpecified,
+                      nsString aURI,
+                      nsString aName,
+                      nsString aFeatures,
+                      nsString aBaseURI)
+      returns (bool windowIsNew, PBrowser window);
 
     sync SyncMessage(nsString aMessage, ClonedMessageData aData,
                      CpowEntry[] aCpows, Principal aPrincipal)
       returns (nsString[] retval);
 
     rpc RpcMessage(nsString aMessage, ClonedMessageData aData,
                    CpowEntry[] aCpows, Principal aPrincipal)
       returns (nsString[] retval);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -37,19 +37,21 @@
 #include "nsEmbedCID.h"
 #include <algorithm>
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 #include "nsFilePickerProxy.h"
 #include "mozilla/dom/Element.h"
 #include "nsIBaseWindow.h"
+#include "nsIBrowserDOMWindow.h"
 #include "nsICachedFileDescriptorListener.h"
 #include "nsIDocumentInlines.h"
 #include "nsIDocShellTreeOwner.h"
+#include "nsIDOMChromeWindow.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIDocShell.h"
 #include "nsIURI.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIWebBrowser.h"
@@ -59,16 +61,17 @@
 #include "nsIXULRuntime.h"
 #include "nsInterfaceHashtable.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
 #include "nsPrintfCString.h"
 #include "nsThreadUtils.h"
 #include "nsWeakReference.h"
+#include "nsWindowWatcher.h"
 #include "PermissionMessageUtils.h"
 #include "PCOMContentPermissionRequestChild.h"
 #include "PuppetWidget.h"
 #include "StructuredCloneUtils.h"
 #include "nsViewportInfo.h"
 #include "JavaScriptChild.h"
 #include "nsILoadContext.h"
 #include "ipc/nsGUIEventIPC.h"
@@ -1225,23 +1228,78 @@ TabChild::ProvideWindow(nsIDOMWindow* aP
 
       // Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the
       // open window call was canceled.  It's important that we pass this error
       // code back to our caller.
       return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures,
                                        aWindowIsNew, aReturn);
     }
 
-    // Otherwise, create a new top-level window.
+    int32_t openLocation =
+      nsWindowWatcher::GetWindowOpenLocation(aParent, aChromeFlags, aCalledFromJS,
+                                             aPositionSpecified, aSizeSpecified);
+
+    // If it turns out we're opening in the current browser, just hand over the
+    // current browser's docshell.
+    if (openLocation == nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
+      nsCOMPtr<nsIWebBrowser> browser = do_GetInterface(WebNavigation());
+      *aWindowIsNew = false;
+      return browser->GetContentDOMWindow(aReturn);
+    }
+
+    // Otherwise, we're opening a new tab or a new window. We have to contact
+    // TabParent in order to do either.
+
     PBrowserChild* newChild;
-    if (!CallCreateWindow(&newChild)) {
+
+    nsAutoCString uriString;
+    if (aURI) {
+      aURI->GetSpec(uriString);
+    }
+
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    aParent->GetDocument(getter_AddRefs(domDoc));
+    if (!domDoc) {
+      NS_ERROR("Could retrieve document from nsIBaseWindow");
+      return NS_ERROR_FAILURE;
+    }
+
+    nsCOMPtr<nsIDocument> doc;
+    doc = do_QueryInterface(domDoc);
+    if (!doc) {
+      NS_ERROR("Document from nsIBaseWindow didn't QI to nsIDocument");
+      return NS_ERROR_FAILURE;
+    }
+
+    nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
+    if (!baseURI) {
+      NS_ERROR("nsIDocument didn't return a base URI");
+      return NS_ERROR_FAILURE;
+    }
+
+    nsAutoCString baseURIString;
+    baseURI->GetSpec(baseURIString);
+
+    nsAutoString nameString;
+    nameString.Assign(aName);
+    nsAutoCString features;
+
+    // We can assume that if content is requesting to open a window from a remote
+    // tab, then we want to enforce that the new window is also a remote tab.
+    features.Assign(aFeatures);
+    features.Append(",remote");
+
+    if (!CallCreateWindow(aChromeFlags, aCalledFromJS, aPositionSpecified,
+                          aSizeSpecified, NS_ConvertUTF8toUTF16(uriString),
+                          nameString, NS_ConvertUTF8toUTF16(features),
+                          NS_ConvertUTF8toUTF16(baseURIString),
+                          aWindowIsNew, &newChild)) {
         return NS_ERROR_NOT_AVAILABLE;
     }
 
-    *aWindowIsNew = true;
     nsCOMPtr<nsIDOMWindow> win =
         do_GetInterface(static_cast<TabChild*>(newChild)->WebNavigation());
     win.forget(aReturn);
     return NS_OK;
 }
 
 nsresult
 TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -39,25 +39,28 @@
 #include "nsIDOMElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPromptFactory.h"
 #include "nsIURI.h"
 #include "nsIWebBrowserChrome.h"
+#include "nsIWindowCreator2.h"
 #include "nsIXULBrowserWindow.h"
 #include "nsIXULWindow.h"
 #include "nsViewManager.h"
 #include "nsIWidget.h"
 #include "nsIWindowWatcher.h"
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowWatcher.h"
 #include "nsPrintfCString.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
+#include "nsWindowWatcher.h"
 #include "private/pprio.h"
 #include "PermissionMessageUtils.h"
 #include "StructuredCloneUtils.h"
 #include "ColorPickerParent.h"
 #include "JavaScriptParent.h"
 #include "FilePickerParent.h"
 #include "TabChild.h"
 #include "LoadContext.h"
@@ -383,45 +386,105 @@ TabParent::RecvEvent(const RemoteDOMEven
   event->SetOwner(target);
 
   bool dummy;
   target->DispatchEvent(event, &dummy);
   return true;
 }
 
 bool
-TabParent::AnswerCreateWindow(PBrowserParent** retval)
+TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
+                              const bool& aCalledFromJS,
+                              const bool& aPositionSpecified,
+                              const bool& aSizeSpecified,
+                              const nsString& aURI,
+                              const nsString& aName,
+                              const nsString& aFeatures,
+                              const nsString& aBaseURI,
+                              bool* aWindowIsNew,
+                              PBrowserParent** aRetVal)
 {
-    if (!mBrowserDOMWindow) {
-        return false;
-    }
+  if (IsBrowserOrApp()) {
+    return false;
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsPIWindowWatcher> pwwatch =
+    do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, false);
 
-    // Only non-app, non-browser processes may call CreateWindow.
-    if (IsBrowserOrApp()) {
-        return false;
-    }
+  nsCOMPtr<nsIContent> frame(do_QueryInterface(mFrameElement));
+  NS_ENSURE_TRUE(frame, false);
+
+  nsCOMPtr<nsIDOMWindow> parent = do_QueryInterface(frame->OwnerDoc()->GetWindow());
+  NS_ENSURE_TRUE(parent, false);
+
+  int32_t openLocation =
+    nsWindowWatcher::GetWindowOpenLocation(parent, aChromeFlags, aCalledFromJS,
+                                           aPositionSpecified, aSizeSpecified);
 
-    // Get a new rendering area from the browserDOMWin.  We don't want
-    // to be starting any loads here, so get it with a null URI.
+  MOZ_ASSERT(openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB ||
+             openLocation == nsIBrowserDOMWindow::OPEN_NEWWINDOW);
+
+  *aWindowIsNew = true;
+
+  // Opening new tabs is the easy case...
+  if (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB) {
+    NS_ENSURE_TRUE(mBrowserDOMWindow, false);
+
     nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
     mBrowserDOMWindow->OpenURIInFrame(nullptr, nullptr,
                                       nsIBrowserDOMWindow::OPEN_NEWTAB,
                                       nsIBrowserDOMWindow::OPEN_NEW,
                                       getter_AddRefs(frameLoaderOwner));
-    if (!frameLoaderOwner) {
-        return false;
-    }
+    NS_ENSURE_TRUE(frameLoaderOwner, false);
 
     nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
-    if (!frameLoader) {
-        return false;
-    }
+    NS_ENSURE_TRUE(frameLoader, false);
+
+    *aRetVal = frameLoader->GetRemoteBrowser();
+    return true;
+  }
+
+  // WindowWatcher is going to expect a valid URI to open a window
+  // to. If it can't find one, it's going to attempt to figure one
+  // out on its own, which is problematic because it can't access
+  // the document for the remote browser we're opening. Luckily,
+  // TabChild has sent us a baseURI with which we can ensure that
+  // the URI we pass to WindowWatcher is valid.
+  nsCOMPtr<nsIURI> baseURI;
+  rv = NS_NewURI(getter_AddRefs(baseURI), aBaseURI);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsCOMPtr<nsIURI> finalURI;
+  rv = NS_NewURI(getter_AddRefs(finalURI), NS_ConvertUTF16toUTF8(aURI).get(), baseURI);
+  NS_ENSURE_SUCCESS(rv, false);
 
-    *retval = frameLoader->GetRemoteBrowser();
-    return true;
+  nsAutoCString finalURIString;
+  finalURI->GetSpec(finalURIString);
+
+  nsCOMPtr<nsIDOMWindow> window;
+
+  rv = pwwatch->OpenWindow2(parent, finalURIString.get(),
+                            NS_ConvertUTF16toUTF8(aName).get(),
+                            NS_ConvertUTF16toUTF8(aFeatures).get(), aCalledFromJS,
+                            false, false, this, nullptr, getter_AddRefs(window));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(window);
+  NS_ENSURE_TRUE(pwindow, false);
+
+  nsRefPtr<nsIDocShell> newDocShell = pwindow->GetDocShell();
+  NS_ENSURE_TRUE(newDocShell, false);
+
+  nsCOMPtr<nsITabParent> newRemoteTab = newDocShell->GetOpenedRemote();
+  NS_ENSURE_TRUE(newRemoteTab, false);
+
+  *aRetVal = static_cast<TabParent*>(newRemoteTab.get());
+  return true;
 }
 
 void
 TabParent::LoadURL(nsIURI* aURI)
 {
     MOZ_ASSERT(aURI);
 
     if (mIsDestroyed) {
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -122,17 +122,26 @@ public:
                                              TextureFactoryIdentifier* aFactoryIdentifier,
                                              uint64_t* aLayersId,
                                              bool* aSuccess) MOZ_OVERRIDE;
     virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
                                             const nsString& aURL,
                                             const nsString& aName,
                                             const nsString& aFeatures,
                                             bool* aOutWindowOpened) MOZ_OVERRIDE;
-    virtual bool AnswerCreateWindow(PBrowserParent** retval) MOZ_OVERRIDE;
+    virtual bool AnswerCreateWindow(const uint32_t& aChromeFlags,
+                                    const bool& aCalledFromJS,
+                                    const bool& aPositionSpecified,
+                                    const bool& aSizeSpecified,
+                                    const nsString& aURI,
+                                    const nsString& aName,
+                                    const nsString& aFeatures,
+                                    const nsString& aBaseURI,
+                                    bool* aWindowIsNew,
+                                    PBrowserParent** aRetVal) MOZ_OVERRIDE;
     virtual bool RecvSyncMessage(const nsString& aMessage,
                                  const ClonedMessageData& aData,
                                  const InfallibleTArray<CpowEntry>& aCpows,
                                  const IPC::Principal& aPrincipal,
                                  InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
     virtual bool AnswerRpcMessage(const nsString& aMessage,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
--- a/dom/tests/browser/browser.ini
+++ b/dom/tests/browser/browser.ini
@@ -16,16 +16,21 @@ support-files =
 [browser_autofocus_background.js]
 [browser_autofocus_preference.js]
 [browser_bug396843.js]
 [browser_focus_steal_from_chrome.js]
 [browser_focus_steal_from_chrome_during_mousedown.js]
 [browser_frame_elements.js]
 [browser_geolocation_privatebrowsing_perwindowpb.js]
 [browser_localStorage_privatestorageevent.js]
+[browser_test_new_window_from_content.js]
+skip-if = (toolkit == 'android' || buildapp == 'b2g')
+support-files =
+  test_new_window_from_content_child.html
+  test_new_window_from_content_child.js
 [browser_webapps_permissions.js]
 # TODO: Re-enable permissions tests on Mac, bug 795334
 skip-if = buildapp != "b2g"
 support-files =
   test-webapp.webapp
   test-webapp-reinstall.webapp
   test-webapp-original.webapp
   test-webapps-permissions.html
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/browser_test_new_window_from_content.js
@@ -0,0 +1,340 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/*
+  We have three ways for content to open new windows:
+     1) window.open (with the default features)
+     2) window.open (with non-default features)
+     3) target="_blank" in <a> tags
+
+     We also have two prefs that modify our window opening behaviours:
+
+     1) browser.link.open_newwindow
+
+        This has a numeric value that allows us to set our window-opening behaviours from
+        content in three ways:
+        1) Open links that would normally open a new window in the current tab
+        2) Open links that would normally open a new window in a new window
+        3) Open links that would normally open a new window in a new tab (default)
+
+     2) browser.link.open_newwindow.restriction
+
+        This has a numeric value that allows us to fine tune the browser.link.open_newwindow
+        pref so that it can discriminate between different techniques for opening windows.
+
+        0) All things that open windows should behave according to browser.link.open_newwindow.
+        1) No things that open windows should behave according to browser.link.open_newwindow
+           (essentially rendering browser.link.open_newwindow inert).
+        2) Most things that open windows should behave according to browser.link.open_newwindow,
+           _except_ for window.open calls with the "feature" parameter. This will open in a new
+           window regardless of what browser.link.open_newwindow is set at. (default)
+
+     This file attempts to test each window opening technique against all possible settings for
+     each preference.
+*/
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+const kContentDoc = "http://www.example.com/browser/dom/tests/browser/test_new_window_from_content_child.html";
+const kContentScript = "chrome://mochitests/content/browser/dom/tests/browser/test_new_window_from_content_child.js";
+const kNewWindowPrefKey = "browser.link.open_newwindow";
+const kNewWindowRestrictionPrefKey = "browser.link.open_newwindow.restriction";
+const kSameTab = "same tab";
+const kNewWin = "new window";
+const kNewTab = "new tab";
+
+// The following "matrices" represent the result of content attempting to
+// open a window with window.open with the default feature set. The key of
+// the kWinOpenDefault object represents the value of browser.link.open_newwindow.
+// The value for each key is an array that represents the result (either opening
+// the link in the same tab, a new window, or a new tab), where the index of each
+// result maps to the browser.link.open_newwindow.restriction pref. I've tried
+// to illustrate this more clearly in the kWinOpenDefault object.
+const kWinOpenDefault = {
+//                    open_newwindow.restriction
+//                    0         1        2
+// open_newwindow
+                  1: [kSameTab, kNewWin, kSameTab],
+                  2: [kNewWin, kNewWin, kNewWin],
+                  3: [kNewTab, kNewWin, kNewTab],
+};
+
+const kWinOpenNonDefault = {
+  1: [kSameTab, kNewWin, kNewWin],
+  2: [kNewWin, kNewWin, kNewWin],
+  3: [kNewTab, kNewWin, kNewWin],
+};
+
+const kTargetBlank = {
+  1: [kSameTab, kSameTab, kSameTab],
+  2: [kNewWin, kNewWin, kNewWin],
+  3: [kNewTab, kNewTab, kNewTab],
+};
+
+// We'll be changing these preferences a lot, so we'll stash their original
+// values and make sure we restore them at the end of the test.
+let originalNewWindowPref = Services.prefs.getIntPref(kNewWindowPrefKey);
+let originalNewWindowRestrictionPref =
+  Services.prefs.getIntPref(kNewWindowRestrictionPrefKey);
+
+registerCleanupFunction(function() {
+  Services.prefs.setIntPref(kNewWindowPrefKey, originalNewWindowPref);
+  Services.prefs.setIntPref(kNewWindowRestrictionPrefKey,
+                            originalNewWindowRestrictionPref);
+  // If there are any content tabs leftover, make sure they're not going to
+  // block exiting with onbeforeunload.
+  for (let tab of gBrowser.tabs) {
+    let browser = gBrowser.getBrowserForTab(tab);
+    if (browser.contentDocument.location == kContentDoc) {
+      closeTab(tab);
+    }
+  }
+});
+
+/**
+ * WindowOpenListener is a very simple nsIWindowMediatorListener that
+ * listens for a new window opening to aExpectedURI. It has two Promises
+ * attached to it - openPromise and closePromise. As you'd expect,
+ * openPromise resolves when the window is opened, and closePromise
+ * resolves if and when a window with the same URI closes. There is
+ * no attempt to make sure that it's the same window opening and
+ * closing - we just use the URI.
+ *
+ * @param aExpectedURI the URI to watch for in a new window.
+ * @return nsIWindowMediatorListener
+ */
+function WindowOpenListener(aExpectedURI) {
+  this._openDeferred = Promise.defer();
+  this._closeDeferred = Promise.defer();
+  this._expectedURI = aExpectedURI;
+}
+
+WindowOpenListener.prototype = {
+  get openPromise() {
+    return this._openDeferred.promise;
+  },
+
+  get closePromise() {
+    return this._closeDeferred.promise;
+  },
+
+  onOpenWindow: function(aXULWindow) {
+    let domWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIDOMWindow);
+    let location = domWindow.document.location;
+    if (location == this._expectedURI) {
+      let deferred = this._openDeferred;
+      domWindow.addEventListener("load", function onWindowLoad() {
+        domWindow.removeEventListener("load", onWindowLoad);
+        deferred.resolve(domWindow);
+      })
+    }
+  },
+
+  onCloseWindow: function(aXULWindow) {
+    this._closeDeferred.resolve();
+  },
+  onWindowTitleChange: function(aXULWindow, aNewTitle) {},
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWindowMediatorListener])
+};
+
+/**
+ * Adds the testing tab, and injects our frame script which
+ * allows us to send click events to links and other things.
+ *
+ * @return a Promise that resolves once the tab is loaded and ready.
+ */
+function loadAndSelectTestTab() {
+  let tab = gBrowser.addTab(kContentDoc);
+  gBrowser.selectedTab = tab;
+
+  let browser = gBrowser.getBrowserForTab(tab);
+
+  // Bug 687194 - Mochitest registers its chrome URLs after browser
+  // initialization, so the content processes don't pick them up. That
+  // means we can't load our frame script from its chrome URI, because
+  // the content process won't be able to find it.
+  //
+  // Instead, we resolve the chrome URI for the script to a file URI, which
+  // we can then pass to the content process, which it is able to find.
+  let registry = Cc['@mozilla.org/chrome/chrome-registry;1'].getService(Ci.nsIChromeRegistry);
+  let fileURI = registry.convertChromeURL(Services.io.newURI(kContentScript, null, null)).spec;
+  browser.messageManager.loadFrameScript(fileURI, false);
+
+  let deferred = Promise.defer();
+  browser.addEventListener("DOMContentLoaded", function onBrowserLoad(aEvent) {
+    browser.removeEventListener("DOMContentLoaded", onBrowserLoad);
+    deferred.resolve(tab);
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Clears the onbeforeunload event handler from the testing tab,
+ * and then closes the tab.
+ *
+ * @param aTab the testing tab to close.
+ * @param a Promise that resolves once the tab has been closed.
+ */
+function closeTab(aTab) {
+  let deferred = Promise.defer();
+  let browserMM = gBrowser.getBrowserForTab(aTab).messageManager;
+  browserMM.sendAsyncMessage("TEST:allow-unload");
+  browserMM.addMessageListener("TEST:allow-unload:done", function(aMessage) {
+    gBrowser.removeTab(aTab);
+    deferred.resolve();
+  })
+  return deferred.promise;
+}
+
+/**
+ * Sends a click event on some item into a tab.
+ *
+ * @param aTab the tab to send the click event to
+ * @param aItemId the item within the tab content to click.
+ */
+function clickInTab(aTab, aItemId) {
+  let browserMM = gBrowser.getBrowserForTab(aTab).messageManager;
+  browserMM.sendAsyncMessage("TEST:click-item", {
+    details: aItemId,
+  });
+}
+
+/**
+ * For some expectation when a link is clicked, creates and
+ * returns a Promise that resolves when that expectation is
+ * fulfilled. For example, aExpectation might be kSameTab, which
+ * will cause this function to return a Promise that resolves when
+ * the current tab attempts to browse to about:blank.
+ *
+ * This function also takes care of cleaning up once the result has
+ * occurred - for example, if a new window was opened, this function
+ * closes it before resolving.
+ *
+ * @param aTab the tab with the test document
+ * @param aExpectation one of kSameTab, kNewWin, or kNewTab.
+ * @return a Promise that resolves when the expectation is fulfilled,
+ *         and cleaned up after.
+ */
+function prepareForResult(aTab, aExpectation) {
+  let deferred = Promise.defer();
+  let browser = gBrowser.getBrowserForTab(aTab);
+
+  switch(aExpectation) {
+    case kSameTab:
+      // We expect about:blank to be loaded in the current tab. In order
+      // to prevent us needing to reload the document and content script
+      // after browsing away, we'll detect the attempt by using onbeforeunload,
+      // and then cancel the unload. It's a hack, but it's also a pretty
+      // cheap way of detecting when we're browsing away in the test tab.
+      // The onbeforeunload event handler is set in the content script automatically.
+      browser.addEventListener("DOMWillOpenModalDialog", function onModalDialog() {
+        browser.removeEventListener("DOMWillOpenModalDialog", onModalDialog, true);
+        executeSoon(() => {
+          let stack = browser.parentNode;
+          let dialogs = stack.getElementsByTagNameNS(kXULNS, "tabmodalprompt");
+          dialogs[0].ui.button1.click()
+          deferred.resolve();
+        })
+      }, true);
+      break;
+    case kNewWin:
+      let listener = new WindowOpenListener("about:blank");
+      Services.wm.addListener(listener);
+
+      info("Waiting for a new about:blank window");
+      listener.openPromise.then(function(aWindow) {
+        info("Got the new about:blank window - closing it.");
+        executeSoon(() => {
+          aWindow.close();
+        });
+        listener.closePromise.then(() => {
+          info("New about:blank window closed!");
+          Services.wm.removeListener(listener);
+          deferred.resolve();
+        });
+      });
+      break;
+    case kNewTab:
+      gBrowser.tabContainer.addEventListener("TabOpen", function onTabOpen(aEvent) {
+        let newTab = aEvent.target;
+        let newBrowser = gBrowser.getBrowserForTab(newTab);
+        if (newBrowser.contentDocument.location.href == "about:blank") {
+          gBrowser.tabContainer.removeEventListener("TabOpen", onTabOpen);
+          executeSoon(() => {
+            gBrowser.removeTab(newTab);
+            deferred.resolve();
+          })
+        }
+      })
+      break;
+    default:
+      ok(false, "prepareForResult can't handle an expectation of " + aExpectation)
+      return;
+  }
+
+  return deferred.promise;
+}
+
+/**
+ * Ensure that clicks on a link with ID aLinkID cause us to
+ * perform as specified in the supplied aMatrix (kWinOpenDefault,
+ * for example).
+ *
+ * @param aLinkId the id of the link within the testing page to test.
+ * @param aMatrix a testing matrix for the
+ *        browser.link.open_newwindow and browser.link.open_newwindow.restriction
+ *        prefs to test against. See kWinOpenDefault for an example.
+ */
+function testLinkWithMatrix(aLinkId, aMatrix) {
+  return Task.spawn(function* () {
+    let tab = yield loadAndSelectTestTab();
+    // This nested for-loop is unravelling the matrix const
+    // we set up, and gives us three things through each tick
+    // of the inner loop:
+    // 1) newWindowPref: a browser.link.open_newwindow pref to try
+    // 2) newWindowRestPref: a browser.link.open_newwindow.restriction pref to try
+    // 3) expectation: what we expect the click outcome on this link to be,
+    //                 which will either be kSameTab, kNewWin or kNewTab.
+
+    for (let newWindowPref in aMatrix) {
+      let expectations = aMatrix[newWindowPref];
+      for (let i = 0; i < expectations.length; ++i) {
+        let newWindowRestPref = i;
+        let expectation = expectations[i];
+
+        Services.prefs.setIntPref("browser.link.open_newwindow", newWindowPref);
+        Services.prefs.setIntPref("browser.link.open_newwindow.restriction", newWindowRestPref);
+        info("Clicking on " + aLinkId);
+        info("Testing with browser.link.open_newwindow = " + newWindowPref + " and " +
+             "browser.link.open_newwindow.restriction = " + newWindowRestPref);
+        info("Expecting: " + expectation);
+        let resultPromise = prepareForResult(tab, expectation);
+        clickInTab(tab, aLinkId);
+        yield resultPromise;
+        ok(true, "Got expectation: " + expectation);
+      }
+    }
+    yield closeTab(tab);
+  });
+}
+
+add_task(function* test_window_open_with_defaults() {
+  yield testLinkWithMatrix("winOpenDefault", kWinOpenDefault);
+});
+
+add_task(function* test_window_open_with_non_defaults() {
+  yield testLinkWithMatrix("winOpenNonDefault", kWinOpenNonDefault);
+});
+
+add_task(function* test_target__blank() {
+  yield testLinkWithMatrix("targetBlank", kTargetBlank);
+});
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/test_new_window_from_content_child.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<head>
+  <meta charset="utf-8">
+  <title>Test popup window opening behaviour</title>
+</head>
+<body>
+  <p><a id="winOpenDefault" href="#" onclick="return openWindow();">Open a new window via window.open with default features.</a></p>
+  <p><a id="winOpenNonDefault" href="#" onclick="return openWindow('resizable=no, toolbar=no, scrollbars=no, menubar=no, status=no, directories=no, height=100, width=500');">Open a new window via window.open with non-default features.</a></p>
+  <p><a id="targetBlank" href="about:blank" target="_blank">Open a new window via target="_blank".</a></p>
+</body>
+</html>
+
+<script>
+function openWindow(aFeatures="") {
+  window.open("about:blank", "_blank", aFeatures);
+  return false;
+}
+
+window.onbeforeunload = function(aEvent) {
+  return "We should not browse away from this document.";
+}
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/test_new_window_from_content_child.js
@@ -0,0 +1,19 @@
+// A hacky mechanism for catching and detecting that we're attempting
+// to browse away is by setting the onbeforeunload event handler. We
+// detect this dialog opening in the parent test script, and dismiss
+// it.
+
+function handleClickItem(aMessage) {
+  let itemId = aMessage.data.details;
+  content.console.log("Getting item with ID: " + itemId);
+  let item = content.document.getElementById(itemId);
+  item.click();
+}
+
+function handleAllowUnload(aMessage) {
+  content.onbeforeunload = null;
+  sendSyncMessage("TEST:allow-unload:done");
+}
+
+addMessageListener("TEST:click-item", handleClickItem);
+addMessageListener("TEST:allow-unload", handleAllowUnload);
\ No newline at end of file
--- a/dom/webidl/XPathEvaluator.webidl
+++ b/dom/webidl/XPathEvaluator.webidl
@@ -1,23 +1,22 @@
 /* -*- 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/.
  */
 
 interface XPathExpression;
 interface XPathNSResolver;
-interface XPathResult;
 
 [Constructor]
 interface XPathEvaluator {
   // Based on nsIDOMXPathEvaluator
   [NewObject, Throws]
   XPathExpression createExpression(DOMString expression,
                                    XPathNSResolver? resolver);
   [NewObject, Throws]
   XPathNSResolver createNSResolver(Node? nodeResolver);
   [Throws]
   XPathResult evaluate(DOMString expression, Node? contextNode,
                        XPathNSResolver? resolver, unsigned short type,
-                       XPathResult? result);
+                       object? result);
 };
new file mode 100644
--- /dev/null
+++ b/dom/webidl/XPathResult.webidl
@@ -0,0 +1,38 @@
+/* -*- 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/.
+ *
+ * Corresponds to http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020208
+ */
+
+interface XPathResult {
+  // XPathResultType
+  const unsigned short ANY_TYPE = 0;
+  const unsigned short NUMBER_TYPE = 1;
+  const unsigned short STRING_TYPE = 2;
+  const unsigned short BOOLEAN_TYPE = 3;
+  const unsigned short UNORDERED_NODE_ITERATOR_TYPE = 4;
+  const unsigned short ORDERED_NODE_ITERATOR_TYPE = 5;
+  const unsigned short UNORDERED_NODE_SNAPSHOT_TYPE = 6;
+  const unsigned short ORDERED_NODE_SNAPSHOT_TYPE = 7;
+  const unsigned short ANY_UNORDERED_NODE_TYPE = 8;
+  const unsigned short FIRST_ORDERED_NODE_TYPE = 9;
+
+  readonly attribute unsigned short resultType;
+  [Throws]
+  readonly attribute double numberValue;
+  [Throws]
+  readonly attribute DOMString stringValue;
+  [Throws]
+  readonly attribute boolean booleanValue;
+  [Throws]
+  readonly attribute Node? singleNodeValue;
+  readonly attribute boolean invalidIteratorState;
+  [Throws]
+  readonly attribute unsigned long snapshotLength;
+  [Throws]
+  Node? iterateNext();
+  [Throws]
+  Node? snapshotItem(unsigned long index);
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -474,16 +474,17 @@ WEBIDL_FILES = [
     'WorkerNavigator.webidl',
     'XMLDocument.webidl',
     'XMLHttpRequest.webidl',
     'XMLHttpRequestEventTarget.webidl',
     'XMLHttpRequestUpload.webidl',
     'XMLSerializer.webidl',
     'XMLStylesheetProcessingInstruction.webidl',
     'XPathEvaluator.webidl',
+    'XPathResult.webidl',
     'XULCommandEvent.webidl',
     'XULDocument.webidl',
     'XULElement.webidl',
 ]
 
 if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']:
     WEBIDL_FILES += [
         'AudioChannelManager.webidl',
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3130,20 +3130,21 @@ WorkerPrivateParent<Derived>::BroadcastE
   for (size_t index = 0; index < sharedWorkers.Length(); index++) {
     nsRefPtr<SharedWorker>& sharedWorker = sharedWorkers[index];
 
     // May be null.
     nsPIDOMWindow* window = sharedWorker->GetOwner();
 
     size_t actionsIndex = windowActions.LastIndexOf(WindowAction(window));
 
-    nsIGlobalObject* global = sharedWorker->GetParentObject();
-    AutoJSAPIWithErrorsReportedToWindow jsapi(global);
+    AutoJSAPI jsapi;
+    if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReportingUsingWin(sharedWorker->GetOwner()))) {
+      continue;
+    }
     JSContext* cx = jsapi.cx();
-    JSAutoCompartment ac(cx, global->GetGlobalJSObject());
 
     RootedDictionary<ErrorEventInit> errorInit(aCx);
     errorInit.mBubbles = false;
     errorInit.mCancelable = true;
     errorInit.mMessage = aMessage;
     errorInit.mFilename = aFilename;
     errorInit.mLineno = aLineNumber;
     errorInit.mColno = aColumnNumber;
--- a/dom/xbl/XBLChildrenElement.cpp
+++ b/dom/xbl/XBLChildrenElement.cpp
@@ -98,18 +98,18 @@ nsAnonymousContentList::GetLength(uint32
   }
 
   uint32_t count = 0;
   for (nsIContent* child = mParent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
       XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
-      if (!point->mInsertedChildren.IsEmpty()) {
-        count += point->mInsertedChildren.Length();
+      if (point->HasInsertedChildren()) {
+        count += point->InsertedChildrenLength();
       }
       else {
         count += point->GetChildCount();
       }
     }
     else {
       ++count;
     }
@@ -139,21 +139,21 @@ nsAnonymousContentList::Item(uint32_t aI
   }
 
   uint32_t remIndex = aIndex;
   for (nsIContent* child = mParent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
       XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
-      if (!point->mInsertedChildren.IsEmpty()) {
-        if (remIndex < point->mInsertedChildren.Length()) {
-          return point->mInsertedChildren[remIndex];
+      if (point->HasInsertedChildren()) {
+        if (remIndex < point->InsertedChildrenLength()) {
+          return point->InsertedChild(remIndex);
         }
-        remIndex -= point->mInsertedChildren.Length();
+        remIndex -= point->InsertedChildrenLength();
       }
       else {
         if (remIndex < point->GetChildCount()) {
           return point->GetChildAt(remIndex);
         }
         remIndex -= point->GetChildCount();
       }
     }
@@ -174,33 +174,33 @@ nsAnonymousContentList::IndexOf(nsIConte
   NS_ASSERTION(!aContent->NodeInfo()->Equals(nsGkAtoms::children,
                                              kNameSpaceID_XBL),
                "Looking for insertion point");
 
   if (!mParent) {
     return -1;
   }
 
-  size_t index = 0;
+  int32_t index = 0;
   for (nsIContent* child = mParent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
       XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
-      if (!point->mInsertedChildren.IsEmpty()) {
-        size_t insIndex = point->mInsertedChildren.IndexOf(aContent);
-        if (insIndex != point->mInsertedChildren.NoIndex) {
+      if (point->HasInsertedChildren()) {
+        int32_t insIndex = point->IndexOfInsertedChild(aContent);
+        if (insIndex != -1) {
           return index + insIndex;
         }
-        index += point->mInsertedChildren.Length();
+        index += point->InsertedChildrenLength();
       }
       else {
         int32_t insIndex = point->IndexOf(aContent);
         if (insIndex != -1) {
-          return index + (size_t)insIndex;
+          return index + insIndex;
         }
         index += point->GetChildCount();
       }
     }
     else {
       if (child == aContent) {
         return index;
       }
--- a/dom/xbl/XBLChildrenElement.h
+++ b/dom/xbl/XBLChildrenElement.h
@@ -17,18 +17,16 @@ class nsAnonymousContentList;
 namespace mozilla {
 namespace dom {
 
 class ExplicitChildIterator;
 
 class XBLChildrenElement : public nsXMLElement
 {
 public:
-  friend class mozilla::dom::ExplicitChildIterator;
-  friend class nsAnonymousContentList;
   XBLChildrenElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsXMLElement(aNodeInfo)
   {
   }
   XBLChildrenElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     : nsXMLElement(aNodeInfo)
   {
   }
@@ -110,39 +108,40 @@ public:
     return mInsertedChildren.Length();
   }
 
   bool HasInsertedChildren()
   {
     return !mInsertedChildren.IsEmpty();
   }
 
-  enum {
-    NoIndex = uint32_t(-1)
-  };
-  uint32_t IndexOfInsertedChild(nsIContent* aChild)
+  int32_t IndexOfInsertedChild(nsIContent* aChild)
   {
     return mInsertedChildren.IndexOf(aChild);
   }
 
   bool Includes(nsIContent* aChild)
   {
     NS_ASSERTION(!mIncludes.IsEmpty(),
                  "Shouldn't check for includes on default insertion point");
     return mIncludes.Contains(aChild->Tag());
   }
 
   bool IsDefaultInsertion()
   {
     return mIncludes.IsEmpty();
   }
 
-  nsTArray<nsIContent*> mInsertedChildren;
+  nsIContent* InsertedChild(uint32_t aIndex)
+  {
+    return mInsertedChildren[aIndex];
+  }
 
 private:
+  nsTArray<nsIContent*> mInsertedChildren; // WEAK
   nsTArray<nsCOMPtr<nsIAtom> > mIncludes;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 class nsAnonymousContentList : public nsINodeList
 {
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -808,51 +808,51 @@ nsBindingManager::MediumFeaturesChanged(
   set->EnumerateEntries(EnumMediumFeaturesChanged, &data);
   return NS_OK;
 }
 
 static PLDHashOperator
 EnumAppendAllSheets(nsRefPtrHashKey<nsIContent> *aKey, void* aClosure)
 {
   nsIContent *boundContent = aKey->GetKey();
-  nsTArray<nsCSSStyleSheet*>* array =
-    static_cast<nsTArray<nsCSSStyleSheet*>*>(aClosure);
+  nsTArray<CSSStyleSheet*>* array =
+    static_cast<nsTArray<CSSStyleSheet*>*>(aClosure);
   for (nsXBLBinding *binding = boundContent->GetXBLBinding(); binding;
        binding = binding->GetBaseBinding()) {
     binding->PrototypeBinding()->AppendStyleSheetsTo(*array);
   }
   return PL_DHASH_NEXT;
 }
 
 void
-nsBindingManager::AppendAllSheets(nsTArray<nsCSSStyleSheet*>& aArray)
+nsBindingManager::AppendAllSheets(nsTArray<CSSStyleSheet*>& aArray)
 {
   if (mBoundContentSet) {
     mBoundContentSet->EnumerateEntries(EnumAppendAllSheets, &aArray);
   }
 }
 
 static void
 InsertAppendedContent(XBLChildrenElement* aPoint,
                       nsIContent* aFirstNewContent)
 {
-  size_t insertionIndex;
+  int32_t insertionIndex;
   if (nsIContent* prevSibling = aFirstNewContent->GetPreviousSibling()) {
     // If we have a previous sibling, then it must already be in aPoint. Find
     // it and insert after it.
     insertionIndex = aPoint->IndexOfInsertedChild(prevSibling);
-    MOZ_ASSERT(insertionIndex != aPoint->NoIndex);
+    MOZ_ASSERT(insertionIndex != -1);
 
     // Our insertion index is one after our previous sibling's index.
     ++insertionIndex;
   } else {
     // Otherwise, we append.
     // TODO This is wrong for nested insertion points. In that case, we need to
     // keep track of the right index to insert into.
-    insertionIndex = aPoint->mInsertedChildren.Length();
+    insertionIndex = aPoint->InsertedChildrenLength();
   }
 
   // Do the inserting.
   for (nsIContent* currentChild = aFirstNewContent;
        currentChild;
        currentChild = currentChild->GetNextSibling()) {
     aPoint->InsertInsertedChildAt(currentChild, insertionIndex++);
   }
@@ -1072,25 +1072,25 @@ nsBindingManager::HandleChildInsertion(n
     if (!point) {
       break;
     }
 
     // Insert the child into the proper insertion point.
     // TODO If there were multiple insertion points, this approximation can be
     // wrong. We need to re-run the distribution algorithm. In the meantime,
     // this should work well enough.
-    size_t index = aAppend ? point->mInsertedChildren.Length() : 0;
+    uint32_t index = aAppend ? point->InsertedChildrenLength() : 0;
     for (nsIContent* currentSibling = aChild->GetPreviousSibling();
          currentSibling;
          currentSibling = currentSibling->GetPreviousSibling()) {
       // If we find one of our previous siblings in the insertion point, the
       // index following it is the correct insertion point. Otherwise, we guess
       // based on whether we're appending or inserting.
-      size_t pointIndex = point->IndexOfInsertedChild(currentSibling);
-      if (pointIndex != point->NoIndex) {
+      int32_t pointIndex = point->IndexOfInsertedChild(currentSibling);
+      if (pointIndex != -1) {
         index = pointIndex + 1;
         break;
       }
     }
 
     point->InsertInsertedChildAt(aChild, index);
 
     nsIContent* newParent = point->GetParent();
--- a/dom/xbl/nsBindingManager.h
+++ b/dom/xbl/nsBindingManager.h
@@ -25,17 +25,20 @@ class nsIDocument;
 class nsIURI;
 class nsXBLDocumentInfo;
 class nsIStreamListener;
 class nsStyleSet;
 class nsXBLBinding;
 template<class E> class nsRefPtr;
 typedef nsTArray<nsRefPtr<nsXBLBinding> > nsBindingList;
 class nsIPrincipal;
-class nsCSSStyleSheet;
+
+namespace mozilla {
+class CSSStyleSheet;
+} // namespace mozilla
 
 class nsBindingManager MOZ_FINAL : public nsStubMutationObserver
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
@@ -111,17 +114,17 @@ public:
   /**
    * Do any processing that needs to happen as a result of a change in
    * the characteristics of the medium, and return whether this rule
    * processor's rules have changed (e.g., because of media queries).
    */
   nsresult MediumFeaturesChanged(nsPresContext* aPresContext,
                                  bool* aRulesChanged);
 
-  void AppendAllSheets(nsTArray<nsCSSStyleSheet*>& aArray);
+  void AppendAllSheets(nsTArray<mozilla::CSSStyleSheet*>& aArray);
 
   void Traverse(nsIContent *aContent,
                             nsCycleCollectionTraversalCallback &cb);
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsBindingManager)
 
   // Notify the binding manager when an outermost update begins and
   // ends.  The end method can execute script.
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -697,17 +697,17 @@ static void
 UpdateInsertionParent(XBLChildrenElement* aPoint,
                       nsIContent* aOldBoundElement)
 {
   if (aPoint->IsDefaultInsertion()) {
     return;
   }
 
   for (size_t i = 0; i < aPoint->InsertedChildrenLength(); ++i) {
-    nsIContent* child = aPoint->mInsertedChildren[i];
+    nsIContent* child = aPoint->InsertedChild(i);
 
     MOZ_ASSERT(child->GetParentNode());
 
     // Here, we're iterating children that we inserted. There are two cases:
     // either |child| is an explicit child of |aOldBoundElement| and is no
     // longer inserted anywhere or it's a child of a <children> element
     // parented to |aOldBoundElement|. In the former case, the child is no
     // longer inserted anywhere, so we set its insertion parent to null. In the
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -1681,40 +1681,40 @@ void
 nsXBLPrototypeBinding::EnsureResources()
 {
   if (!mResources) {
     mResources = new nsXBLPrototypeResources(this);
   }
 }
 
 void
-nsXBLPrototypeBinding::AppendStyleSheet(nsCSSStyleSheet* aSheet)
+nsXBLPrototypeBinding::AppendStyleSheet(CSSStyleSheet* aSheet)
 {
   EnsureResources();
   mResources->AppendStyleSheet(aSheet);
 }
 
 void
-nsXBLPrototypeBinding::RemoveStyleSheet(nsCSSStyleSheet* aSheet)
+nsXBLPrototypeBinding::RemoveStyleSheet(CSSStyleSheet* aSheet)
 {
   if (!mResources) {
     MOZ_ASSERT(false, "Trying to remove a sheet that does not exist.");
     return;
   }
 
   mResources->RemoveStyleSheet(aSheet);
 } 
 void
-nsXBLPrototypeBinding::InsertStyleSheetAt(size_t aIndex, nsCSSStyleSheet* aSheet)
+nsXBLPrototypeBinding::InsertStyleSheetAt(size_t aIndex, CSSStyleSheet* aSheet)
 {
   EnsureResources();
   mResources->InsertStyleSheetAt(aIndex, aSheet);
 }
 
-nsCSSStyleSheet*
+CSSStyleSheet*
 nsXBLPrototypeBinding::StyleSheetAt(size_t aIndex) const
 {
   MOZ_ASSERT(mResources);
   return mResources->StyleSheetAt(aIndex);
 }
 
 size_t
 nsXBLPrototypeBinding::SheetCount() const
@@ -1725,14 +1725,14 @@ nsXBLPrototypeBinding::SheetCount() cons
 bool
 nsXBLPrototypeBinding::HasStyleSheets() const
 {
   return mResources && mResources->HasStyleSheets();
 }
 
 void
 nsXBLPrototypeBinding::AppendStyleSheetsTo(
-                                      nsTArray<nsCSSStyleSheet*>& aResult) const
+                                      nsTArray<CSSStyleSheet*>& aResult) const
 {
   if (mResources) {
     mResources->AppendStyleSheetsTo(aResult);
   }
 }
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -20,16 +20,20 @@
 
 class nsIAtom;
 class nsIContent;
 class nsIDocument;
 class nsXBLAttributeEntry;
 class nsXBLBinding;
 class nsXBLProtoImplField;
 
+namespace mozilla {
+class CSSStyleSheet;
+} // namespace mozilla
+
 // *********************************************************************/
 // The XBLPrototypeBinding class
 
 // Instances of this class are owned by the nsXBLDocumentInfo object returned
 // by XBLDocumentInfo().  Consumers who want to refcount things should refcount
 // that.
 class nsXBLPrototypeBinding MOZ_FINAL
 {
@@ -108,23 +112,23 @@ public:
   void SetBasePrototype(nsXBLPrototypeBinding* aBinding);
   nsXBLPrototypeBinding* GetBasePrototype() { return mBaseBinding; }
 
   nsXBLDocumentInfo* XBLDocumentInfo() const { return mXBLDocInfoWeak; }
   bool IsChrome() { return mXBLDocInfoWeak->IsChrome(); }
 
   void SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent);
 
-  void AppendStyleSheet(nsCSSStyleSheet* aSheet);
-  void RemoveStyleSheet(nsCSSStyleSheet* aSheet);
-  void InsertStyleSheetAt(size_t aIndex, nsCSSStyleSheet* aSheet);
-  nsCSSStyleSheet* StyleSheetAt(size_t aIndex) const;
+  void AppendStyleSheet(mozilla::CSSStyleSheet* aSheet);
+  void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet);
+  void InsertStyleSheetAt(size_t aIndex, mozilla::CSSStyleSheet* aSheet);
+  mozilla::CSSStyleSheet* StyleSheetAt(size_t aIndex) const;
   size_t SheetCount() const;
   bool HasStyleSheets() const;
-  void AppendStyleSheetsTo(nsTArray<nsCSSStyleSheet*>& aResult) const;
+  void AppendStyleSheetsTo(nsTArray<mozilla::CSSStyleSheet*>& aResult) const;
 
   nsIStyleRuleProcessor* GetRuleProcessor();
 
   nsresult FlushSkinSheets();
 
   nsIAtom* GetBaseTag(int32_t* aNamespaceID);
   void SetBaseTag(int32_t aNamespaceID, nsIAtom* aTag);
 
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -75,28 +75,28 @@ nsXBLPrototypeResources::FlushSkinSheets
     return NS_OK;
   }
 
   // We have scoped stylesheets.  Reload any chrome stylesheets we
   // encounter.  (If they aren't skin sheets, it doesn't matter, since
   // they'll still be in the chrome cache.
   mRuleProcessor = nullptr;
 
-  nsTArray<nsRefPtr<nsCSSStyleSheet>> oldSheets;
+  nsTArray<nsRefPtr<CSSStyleSheet>> oldSheets;
 
   oldSheets.SwapElements(mStyleSheetList);
 
   mozilla::css::Loader* cssLoader = doc->CSSLoader();
 
   for (size_t i = 0, count = oldSheets.Length(); i < count; ++i) {
-    nsCSSStyleSheet* oldSheet = oldSheets[i];
+    CSSStyleSheet* oldSheet = oldSheets[i];
 
     nsIURI* uri = oldSheet->GetSheetURI();
 
-    nsRefPtr<nsCSSStyleSheet> newSheet;
+    nsRefPtr<CSSStyleSheet> newSheet;
     if (IsChromeURI(uri)) {
       if (NS_FAILED(cssLoader->LoadSheetSync(uri, getter_AddRefs(newSheet))))
         continue;
     }
     else {
       newSheet = oldSheet;
     }
 
@@ -133,35 +133,35 @@ void
 nsXBLPrototypeResources::GatherRuleProcessor()
 {
   mRuleProcessor = new nsCSSRuleProcessor(mStyleSheetList,
                                           nsStyleSet::eDocSheet,
                                           nullptr);
 }
 
 void
-nsXBLPrototypeResources::AppendStyleSheet(nsCSSStyleSheet* aSheet)
+nsXBLPrototypeResources::AppendStyleSheet(CSSStyleSheet* aSheet)
 {
   mStyleSheetList.AppendElement(aSheet);
 }
 
 void
-nsXBLPrototypeResources::RemoveStyleSheet(nsCSSStyleSheet* aSheet)
+nsXBLPrototypeResources::RemoveStyleSheet(CSSStyleSheet* aSheet)
 {
   DebugOnly<bool> found = mStyleSheetList.RemoveElement(aSheet);
   MOZ_ASSERT(found, "Trying to remove a sheet that does not exist.");
 }
 
 void
-nsXBLPrototypeResources::InsertStyleSheetAt(size_t aIndex, nsCSSStyleSheet* aSheet)
+nsXBLPrototypeResources::InsertStyleSheetAt(size_t aIndex, CSSStyleSheet* aSheet)
 {
   mStyleSheetList.InsertElementAt(aIndex, aSheet);
 }
 
-nsCSSStyleSheet*
+CSSStyleSheet*
 nsXBLPrototypeResources::StyleSheetAt(size_t aIndex) const
 {
   return mStyleSheetList[aIndex];
 }
 
 size_t
 nsXBLPrototypeResources::SheetCount() const
 {
@@ -171,12 +171,12 @@ nsXBLPrototypeResources::SheetCount() co
 bool
 nsXBLPrototypeResources::HasStyleSheets() const
 {
   return !mStyleSheetList.IsEmpty();
 }
 
 void
 nsXBLPrototypeResources::AppendStyleSheetsTo(
-                                      nsTArray<nsCSSStyleSheet*>& aResult) const
+                                      nsTArray<CSSStyleSheet*>& aResult) const
 {
   aResult.AppendElements(mStyleSheetList);
 }
--- a/dom/xbl/nsXBLPrototypeResources.h
+++ b/dom/xbl/nsXBLPrototypeResources.h
@@ -5,22 +5,25 @@
 
 #ifndef nsXBLPrototypeResources_h__
 #define nsXBLPrototypeResources_h__
 
 #include "nsAutoPtr.h"
 #include "nsICSSLoaderObserver.h"
 
 class nsCSSRuleProcessor;
-class nsCSSStyleSheet;
 class nsIAtom;
 class nsIContent;
 class nsXBLPrototypeBinding;
 class nsXBLResourceLoader;
 
+namespace mozilla {
+class CSSStyleSheet;
+} // namespace mozilla
+
 // *********************************************************************/
 // The XBLPrototypeResources class
 
 class nsXBLPrototypeResources
 {
 public:
   nsXBLPrototypeResources(nsXBLPrototypeBinding* aBinding);
   ~nsXBLPrototypeResources();
@@ -31,37 +34,37 @@ public:
   nsresult FlushSkinSheets();
 
   nsresult Write(nsIObjectOutputStream* aStream);
 
   void Traverse(nsCycleCollectionTraversalCallback &cb) const;
 
   void ClearLoader();
 
-  void AppendStyleSheet(nsCSSStyleSheet* aSheet);
-  void RemoveStyleSheet(nsCSSStyleSheet* aSheet);
-  void InsertStyleSheetAt(size_t aIndex, nsCSSStyleSheet* aSheet);
-  nsCSSStyleSheet* StyleSheetAt(size_t aIndex) const;
+  void AppendStyleSheet(mozilla::CSSStyleSheet* aSheet);
+  void RemoveStyleSheet(mozilla::CSSStyleSheet* aSheet);
+  void InsertStyleSheetAt(size_t aIndex, mozilla::CSSStyleSheet* aSheet);
+  mozilla::CSSStyleSheet* StyleSheetAt(size_t aIndex) const;
   size_t SheetCount() const;
   bool HasStyleSheets() const;
-  void AppendStyleSheetsTo(nsTArray<nsCSSStyleSheet*>& aResult) const;
+  void AppendStyleSheetsTo(nsTArray<mozilla::CSSStyleSheet*>& aResult) const;
 
   /**
    * Recreates mRuleProcessor to represent the current list of style sheets
    * stored in mStyleSheetList.  (Named GatherRuleProcessor to parallel
    * nsStyleSet::GatherRuleProcessors.)
    */
   void GatherRuleProcessor();
 
   nsCSSRuleProcessor* GetRuleProcessor() const { return mRuleProcessor; }
 
 private:
   // A loader object. Exists only long enough to load resources, and then it dies.
   nsRefPtr<nsXBLResourceLoader> mLoader;
 
   // A list of loaded stylesheets for this binding.
-  nsTArray<nsRefPtr<nsCSSStyleSheet>> mStyleSheetList;
+  nsTArray<nsRefPtr<mozilla::CSSStyleSheet>> mStyleSheetList;
 
   // The list of stylesheets converted to a rule processor.
   nsRefPtr<nsCSSRuleProcessor> mRuleProcessor;
 };
 
 #endif
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -1,39 +1,41 @@
 /* -*- 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 "nsTArray.h"
 #include "nsString.h"
-#include "nsCSSStyleSheet.h"
 #include "nsIStyleRuleProcessor.h"
 #include "nsIDocument.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsXBLService.h"
 #include "nsIServiceManager.h"
 #include "nsXBLResourceLoader.h"
 #include "nsXBLPrototypeResources.h"
 #include "nsIDocumentObserver.h"
 #include "imgILoader.h"
 #include "imgRequestProxy.h"
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Loader.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsGkAtoms.h"
 #include "nsFrameManager.h"
 #include "nsStyleContext.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsContentUtils.h"
 #include "nsStyleSet.h"
 #include "nsIScriptSecurityManager.h"
 
+using namespace mozilla;
+
 NS_IMPL_CYCLE_COLLECTION(nsXBLResourceLoader, mBoundElements)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLResourceLoader)
   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLResourceLoader)
@@ -130,17 +132,17 @@ nsXBLResourceLoader::LoadResources(bool*
       bool chrome;
       nsresult rv;
       if (NS_SUCCEEDED(url->SchemeIs("chrome", &chrome)) && chrome)
       {
         rv = nsContentUtils::GetSecurityManager()->
           CheckLoadURIWithPrincipal(docPrincipal, url,
                                     nsIScriptSecurityManager::ALLOW_CHROME);
         if (NS_SUCCEEDED(rv)) {
-          nsRefPtr<nsCSSStyleSheet> sheet;
+          nsRefPtr<CSSStyleSheet> sheet;
           rv = cssLoader->LoadSheetSync(url, getter_AddRefs(sheet));
           NS_ASSERTION(NS_SUCCEEDED(rv), "Load failed!!!");
           if (NS_SUCCEEDED(rv))
           {
             rv = StyleSheetLoaded(sheet, false, NS_OK);
             NS_ASSERTION(NS_SUCCEEDED(rv), "Processing the style sheet failed!!!");
           }
         }
@@ -159,17 +161,17 @@ nsXBLResourceLoader::LoadResources(bool*
   
   // Destroy our resource list.
   delete mResourceList;
   mResourceList = nullptr;
 }
 
 // nsICSSLoaderObserver
 NS_IMETHODIMP
-nsXBLResourceLoader::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
+nsXBLResourceLoader::StyleSheetLoaded(CSSStyleSheet* aSheet,
                                       bool aWasAlternate,
                                       nsresult aStatus)
 {
   if (!mResources) {
     // Our resources got destroyed -- just bail out
     return NS_OK;
   }
    
--- a/dom/xbl/nsXBLResourceLoader.h
+++ b/dom/xbl/nsXBLResourceLoader.h
@@ -24,17 +24,18 @@ class nsIObjectOutputStream;
 
 class nsXBLResourceLoader : public nsICSSLoaderObserver
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsXBLResourceLoader)
 
   // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet, bool aWasAlternate,
+  NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
+                              bool aWasAlternate,
                               nsresult aStatus) MOZ_OVERRIDE;
 
   void LoadResources(bool* aResult);
   void AddResource(nsIAtom* aResourceType, const nsAString& aSrc);
   void AddResourceListener(nsIContent* aElement);
 
   nsXBLResourceLoader(nsXBLPrototypeBinding* aBinding,
                       nsXBLPrototypeResources* aResources);
--- a/dom/xslt/tests/mochitest/test_bug319374.xhtml
+++ b/dom/xslt/tests/mochitest/test_bug319374.xhtml
@@ -34,18 +34,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     function getAnonymousNodes(e) {
       return SpecialPowers.wrap(document).getAnonymousNodes(e);
     }
     try {
       var xp = new XPathEvaluator();
       var result = xp.evaluate("*",
                                document.getElementById('content'),
                                null,
-                               SpecialPowers.Ci.nsIDOMXPathResult.
-                                 UNORDERED_NODE_ITERATOR_TYPE,
+                               XPathResult.UNORDERED_NODE_ITERATOR_TYPE,
                                null);
       var res = null;
       while (res = result.iterateNext()) {
         ++counter; 
         var anon = getAnonymousNodes(res);
         anon[0].removeChild(anon[0].firstChild); // Removing a child node
         anon[0].removeAttribute("attr1"); // Removing an attribute
         anon[1].firstChild.data = "anon text changed" // Modifying text data
@@ -64,36 +63,34 @@ https://bugzilla.mozilla.org/show_bug.cg
     var anonAttr2 =
       getAnonymousNodes(document.getElementById('content').
         lastChild)[0].getAttributeNode('attr');
     var resultAttr = null;
     try {
       var xp2 = SpecialPowers.wrap(xp).evaluate(".",
                             anonAttr1,
                             null,
-                            SpecialPowers.Ci.nsIDOMXPathResult.
-                              UNORDERED_NODE_ITERATOR_TYPE,
+                            XPathResult.UNORDERED_NODE_ITERATOR_TYPE,
                             null);
       // Attribute changing in a different anonymous tree.
       anonAttr2.value = "foo";
       resultAttr = xp2.iterateNext();
       ok(SpecialPowers.compare(resultAttr, anonAttr1), "XPathEvaluator returned wrong attribute!")
     } catch (e) {
       ok(false, e);
     }
 
     // Test 3: If the anonymous tree in which context node is in is modified,
     //         XPath result should throw when iterateNext() is called.
     resultAttr = null;
     try {
       var xp3 = xp.evaluate(".",
                             anonAttr1,
                             null,
-                            SpecialPowers.Ci.nsIDOMXPathResult.
-                              UNORDERED_NODE_ITERATOR_TYPE,
+                            XPathResult.UNORDERED_NODE_ITERATOR_TYPE,
                             null);
       // Attribute changing in the same anonymous tree.
       anonAttr1.ownerElement.setAttribute("foo", "bar");
       resultAttr = xp3.iterateNext();
       ok(resultAttr == anonAttr1,
          "XPathEvaluator should have thrown an exception!")
     } catch (e) {
       ok(true, e);
--- a/dom/xslt/xpath/XPathEvaluator.cpp
+++ b/dom/xslt/xpath/XPathEvaluator.cpp
@@ -4,28 +4,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/XPathEvaluator.h"
 #include "mozilla/Move.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 #include "nsXPathExpression.h"
 #include "nsXPathNSResolver.h"
-#include "nsXPathResult.h"
+#include "XPathResult.h"
 #include "nsContentCID.h"
 #include "txExpr.h"
 #include "txExprParser.h"
 #include "nsError.h"
 #include "txURIUtils.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsDOMString.h"
 #include "nsNameSpaceManager.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/XPathEvaluatorBinding.h"
+#include "mozilla/dom/BindingUtils.h"
 
 extern nsresult
 TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
                             nsIAtom *aName, nsISupports *aState,
                             FunctionCall **aFunction);
 
 namespace mozilla {
 namespace dom {
@@ -169,26 +170,28 @@ XPathEvaluator::CreateNSResolver(nsINode
                                  ErrorResult& rv)
 {
   nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver);
   nsCOMPtr<nsIDOMXPathNSResolver> res;
   rv = CreateNSResolver(nodeResolver, getter_AddRefs(res));
   return res.forget();
 }
 
-already_AddRefed<nsISupports>
-XPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode,
+already_AddRefed<XPathResult>
+XPathEvaluator::Evaluate(JSContext* aCx, const nsAString& aExpression,
+                         nsINode* aContextNode,
                          nsIDOMXPathNSResolver* aResolver, uint16_t aType,
-                         nsISupports* aResult, ErrorResult& rv)
+                         JS::Handle<JSObject*> aResult, ErrorResult& rv)
 {
   nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode);
   nsCOMPtr<nsISupports> res;
   rv = Evaluate(aExpression, contextNode, aResolver, aType,
-                aResult, getter_AddRefs(res));
-  return res.forget();
+                aResult ? UnwrapDOMObjectToISupports(aResult) : nullptr,
+                getter_AddRefs(res));
+  return res.forget().downcast<nsIXPathResult>().downcast<XPathResult>();
 }
 
 
 /*
  * Implementation of txIParseContext private to XPathEvaluator, based on a
  * nsIDOMXPathNSResolver
  */
 
--- a/dom/xslt/xpath/XPathEvaluator.h
+++ b/dom/xslt/xpath/XPathEvaluator.h
@@ -16,16 +16,17 @@
 
 class nsINode;
 class txResultRecycler;
 
 namespace mozilla {
 namespace dom {
 
 class GlobalObject;
+class XPathResult;
 
 /**
  * A class for evaluating an XPath expression string
  */
 class XPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator
 {
 public:
     XPathEvaluator(nsIDocument* aDocument = nullptr);
@@ -45,20 +46,21 @@ public:
     static already_AddRefed<XPathEvaluator>
         Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
     already_AddRefed<nsIDOMXPathExpression>
         CreateExpression(const nsAString& aExpression,
                          nsIDOMXPathNSResolver* aResolver,
                          ErrorResult& rv);
     already_AddRefed<nsIDOMXPathNSResolver>
         CreateNSResolver(nsINode* aNodeResolver, ErrorResult& rv);
-    already_AddRefed<nsISupports>
-        Evaluate(const nsAString& aExpression, nsINode* aContextNode,
-                 nsIDOMXPathNSResolver* aResolver, uint16_t aType,
-                 nsISupports* aResult, ErrorResult& rv);
+    already_AddRefed<XPathResult>
+        Evaluate(JSContext* aCx, const nsAString& aExpression,
+                 nsINode* aContextNode, nsIDOMXPathNSResolver* aResolver,
+                 uint16_t aType, JS::Handle<JSObject*> aResult,
+                 ErrorResult& rv);
 private:
     nsWeakPtr mDocument;
     nsRefPtr<txResultRecycler> mRecycler;
 };
 
 inline nsISupports*
 ToSupports(XPathEvaluator* e)
 {
rename from dom/xslt/xpath/nsXPathResult.cpp
rename to dom/xslt/xpath/XPathResult.cpp
--- a/dom/xslt/xpath/nsXPathResult.cpp
+++ b/dom/xslt/xpath/XPathResult.cpp
@@ -1,267 +1,184 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "nsXPathResult.h"
+#include "XPathResult.h"
 #include "txExprResult.h"
 #include "txNodeSet.h"
 #include "nsError.h"
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/Element.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMDocument.h"
 #include "nsDOMString.h"
 #include "txXPathTreeWalker.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/dom/XPathResultBinding.h"
 
-using namespace mozilla::dom;
+namespace mozilla {
+namespace dom {
 
-nsXPathResult::nsXPathResult() : mDocument(nullptr),
-                                 mCurrentPos(0),
-                                 mResultType(ANY_TYPE),
-                                 mInvalidIteratorState(true),
-                                 mBooleanResult(false),
-                                 mNumberResult(0)
+XPathResult::XPathResult(nsINode* aParent)
+    : mParent(aParent),
+      mDocument(nullptr),
+      mCurrentPos(0),
+      mResultType(ANY_TYPE),
+      mInvalidIteratorState(true),
+      mBooleanResult(false),
+      mNumberResult(0)
 {
+    SetIsDOMBinding();
 }
 
-nsXPathResult::nsXPathResult(const nsXPathResult &aResult)
-    : mResult(aResult.mResult),
+XPathResult::XPathResult(const XPathResult &aResult)
+    : mParent(aResult.mParent),
+      mResult(aResult.mResult),
       mResultNodes(aResult.mResultNodes),
       mDocument(aResult.mDocument),
+      mContextNode(aResult.mContextNode),
       mCurrentPos(0),
       mResultType(aResult.mResultType),
-      mContextNode(aResult.mContextNode),
       mInvalidIteratorState(aResult.mInvalidIteratorState)
 {
+    SetIsDOMBinding();
     if (mDocument) {
         mDocument->AddMutationObserver(this);
     }
 }
 
-nsXPathResult::~nsXPathResult()
+XPathResult::~XPathResult()
 {
     RemoveObserver();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXPathResult)
+NS_IMPL_CYCLE_COLLECTION_CLASS(XPathResult)
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXPathResult)
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(XPathResult)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPathResult)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+    NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
     {
         tmp->RemoveObserver();
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXPathResult)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPathResult)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResultNodes)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXPathResult)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXPathResult)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(XPathResult)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(XPathResult)
 
-DOMCI_DATA(XPathResult, nsXPathResult)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXPathResult)
-    NS_INTERFACE_MAP_ENTRY(nsIDOMXPathResult)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPathResult)
+    NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
     NS_INTERFACE_MAP_ENTRY(nsIXPathResult)
-    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathResult)
-    NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XPathResult)
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPathResult)
 NS_INTERFACE_MAP_END
 
+JSObject*
+XPathResult::WrapObject(JSContext* aCx)
+{
+    return XPathResultBinding::Wrap(aCx, this);
+}
+
 void
-nsXPathResult::RemoveObserver()
+XPathResult::RemoveObserver()
 {
     if (mDocument) {
         mDocument->RemoveMutationObserver(this);
     }
 }
 
-NS_IMETHODIMP
-nsXPathResult::GetResultType(uint16_t *aResultType)
-{
-    *aResultType = mResultType;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::GetNumberValue(double *aNumberValue)
-{
-    if (mResultType != NUMBER_TYPE) {
-        return NS_ERROR_DOM_TYPE_ERR;
-    }
-
-    *aNumberValue = mNumberResult;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::GetStringValue(nsAString &aStringValue)
-{
-    if (mResultType != STRING_TYPE) {
-        return NS_ERROR_DOM_TYPE_ERR;
-    }
-
-    aStringValue = mStringResult;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::GetBooleanValue(bool *aBooleanValue)
-{
-    if (mResultType != BOOLEAN_TYPE) {
-        return NS_ERROR_DOM_TYPE_ERR;
-    }
-
-    *aBooleanValue = mBooleanResult;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::GetSingleNodeValue(nsIDOMNode **aSingleNodeValue)
-{
-    if (!isNode()) {
-        return NS_ERROR_DOM_TYPE_ERR;
-    }
-
-    if (mResultNodes.Count() > 0) {
-        NS_ADDREF(*aSingleNodeValue = mResultNodes[0]);
-    }
-    else {
-        *aSingleNodeValue = nullptr;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::GetInvalidIteratorState(bool *aInvalidIteratorState)
-{
-    *aInvalidIteratorState = isIterator() && mInvalidIteratorState;
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::GetSnapshotLength(uint32_t *aSnapshotLength)
-{
-    if (!isSnapshot()) {
-        return NS_ERROR_DOM_TYPE_ERR;
-    }
-
-    *aSnapshotLength = (uint32_t)mResultNodes.Count();
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::IterateNext(nsIDOMNode **aResult)
+nsINode*
+XPathResult::IterateNext(ErrorResult& aRv)
 {
     if (!isIterator()) {
-        return NS_ERROR_DOM_TYPE_ERR;
+        aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+        return nullptr;
     }
 
     if (mDocument) {
         mDocument->FlushPendingNotifications(Flush_Content);
     }
 
     if (mInvalidIteratorState) {
-        return NS_ERROR_DOM_INVALID_STATE_ERR;
-    }
-
-    if (mCurrentPos < (uint32_t)mResultNodes.Count()) {
-        NS_ADDREF(*aResult = mResultNodes[mCurrentPos++]);
-    }
-    else {
-        *aResult = nullptr;
+        aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+        return nullptr;
     }
 
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPathResult::SnapshotItem(uint32_t aIndex, nsIDOMNode **aResult)
-{
-    if (!isSnapshot()) {
-        return NS_ERROR_DOM_TYPE_ERR;
-    }
-
-    NS_IF_ADDREF(*aResult = mResultNodes.SafeObjectAt(aIndex));
-
-    return NS_OK;
+    return mResultNodes.SafeObjectAt(mCurrentPos++);
 }
 
 void
-nsXPathResult::NodeWillBeDestroyed(const nsINode* aNode)
+XPathResult::NodeWillBeDestroyed(const nsINode* aNode)
 {
     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
     // Set to null to avoid unregistring unnecessarily
     mDocument = nullptr;
     Invalidate(aNode->IsNodeOfType(nsINode::eCONTENT) ?
                static_cast<const nsIContent*>(aNode) : nullptr);
 }
 
 void
-nsXPathResult::CharacterDataChanged(nsIDocument* aDocument,
-                                    nsIContent *aContent,
-                                    CharacterDataChangeInfo* aInfo)
+XPathResult::CharacterDataChanged(nsIDocument* aDocument,
+                                  nsIContent *aContent,
+                                  CharacterDataChangeInfo* aInfo)
 {
     Invalidate(aContent);
 }
 
 void
-nsXPathResult::AttributeChanged(nsIDocument* aDocument,
-                                Element* aElement,
-                                int32_t aNameSpaceID,
-                                nsIAtom* aAttribute,
-                                int32_t aModType)
+XPathResult::AttributeChanged(nsIDocument* aDocument,
+                              Element* aElement,
+                              int32_t aNameSpaceID,
+                              nsIAtom* aAttribute,
+                              int32_t aModType)
 {
     Invalidate(aElement);
 }
 
 void
-nsXPathResult::ContentAppended(nsIDocument* aDocument,
-                               nsIContent* aContainer,
-                               nsIContent* aFirstNewContent,
-                               int32_t aNewIndexInContainer)
+XPathResult::ContentAppended(nsIDocument* aDocument,
+                             nsIContent* aContainer,
+                             nsIContent* aFirstNewContent,
+                             int32_t aNewIndexInContainer)
 {
     Invalidate(aContainer);
 }
 
 void
-nsXPathResult::ContentInserted(nsIDocument* aDocument,
-                               nsIContent* aContainer,
-                               nsIContent* aChild,
-                               int32_t aIndexInContainer)
+XPathResult::ContentInserted(nsIDocument* aDocument,
+                             nsIContent* aContainer,
+                             nsIContent* aChild,
+                             int32_t aIndexInContainer)
 {
     Invalidate(aContainer);
 }
 
 void
-nsXPathResult::ContentRemoved(nsIDocument* aDocument,
-                              nsIContent* aContainer,
-                              nsIContent* aChild,
-                              int32_t aIndexInContainer,
-                              nsIContent* aPreviousSibling)
+XPathResult::ContentRemoved(nsIDocument* aDocument,
+                            nsIContent* aContainer,
+                            nsIContent* aChild,
+                            int32_t aIndexInContainer,
+                            nsIContent* aPreviousSibling)
 {
     Invalidate(aContainer);
 }
 
 nsresult
-nsXPathResult::SetExprResult(txAExprResult* aExprResult, uint16_t aResultType,
-                             nsINode* aContextNode)
+XPathResult::SetExprResult(txAExprResult* aExprResult, uint16_t aResultType,
+                           nsINode* aContextNode)
 {
     MOZ_ASSERT(aExprResult);
 
     if ((isSnapshot(aResultType) || isIterator(aResultType) ||
          isNode(aResultType)) &&
         aExprResult->getResultType() != txAExprResult::NODESET) {
         // The DOM spec doesn't really say what should happen when reusing an
         // XPathResult and an error is thrown. Let's not touch the XPathResult
@@ -300,59 +217,48 @@ nsXPathResult::SetExprResult(txAExprResu
         default:
         {
             MOZ_ASSERT(isNode() || isIterator() || isSnapshot());
         }
     }
 
     if (aExprResult->getResultType() == txAExprResult::NODESET) {
         txNodeSet *nodeSet = static_cast<txNodeSet*>(aExprResult);
-        nsCOMPtr<nsIDOMNode> node;
         int32_t i, count = nodeSet->size();
         for (i = 0; i < count; ++i) {
-            txXPathNativeNode::getNode(nodeSet->get(i), getter_AddRefs(node));
-            if (node) {
-                mResultNodes.AppendObject(node);
-            }
+            nsINode* node = txXPathNativeNode::getNode(nodeSet->get(i));
+            mResultNodes.AppendObject(node);
         }
 
         if (count > 0) {
             mResult = nullptr;
         }
     }
 
     if (!isIterator()) {
         return NS_OK;
     }
 
     mInvalidIteratorState = false;
 
     if (mResultNodes.Count() > 0) {
         // If we support the document() function in DOM-XPath we need to
         // observe all documents that we have resultnodes in.
-        nsCOMPtr<nsIDOMDocument> document;
-        mResultNodes[0]->GetOwnerDocument(getter_AddRefs(document));
-        if (document) {
-            mDocument = do_QueryInterface(document);
-        }
-        else {
-            mDocument = do_QueryInterface(mResultNodes[0]);
-        }
-
+        mDocument = mResultNodes[0]->OwnerDoc();
         NS_ASSERTION(mDocument, "We need a document!");
         if (mDocument) {
             mDocument->AddMutationObserver(this);
         }
     }
 
     return NS_OK;
 }
 
 void
-nsXPathResult::Invalidate(const nsIContent* aChangeRoot)
+XPathResult::Invalidate(const nsIContent* aChangeRoot)
 {
     nsCOMPtr<nsINode> contextNode = do_QueryReferent(mContextNode);
     if (contextNode && aChangeRoot && aChangeRoot->GetBindingParent()) {
         // If context node is in anonymous content, changes to
         // non-anonymous content need to invalidate the XPathResult. If
         // the changes are happening in a different anonymous trees, no
         // invalidation should happen.
         nsIContent* ctxBindingParent = nullptr;
@@ -376,17 +282,17 @@ nsXPathResult::Invalidate(const nsIConte
     // Make sure nulling out mDocument is the last thing we do.
     if (mDocument) {
         mDocument->RemoveMutationObserver(this);
         mDocument = nullptr;
     }
 }
 
 nsresult
-nsXPathResult::GetExprResult(txAExprResult** aExprResult)
+XPathResult::GetExprResult(txAExprResult** aExprResult)
 {
     if (isIterator() && mInvalidIteratorState) {
         return NS_ERROR_DOM_INVALID_STATE_ERR;
     }
 
     if (mResult) {
         NS_ADDREF(*aExprResult = mResult);
 
@@ -413,25 +319,23 @@ nsXPathResult::GetExprResult(txAExprResu
     }
 
     NS_ADDREF(*aExprResult = nodeSet);
 
     return NS_OK;
 }
 
 nsresult
-nsXPathResult::Clone(nsIXPathResult **aResult)
+XPathResult::Clone(nsIXPathResult **aResult)
 {
     *aResult = nullptr;
 
     if (isIterator() && mInvalidIteratorState) {
         return NS_ERROR_DOM_INVALID_STATE_ERR;
     }
 
-    nsCOMPtr<nsIXPathResult> result = new nsXPathResult(*this);
-    if (!result) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    result.swap(*aResult);
+    NS_ADDREF(*aResult = new XPathResult(*this));
 
     return NS_OK;
 }
+
+} // namespace dom
+} // namespace mozilla
rename from dom/xslt/xpath/nsXPathResult.h
rename to dom/xslt/xpath/XPathResult.h
--- a/dom/xslt/xpath/nsXPathResult.h
+++ b/dom/xslt/xpath/XPathResult.h
@@ -1,26 +1,30 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 nsXPathResult_h__
-#define nsXPathResult_h__
+#ifndef mozilla_dom_XPathResult_h
+#define mozilla_dom_XPathResult_h
 
-#include "txExprResult.h"
-#include "nsIDOMXPathResult.h"
 #include "nsStubMutationObserver.h"
+#include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
+#include "nsString.h"
+#include "nsWrapperCache.h"
+#include "nsINode.h"
 
 class nsIDocument;
+class txAExprResult;
 
 // {662f2c9a-c7cd-4cab-9349-e733df5a838c}
 #define NS_IXPATHRESULT_IID \
 { 0x662f2c9a, 0xc7cd, 0x4cab, {0x93, 0x49, 0xe7, 0x33, 0xdf, 0x5a, 0x83, 0x8c }}
 
 class nsIXPathResult : public nsISupports
 {
 public:
@@ -29,44 +33,131 @@ public:
                                    uint16_t aResultType,
                                    nsINode* aContextNode) = 0;
     virtual nsresult GetExprResult(txAExprResult **aExprResult) = 0;
     virtual nsresult Clone(nsIXPathResult **aResult) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathResult, NS_IXPATHRESULT_IID)
 
+namespace mozilla {
+namespace dom {
+
 /**
  * A class for evaluating an XPath expression string
  */
-class nsXPathResult MOZ_FINAL : public nsIDOMXPathResult,
-                                public nsStubMutationObserver,
-                                public nsIXPathResult
+class XPathResult MOZ_FINAL : public nsIXPathResult,
+                              public nsStubMutationObserver,
+                              public nsWrapperCache
 {
 public:
-    nsXPathResult();
-    nsXPathResult(const nsXPathResult &aResult);
-    ~nsXPathResult();
+    XPathResult(nsINode* aParent);
+    XPathResult(const XPathResult &aResult);
+    ~XPathResult();
+
+    enum {
+        ANY_TYPE = 0U,
+        NUMBER_TYPE = 1U,
+        STRING_TYPE = 2U,
+        BOOLEAN_TYPE = 3U,
+        UNORDERED_NODE_ITERATOR_TYPE = 4U,
+        ORDERED_NODE_ITERATOR_TYPE = 5U,
+        UNORDERED_NODE_SNAPSHOT_TYPE = 6U,
+        ORDERED_NODE_SNAPSHOT_TYPE = 7U,
+        ANY_UNORDERED_NODE_TYPE = 8U,
+        FIRST_ORDERED_NODE_TYPE = 9U
+    };
 
     // nsISupports interface
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXPathResult, nsIDOMXPathResult)
+    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(XPathResult,
+                                                           nsIXPathResult)
+
+    static XPathResult* FromSupports(nsISupports* aSupports)
+    {
+        return static_cast<XPathResult*>(static_cast<nsIXPathResult*>(aSupports));
+    }
+
+    virtual JSObject* WrapObject(JSContext* aCx);
+    nsINode* GetParentObject() const
+    {
+        return mParent;
+    }
+    uint16_t ResultType() const
+    {
+        return mResultType;
+    }
+    double GetNumberValue(ErrorResult& aRv) const
+    {
+        if (mResultType != NUMBER_TYPE) {
+            aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+            return 0;
+        }
+
+        return mNumberResult;
+    }
+    void GetStringValue(nsAString &aStringValue, ErrorResult& aRv) const
+    {
+        if (mResultType != STRING_TYPE) {
+            aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+            return;
+        }
 
-    // nsIDOMXPathResult interface
-    NS_DECL_NSIDOMXPATHRESULT
+        aStringValue = mStringResult;
+    }
+    bool GetBooleanValue(ErrorResult& aRv) const
+    {
+        if (mResultType != BOOLEAN_TYPE) {
+            aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+            return false;
+        }
+
+        return mBooleanResult;
+    }
+    nsINode* GetSingleNodeValue(ErrorResult& aRv) const
+    {
+        if (!isNode()) {
+            aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+            return nullptr;
+       }
+
+        return mResultNodes.SafeObjectAt(0);
+    }
+    bool InvalidIteratorState() const
+    {
+        return isIterator() && mInvalidIteratorState;
+    }
+    uint32_t GetSnapshotLength(ErrorResult& aRv) const
+    {
+        if (!isSnapshot()) {
+            aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+            return 0;
+        }
+
+        return (uint32_t)mResultNodes.Count();
+    }
+    nsINode* IterateNext(ErrorResult& aRv);
+    nsINode* SnapshotItem(uint32_t aIndex, ErrorResult& aRv) const
+    {
+        if (!isSnapshot()) {
+            aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+            return nullptr;
+        }
+
+        return mResultNodes.SafeObjectAt(aIndex);
+    }
 
     // nsIMutationObserver interface
     NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
-    // nsIXPathResult interface
     nsresult SetExprResult(txAExprResult *aExprResult, uint16_t aResultType,
                            nsINode* aContextNode) MOZ_OVERRIDE;
     nsresult GetExprResult(txAExprResult **aExprResult) MOZ_OVERRIDE;
     nsresult Clone(nsIXPathResult **aResult) MOZ_OVERRIDE;
     void RemoveObserver();
 private:
     static bool isSnapshot(uint16_t aResultType)
     {
@@ -93,21 +184,25 @@ private:
     }
     bool isNode() const
     {
         return isNode(mResultType);
     }
 
     void Invalidate(const nsIContent* aChangeRoot);
 
+    nsCOMPtr<nsINode> mParent;
     nsRefPtr<txAExprResult> mResult;
-    nsCOMArray<nsIDOMNode> mResultNodes;
+    nsCOMArray<nsINode> mResultNodes;
     nsCOMPtr<nsIDocument> mDocument;
+    nsWeakPtr mContextNode;
     uint32_t mCurrentPos;
     uint16_t mResultType;
-    nsWeakPtr mContextNode;
     bool mInvalidIteratorState;
     bool mBooleanResult;
     double mNumberResult;
     nsString mStringResult;
 };
 
-#endif
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_XPathResult_h */
--- a/dom/xslt/xpath/moz.build
+++ b/dom/xslt/xpath/moz.build
@@ -1,22 +1,22 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS.mozilla.dom += [
     'XPathEvaluator.h',
+    'XPathResult.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsXPathExpression.cpp',
     'nsXPathNSResolver.cpp',
-    'nsXPathResult.cpp',
     'txBooleanExpr.cpp',
     'txBooleanResult.cpp',
     'txCoreFunctionCall.cpp',
     'txErrorExpr.cpp',
     'txExpr.cpp',
     'txExprLexer.cpp',
     'txExprParser.cpp',
     'txFilterExpr.cpp',
@@ -42,16 +42,17 @@ UNIFIED_SOURCES += [
     'txStringResult.cpp',
     'txUnaryExpr.cpp',
     'txUnionExpr.cpp',
     'txUnionNodeTest.cpp',
     'txVariableRefExpr.cpp',
     'txXPathOptimizer.cpp',
     'txXPCOMExtensionFunction.cpp',
     'XPathEvaluator.cpp',
+    'XPathResult.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../base',
     '../xml',
     '../xslt',
--- a/dom/xslt/xpath/nsXPathExpression.cpp
+++ b/dom/xslt/xpath/nsXPathExpression.cpp
@@ -6,20 +6,21 @@
 #include "mozilla/Move.h"
 #include "nsXPathExpression.h"
 #include "txExpr.h"
 #include "txExprResult.h"
 #include "nsError.h"
 #include "nsIDOMCharacterData.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIDOMDocument.h"
-#include "nsXPathResult.h"
+#include "XPathResult.h"
 #include "txURIUtils.h"
 #include "txXPathTreeWalker.h"
 
+using namespace mozilla::dom;
 using mozilla::Move;
 
 NS_IMPL_CYCLE_COLLECTION(nsXPathExpression, mDocument)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXPathExpression)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXPathExpression)
 
 DOMCI_DATA(XPathExpression, nsXPathExpression)
@@ -110,43 +111,42 @@ nsXPathExpression::EvaluateWithContext(n
 
     EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
                              mRecycler);
     nsRefPtr<txAExprResult> exprResult;
     nsresult rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
     NS_ENSURE_SUCCESS(rv, rv);
 
     uint16_t resultType = aType;
-    if (aType == nsIDOMXPathResult::ANY_TYPE) {
+    if (aType == XPathResult::ANY_TYPE) {
         short exprResultType = exprResult->getResultType();
         switch (exprResultType) {
             case txAExprResult::NUMBER:
-                resultType = nsIDOMXPathResult::NUMBER_TYPE;
+                resultType = XPathResult::NUMBER_TYPE;
                 break;
             case txAExprResult::STRING:
-                resultType = nsIDOMXPathResult::STRING_TYPE;
+                resultType = XPathResult::STRING_TYPE;
                 break;
             case txAExprResult::BOOLEAN:
-                resultType = nsIDOMXPathResult::BOOLEAN_TYPE;
+                resultType = XPathResult::BOOLEAN_TYPE;
                 break;
             case txAExprResult::NODESET:
-                resultType = nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE;
+                resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE;
                 break;
             case txAExprResult::RESULT_TREE_FRAGMENT:
                 NS_ERROR("Can't return a tree fragment!");
                 return NS_ERROR_FAILURE;
         }
     }
 
     // We need a result object and it must be our implementation.
     nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(aInResult);
     if (!xpathResult) {
         // Either no aInResult or not one of ours.
-        xpathResult = new nsXPathResult();
-        NS_ENSURE_TRUE(xpathResult, NS_ERROR_OUT_OF_MEMORY);
+        xpathResult = new XPathResult(context);
     }
     rv = xpathResult->SetExprResult(exprResult, resultType, context);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return CallQueryInterface(xpathResult, aResult);
 }
 
 /*
--- a/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
+++ b/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
@@ -20,17 +20,17 @@
 #include "nsUnicharUtils.h"
 #include "nsAttrName.h"
 #include "nsTArray.h"
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/Element.h"
 #include <stdint.h>
 #include <algorithm>
 
-using mozilla::dom::Attr;
+using namespace mozilla::dom;
 
 const uint32_t kUnknownIndex = uint32_t(-1);
 
 txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
     : mPosition(aOther.mPosition),
       mCurrentIndex(aOther.mCurrentIndex)
 {
 }
@@ -678,21 +678,19 @@ txXPathNativeNode::createXPathNode(nsICo
 {
     nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(aContent) : nullptr;
 
     return new txXPathNode(aContent, txXPathNode::eContent, root);
 }
 
 /* static */
 txXPathNode*
-txXPathNativeNode::createXPathNode(nsIDOMNode* aNode, bool aKeepRootAlive)
+txXPathNativeNode::createXPathNode(nsINode* aNode, bool aKeepRootAlive)
 {
-    uint16_t nodeType;
-    aNode->GetNodeType(&nodeType);
-
+    uint16_t nodeType = aNode->NodeType();
     if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
         nsCOMPtr<nsIAttribute> attr = do_QueryInterface(aNode);
         NS_ASSERTION(attr, "doesn't implement nsIAttribute");
 
         mozilla::dom::NodeInfo *nodeInfo = attr->NodeInfo();
         mozilla::dom::Element* parent =
           static_cast<Attr*>(attr.get())->GetElement();
         if (!parent) {
@@ -709,61 +707,57 @@ txXPathNativeNode::createXPathNode(nsIDO
             }
         }
 
         NS_ERROR("Couldn't find the attribute in its parent!");
 
         return nullptr;
     }
 
-    nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
     uint32_t index;
-    nsINode* root = aKeepRootAlive ? node.get() : nullptr;
+    nsINode* root = aKeepRootAlive ? aNode : nullptr;
 
     if (nodeType == nsIDOMNode::DOCUMENT_NODE) {
         index = txXPathNode::eDocument;
     }
     else {
         index = txXPathNode::eContent;
         if (root) {
             root = txXPathNode::RootOf(root);
         }
     }
 
-    return new txXPathNode(node, index, root);
+    return new txXPathNode(aNode, index, root);
 }
 
 /* static */
 txXPathNode*
 txXPathNativeNode::createXPathNode(nsIDOMDocument* aDocument)
 {
     nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
     return new txXPathNode(document);
 }
 
 /* static */
-nsresult
-txXPathNativeNode::getNode(const txXPathNode& aNode, nsIDOMNode** aResult)
+nsINode*
+txXPathNativeNode::getNode(const txXPathNode& aNode)
 {
     if (!aNode.isAttribute()) {
-        return CallQueryInterface(aNode.mNode, aResult);
+        return aNode.mNode;
     }
 
     const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
 
     nsAutoString namespaceURI;
     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(name->NamespaceID(), namespaceURI);
 
-    nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode.mNode);
-    nsCOMPtr<nsIDOMAttr> attr;
-    element->GetAttributeNodeNS(namespaceURI,
-                                nsDependentAtomString(name->LocalName()),
-                                getter_AddRefs(attr));
-
-    return CallQueryInterface(attr, aResult);
+    nsCOMPtr<Element> element = do_QueryInterface(aNode.mNode);
+    nsDOMAttributeMap* map = element->Attributes();
+    return map->GetNamedItemNS(namespaceURI,
+                               nsDependentAtomString(name->LocalName()));
 }
 
 /* static */
 nsIContent*
 txXPathNativeNode::getContent(const txXPathNode& aNode)
 {
     NS_ASSERTION(aNode.isContent(),
                  "Only call getContent on nsIContent wrappers!");
--- a/dom/xslt/xpath/txXPathTreeWalker.h
+++ b/dom/xslt/xpath/txXPathTreeWalker.h
@@ -112,22 +112,32 @@ public:
       nsIContent* content = aNode.Content();
       return content->IsHTML() && content->IsInHTMLDocument();
     }
 };
 
 class txXPathNativeNode
 {
 public:
+    static txXPathNode* createXPathNode(nsINode* aNode,
+                                        bool aKeepRootAlive = false);
     static txXPathNode* createXPathNode(nsIDOMNode* aNode,
-                                        bool aKeepRootAlive = false);
+                                        bool aKeepRootAlive = false)
+    {
+        nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+        return createXPathNode(node, aKeepRootAlive);
+    }
     static txXPathNode* createXPathNode(nsIContent* aContent,
                                         bool aKeepRootAlive = false);
     static txXPathNode* createXPathNode(nsIDOMDocument* aDocument);
-    static nsresult getNode(const txXPathNode& aNode, nsIDOMNode** aResult);
+    static nsINode* getNode(const txXPathNode& aNode);
+    static nsresult getNode(const txXPathNode& aNode, nsIDOMNode** aResult)
+    {
+        return CallQueryInterface(getNode(aNode), aResult);
+    }
     static nsIContent* getContent(const txXPathNode& aNode);
     static nsIDocument* getDocument(const txXPathNode& aNode);
     static void addRef(const txXPathNode& aNode)
     {
         NS_ADDREF(aNode.mNode);
     }
     static void release(const txXPathNode& aNode)
     {
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -18,37 +18,38 @@
 #include "nsContentCID.h"
 #include "nsNetUtil.h"
 #include "nsUnicharUtils.h"
 #include "nsGkAtoms.h"
 #include "txLog.h"
 #include "nsIConsoleService.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsNameSpaceManager.h"
-#include "nsCSSStyleSheet.h"
 #include "txStringUtils.h"
 #include "txURIUtils.h"
 #include "nsIHTMLDocument.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "nsIDocumentTransformer.h"
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "nsContentUtils.h"
 #include "txXMLUtils.h"
 #include "nsContentSink.h"
 #include "nsINode.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsError.h"
 #include "nsIFrame.h"
 #include <algorithm>
 #include "nsTextNode.h"
 #include "mozilla/dom/Comment.h"
 #include "mozilla/dom/ProcessingInstruction.h"
 
+using namespace mozilla;
 using namespace mozilla::dom;
 
 #define TX_ENSURE_CURRENTNODE                           \
     NS_ASSERTION(mCurrentNode, "mCurrentNode is nullptr"); \
     if (!mCurrentNode)                                  \
         return NS_ERROR_UNEXPECTED
 
 txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
@@ -976,17 +977,17 @@ txTransformNotifier::ScriptEvaluated(nsr
     if (mScriptElements.RemoveObject(aElement)) {
         SignalTransformEnd();
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-txTransformNotifier::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
+txTransformNotifier::StyleSheetLoaded(CSSStyleSheet* aSheet,
                                       bool aWasAlternate,
                                       nsresult aStatus)
 {
     if (mPendingStylesheetCount == 0) {
         // We weren't waiting on this stylesheet anyway.  This can happen if
         // SignalTransformEnd got called with an error aResult.  See
         // http://bugzilla.mozilla.org/show_bug.cgi?id=215465.
         return NS_OK;
--- a/dom/xslt/xslt/txMozillaXMLOutput.h
+++ b/dom/xslt/xslt/txMozillaXMLOutput.h
@@ -33,17 +33,17 @@ class txTransformNotifier MOZ_FINAL : pu
 {
 public:
     txTransformNotifier();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCRIPTLOADEROBSERVER
     
     // nsICSSLoaderObserver
-    NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet* aSheet,
+    NS_IMETHOD StyleSheetLoaded(mozilla::CSSStyleSheet* aSheet,
                                 bool aWasAlternate,
                                 nsresult aStatus) MOZ_OVERRIDE;
 
     void Init(nsITransformObserver* aObserver);
     nsresult AddScriptElement(nsIScriptElement* aElement);
     void AddPendingStylesheet();
     void OnTransformEnd(nsresult aResult = NS_OK);
     void OnTransformStart();
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -15,17 +15,17 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMNodeList.h"
 #include "nsIIOService.h"
 #include "nsILoadGroup.h"
 #include "nsIStringBundle.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
-#include "nsXPathResult.h"
+#include "XPathResult.h"
 #include "txExecutionState.h"
 #include "txMozillaTextOutput.h"
 #include "txMozillaXMLOutput.h"
 #include "txURIUtils.h"
 #include "txXMLUtils.h"
 #include "txUnknownHandler.h"
 #include "txXSLTProcessor.h"
 #include "nsIPrincipal.h"
@@ -804,17 +804,17 @@ txMozillaXSLTProcessor::SetParameter(con
                         NS_ENSURE_SUCCESS(rv, rv);
 
                         if (!nsContentUtils::CanCallerAccess(node)) {
                             return NS_ERROR_DOM_SECURITY_ERR;
                         }
                     }
                 }
 
-                // Clone the nsXPathResult so that mutations don't affect this
+                // Clone the XPathResult so that mutations don't affect this
                 // variable.
                 nsCOMPtr<nsIXPathResult> clone;
                 rv = xpathResult->Clone(getter_AddRefs(clone));
                 NS_ENSURE_SUCCESS(rv, rv);
 
                 nsCOMPtr<nsIWritableVariant> variant =
                     do_CreateInstance("@mozilla.org/variant;1", &rv);
                 NS_ENSURE_SUCCESS(rv, rv);
--- a/editor/idl/nsIEditorStyleSheets.idl
+++ b/editor/idl/nsIEditorStyleSheets.idl
@@ -1,20 +1,22 @@
 /* -*- 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 "nsISupports.idl"
 
 %{C++
-class nsCSSStyleSheet;
+namespace mozilla {
+class CSSStyleSheet;
+} // namespace mozilla
 %}
 
-[ptr] native nsCSSStyleSheet(nsCSSStyleSheet);
+[ptr] native CSSStyleSheet(mozilla::CSSStyleSheet);
 
 [scriptable, uuid(4805e682-49b9-11d3-9ce4-ed60bd6cb5bc)]
 
 interface nsIEditorStyleSheets : nsISupports
 {
   /** Load and apply the style sheet, specified by aURL, to the
     * editor's document, replacing the last style sheet added (if any).
     * This is always asynchronous, and may cause network I/O.
@@ -70,22 +72,22 @@ interface nsIEditorStyleSheets : nsISupp
   /** Enable or disable the given style sheet from the editor's document
     * This is always synchronous
     *
     * @param aURL  The style sheet to be enabled or disabled
     * @param aEnable true to enable, or false to disable the style sheet
     */
   void enableStyleSheet(in AString aURL, in boolean aEnable);
 
-  /** Get the nsCSSStyleSheet associated with the given URL.
+  /** Get the CSSStyleSheet associated with the given URL.
     *
     * @param aURL         The style sheet's URL
     * @return             the style sheet
     */
-  [noscript] nsCSSStyleSheet getStyleSheetForURL(in AString aURL);
+  [noscript] CSSStyleSheet getStyleSheetForURL(in AString aURL);
 
-  /** Get the URL associated with the given nsCSSStyleSheet.
+  /** Get the URL associated with the given CSSStyleSheet.
     *
     * @param aStyleSheet  The style sheet
     * @return             the style sheet's URL
     */
-  [noscript] AString getURLForStyleSheet(in nsCSSStyleSheet aStyleSheet);
+  [noscript] AString getURLForStyleSheet(in CSSStyleSheet aStyleSheet);
 };
--- a/editor/libeditor/base/nsEditPropertyAtomList.h
+++ b/editor/libeditor/base/nsEditPropertyAtomList.h
@@ -126,16 +126,21 @@ EDITOR_ATOM(nav, "nav")
 EDITOR_ATOM(noscript, "noscript")
 EDITOR_ATOM(object, "object")
 EDITOR_ATOM(ol, "ol")
 EDITOR_ATOM(output, "output")
 EDITOR_ATOM(p, "p")
 EDITOR_ATOM(pre, "pre")
 EDITOR_ATOM(progress, "progress")
 EDITOR_ATOM(q, "q")
+EDITOR_ATOM(rb, "rb")
+EDITOR_ATOM(rp, "rp")
+EDITOR_ATOM(rt, "rt")
+EDITOR_ATOM(rtc, "rtc")
+EDITOR_ATOM(ruby, "ruby")
 EDITOR_ATOM(samp, "samp")
 EDITOR_ATOM(script, "script")
 EDITOR_ATOM(section, "section")
 EDITOR_ATOM(select, "select")
 EDITOR_ATOM(size, "size")
 EDITOR_ATOM(small, "small")
 EDITOR_ATOM(span, "span")
 EDITOR_ATOM(s, "s")
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -4421,33 +4421,33 @@ nsEditor::CreateTxnForIMEText(const nsAS
     txn.forget(aTxn);
   }
 
   return rv;
 }
 
 
 NS_IMETHODIMP 
-nsEditor::CreateTxnForAddStyleSheet(nsCSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn)
+nsEditor::CreateTxnForAddStyleSheet(CSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn)
 {
   nsRefPtr<AddStyleSheetTxn> txn = new AddStyleSheetTxn();
 
   nsresult rv = txn->Init(this, aSheet);
   if (NS_SUCCEEDED(rv))
   {
     txn.forget(aTxn);
   }
 
   return rv;
 }
 
 
 
 NS_IMETHODIMP 
-nsEditor::CreateTxnForRemoveStyleSheet(nsCSSStyleSheet* aSheet, RemoveStyleSheetTxn* *aTxn)
+nsEditor::CreateTxnForRemoveStyleSheet(CSSStyleSheet* aSheet, RemoveStyleSheetTxn* *aTxn)
 {
   nsRefPtr<RemoveStyleSheetTxn> txn = new RemoveStyleSheetTxn();
 
   nsresult rv = txn->Init(this, aSheet);
   if (NS_SUCCEEDED(rv))
   {
     txn.forget(aTxn);
   }
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -34,17 +34,16 @@ class DeleteNodeTxn;
 class DeleteTextTxn;
 class EditAggregateTxn;
 class IMETextTxn;
 class InsertElementTxn;
 class InsertTextTxn;
 class JoinElementTxn;
 class RemoveStyleSheetTxn;
 class SplitElementTxn;
-class nsCSSStyleSheet;
 class nsIAtom;
 class nsIContent;
 class nsIDOMCharacterData;
 class nsIDOMDataTransfer;
 class nsIDOMDocument;
 class nsIDOMElement;
 class nsIDOMEvent;
 class nsIDOMEventListener;
@@ -63,16 +62,17 @@ class nsISelection;
 class nsISupports;
 class nsITransaction;
 class nsIWidget;
 class nsRange;
 class nsString;
 class nsTransactionManager;
 
 namespace mozilla {
+class CSSStyleSheet;
 class ErrorResult;
 class TextComposition;
 
 namespace dom {
 class DataTransfer;
 class Element;
 class EventTarget;
 class Selection;
@@ -316,21 +316,23 @@ protected:
                                     int32_t aOffset,
                                     InsertTextTxn ** aTxn);
 
   NS_IMETHOD CreateTxnForIMEText(const nsAString & aStringToInsert,
                                  IMETextTxn ** aTxn);
 
   /** create a transaction for adding a style sheet
     */
-  NS_IMETHOD CreateTxnForAddStyleSheet(nsCSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn);
+  NS_IMETHOD CreateTxnForAddStyleSheet(mozilla::CSSStyleSheet* aSheet,
+                                       AddStyleSheetTxn* *aTxn);
 
   /** create a transaction for removing a style sheet
     */
-  NS_IMETHOD CreateTxnForRemoveStyleSheet(nsCSSStyleSheet* aSheet, RemoveStyleSheetTxn* *aTxn);
+  NS_IMETHOD CreateTxnForRemoveStyleSheet(mozilla::CSSStyleSheet* aSheet,
+                                          RemoveStyleSheetTxn* *aTxn);
   
   NS_IMETHOD DeleteText(nsIDOMCharacterData *aElement,
                         uint32_t             aOffset,
                         uint32_t             aLength);
 
   inline nsresult DeleteText(mozilla::dom::Text* aText, uint32_t aOffset,
                              uint32_t aLength)
   {
--- a/editor/libeditor/base/nsStyleSheetTxns.cpp
+++ b/editor/libeditor/base/nsStyleSheetTxns.cpp
@@ -3,25 +3,27 @@
  * 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 <stddef.h>                     // for nullptr
 
 #include "nsAString.h"
 #include "nsCOMPtr.h"                   // for nsCOMPtr, do_QueryInterface, etc
-#include "nsCSSStyleSheet.h"            // for nsCSSStyleSheet
+#include "mozilla/CSSStyleSheet.h"      // for mozilla::CSSStyleSheet
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE
 #include "nsError.h"                    // for NS_OK, etc
 #include "nsIDOMDocument.h"             // for nsIDOMDocument
 #include "nsIDocument.h"                // for nsIDocument
 #include "nsIDocumentObserver.h"        // for UPDATE_STYLE
 #include "nsIEditor.h"                  // for nsIEditor
 #include "nsStyleSheetTxns.h"
 
+using namespace mozilla;
+
 class nsIStyleSheet;
 
 static void
 AddStyleSheet(nsIEditor* aEditor, nsIStyleSheet* aSheet)
 {
   nsCOMPtr<nsIDOMDocument> domDoc;
   aEditor->GetDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
@@ -53,17 +55,17 @@ AddStyleSheetTxn::AddStyleSheetTxn()
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(AddStyleSheetTxn, EditTxn,
                                    mSheet)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AddStyleSheetTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
 NS_IMETHODIMP
-AddStyleSheetTxn::Init(nsIEditor *aEditor, nsCSSStyleSheet *aSheet)
+AddStyleSheetTxn::Init(nsIEditor *aEditor, CSSStyleSheet *aSheet)
 {
   NS_ENSURE_TRUE(aEditor && aSheet, NS_ERROR_INVALID_ARG);
 
   mEditor = aEditor;
   mSheet = aSheet;
 
   return NS_OK;
 }
@@ -103,17 +105,17 @@ RemoveStyleSheetTxn::RemoveStyleSheetTxn
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(RemoveStyleSheetTxn, EditTxn,
                                    mSheet)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RemoveStyleSheetTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
 NS_IMETHODIMP
-RemoveStyleSheetTxn::Init(nsIEditor *aEditor, nsCSSStyleSheet *aSheet)
+RemoveStyleSheetTxn::Init(nsIEditor *aEditor, CSSStyleSheet *aSheet)
 {
   NS_ENSURE_TRUE(aEditor && aSheet, NS_ERROR_INVALID_ARG);
 
   mEditor = aEditor;
   mSheet = aSheet;
 
   return NS_OK;
 }
--- a/editor/libeditor/base/nsStyleSheetTxns.h
+++ b/editor/libeditor/base/nsStyleSheetTxns.h
@@ -3,67 +3,67 @@
  * 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 nsStylesheetTxns_h__
 #define nsStylesheetTxns_h__
 
 #include "EditTxn.h"                    // for EditTxn, NS_DECL_EDITTXN
 #include "nsAutoPtr.h"                  // for nsRefPtr
-#include "nsCSSStyleSheet.h"            // for nsCSSStyleSheet
+#include "mozilla/CSSStyleSheet.h"      // for mozilla::CSSStyleSheet
 #include "nsCycleCollectionParticipant.h"
 #include "nsID.h"                       // for REFNSIID
-#include "nsISupportsImpl.h"            // for nsCSSStyleSheet::Release
+#include "nsISupportsImpl.h"            // for CSSStyleSheet::Release
 #include "nscore.h"                     // for NS_IMETHOD
 
 class nsIEditor;
 
 class AddStyleSheetTxn : public EditTxn
 {
 public:
   /** Initialize the transaction.
     * @param aEditor the object providing core editing operations
     * @param aSheet   the stylesheet to add
     */
-  NS_IMETHOD Init(nsIEditor         *aEditor,
-                  nsCSSStyleSheet   *aSheet);
+  NS_IMETHOD Init(nsIEditor* aEditor,
+                  mozilla::CSSStyleSheet* aSheet);
 
   AddStyleSheetTxn();
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AddStyleSheetTxn, EditTxn)
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   NS_DECL_EDITTXN
 
 protected:
 
-  nsIEditor*  mEditor;                  // the editor that created this transaction
-  nsRefPtr<nsCSSStyleSheet>  mSheet;    // the style sheet to add
+  nsIEditor* mEditor;                      // the editor that created this transaction
+  nsRefPtr<mozilla::CSSStyleSheet> mSheet; // the style sheet to add
 
 };
 
 
 class RemoveStyleSheetTxn : public EditTxn
 {
 public:
   /** Initialize the transaction.
     * @param aEditor the object providing core editing operations
     * @param aSheet   the stylesheet to remove
     */
-  NS_IMETHOD Init(nsIEditor         *aEditor,
-                  nsCSSStyleSheet   *aSheet);
+  NS_IMETHOD Init(nsIEditor* aEditor,
+                  mozilla::CSSStyleSheet* aSheet);
 
   RemoveStyleSheetTxn();
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RemoveStyleSheetTxn, EditTxn)
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   NS_DECL_EDITTXN
 
 protected:
 
-  nsIEditor*  mEditor;                  // the editor that created this transaction
-  nsRefPtr<nsCSSStyleSheet>  mSheet;    // the style sheet to remove
+  nsIEditor* mEditor;                      // the editor that created this transaction
+  nsRefPtr<mozilla::CSSStyleSheet> mSheet; // the style sheet to remove
 
 };
 
 
 #endif /* nsStylesheetTxns_h__ */
--- a/editor/libeditor/html/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/html/nsHTMLEditUtils.cpp
@@ -529,18 +529,18 @@ nsHTMLEditUtils::SupportsAlignAttr(nsIDO
 #define GROUP_TOPLEVEL         (1 << 1)  
 
 // base, link, meta, script, style, title
 #define GROUP_HEAD_CONTENT     (1 << 2)
 
 // b, big, i, s, small, strike, tt, u
 #define GROUP_FONTSTYLE        (1 << 3)
 
-// abbr, acronym, cite, code, datalist, del, dfn, em, ins, kbd, mark, samp,
-// strong, var
+// abbr, acronym, cite, code, datalist, del, dfn, em, ins, kbd, mark, rb, rp
+// rt, rtc, ruby, samp, strong, var
 #define GROUP_PHRASE           (1 << 4)
 
 // a, applet, basefont, bdo, br, font, iframe, img, map, meter, object, output,
 // progress, q, script, span, sub, sup
 #define GROUP_SPECIAL          (1 << 5)
 
 // button, form, input, label, select, textarea
 #define GROUP_FORMCONTROL      (1 << 6)
@@ -734,16 +734,21 @@ static const nsElementInfo kElements[eHT
        GROUP_SELECT_CONTENT | GROUP_OPTIONS, GROUP_LEAF),
   ELEM(output, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
   ELEM(p, true, false, GROUP_BLOCK | GROUP_P, GROUP_INLINE_ELEMENT),
   ELEM(param, false, false, GROUP_OBJECT_CONTENT, GROUP_NONE),
   ELEM(plaintext, false, false, GROUP_NONE, GROUP_NONE),
   ELEM(pre, true, true, GROUP_BLOCK, GROUP_INLINE_ELEMENT),
   ELEM(progress, true, false, GROUP_SPECIAL, GROUP_FLOW_ELEMENT),
   ELEM(q, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
+  ELEM(rb, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
+  ELEM(rp, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
+  ELEM(rt, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
+  ELEM(rtc, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
+  ELEM(ruby, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
   ELEM(s, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
   ELEM(samp, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
   ELEM(script, true, false, GROUP_HEAD_CONTENT | GROUP_SPECIAL,
        GROUP_LEAF),
   ELEM(section, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
   ELEM(select, true, false, GROUP_FORMCONTROL, GROUP_SELECT_CONTENT),
   ELEM(shadow, true, false, GROUP_NONE, GROUP_INLINE_ELEMENT),
   ELEM(small, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -31,18 +31,18 @@
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsISelectionController.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsILinkHandler.h"
 #include "nsIInlineSpellChecker.h"
 
+#include "mozilla/CSSStyleSheet.h"
 #include "mozilla/css/Loader.h"
-#include "nsCSSStyleSheet.h"
 #include "nsIDOMStyleSheet.h"
 
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsIDOMRange.h"
 #include "nsISupportsArray.h"
 #include "nsContentUtils.h"
 #include "nsIDocumentEncoder.h"
@@ -2849,17 +2849,17 @@ nsHTMLEditor::ReplaceStyleSheet(const ns
 
   return ps->GetDocument()->CSSLoader()->
     LoadSheet(uaURI, nullptr, EmptyCString(), this);
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::RemoveStyleSheet(const nsAString &aURL)
 {
-  nsRefPtr<nsCSSStyleSheet> sheet;
+  nsRefPtr<CSSStyleSheet> sheet;
   nsresult rv = GetStyleSheetForURL(aURL, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(sheet, NS_ERROR_UNEXPECTED);
 
   nsRefPtr<RemoveStyleSheetTxn> txn;
   rv = CreateTxnForRemoveStyleSheet(sheet, getter_AddRefs(txn));
   if (!txn) rv = NS_ERROR_NULL_POINTER;
   if (NS_SUCCEEDED(rv))
@@ -2889,17 +2889,17 @@ nsHTMLEditor::AddOverrideStyleSheet(cons
 
   nsCOMPtr<nsIURI> uaURI;
   nsresult rv = NS_NewURI(getter_AddRefs(uaURI), aURL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We MUST ONLY load synchronous local files (no @import)
   // XXXbz Except this will actually try to load remote files
   // synchronously, of course..
-  nsRefPtr<nsCSSStyleSheet> sheet;
+  nsRefPtr<CSSStyleSheet> sheet;
   // Editor override style sheets may want to style Gecko anonymous boxes
   rv = ps->GetDocument()->CSSLoader()->
     LoadSheetSync(uaURI, true, true, getter_AddRefs(sheet));
 
   // Synchronous loads should ALWAYS return completed
   NS_ENSURE_TRUE(sheet, NS_ERROR_NULL_POINTER);
 
   // Add the override style sheet
@@ -2933,17 +2933,17 @@ nsHTMLEditor::ReplaceOverrideStyleSheet(