Merge m-c to b2g-inbound
authorWes Kocher <wkocher@mozilla.com>
Thu, 05 Jun 2014 19:16:01 -0700
changeset 206328 b7d259bda94a1a0075fad7a964c7df97537b14f2
parent 206327 0ac52fd5bdb3f7ab16f2b8e23add28a8d40f70d2 (current diff)
parent 206189 4a552fb1ca38e5eabb53d59db9f8568f7f67676b (diff)
child 206329 c8ce0908104b4821539a797ff9ce125a1ae602a4
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to b2g-inbound
js/src/vm/PropDesc.h
layout/reftests/text/pre-discard-newlines-1-ref.html
layout/reftests/text/pre-discard-newlines-1.html
mobile/android/base/resources/drawable-hdpi/close_edit_mode.png
mobile/android/base/resources/drawable-mdpi/close_edit_mode.png
mobile/android/base/resources/drawable-xhdpi/close_edit_mode.png
netwerk/test/TestAsyncCache.js
netwerk/test/TestCacheCollisions.js
netwerk/test/TestCachePerformance.js
netwerk/test/TestCacheService.cpp
netwerk/test/TestCacheVisitor.js
netwerk/test/TestDiskCache.js
netwerk/test/TestMCTransport.cpp
netwerk/test/TestObjectCache.js
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,10 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1014976 - Windows debug bustage from linking changes.
-
+Bug 989276 is the latest to incur the wrath of bug 1019955.
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -974,16 +974,19 @@ pref("gfx.canvas.willReadFrequently.enab
 pref("browser.autofocus", false);
 
 // Enable wakelock
 pref("dom.wakelock.enabled", true);
 
 // Disable touch caret by default
 pref("touchcaret.enabled", false);
 
+// Disable selection caret by default
+pref("selectioncaret.enabled", false);
+
 // Enable sync and mozId with Firefox Accounts.
 #ifdef MOZ_SERVICES_FXACCOUNTS
 pref("services.sync.fxaccounts.enabled", true);
 pref("identity.fxaccounts.enabled", true);
 #endif
 
 // Enable mapped array buffer
 pref("dom.mapped_arraybuffer.enabled", true);
--- a/b2g/chrome/content/content.css
+++ b/b2g/chrome/content/content.css
@@ -278,21 +278,19 @@ input[type="checkbox"][disabled]:hover:a
 select[disabled] > button {
   opacity: 0.6;
   padding: 1px 7px 1px 7px;
 }
 
 *:-moz-any-link:active,
 *[role=button]:active,
 button:active,
-input:active,
 option:active,
 select:active,
-label:active,
-textarea:active {
+label:active {
   background-color: rgba(141, 184, 216, 0.5);
 }
 
 input[type=number] > div > div, /* work around bug 946184 */
 input[type=number]::-moz-number-spin-box {
   display: none;
 }
 
--- a/b2g/chrome/content/devtools.js
+++ b/b2g/chrome/content/devtools.js
@@ -267,17 +267,24 @@ Target.prototype = {
    * widgets.
    */
   destroy: function target_destroy() {
     delete this.metrics;
     this._send({});
   },
 
   _send: function target_send(data) {
-    shell.sendEvent(this.frame, 'developer-hud-update', Cu.cloneInto(data, this.frame));
+    let frame = this.frame;
+
+    let systemapp = document.querySelector('#systemapp');
+    if (this.frame === systemapp) {
+      frame = getContentWindow();
+    }
+
+    shell.sendEvent(frame, 'developer-hud-update', Cu.cloneInto(data, target));
   }
 
 };
 
 
 /**
  * The Console Watcher tracks the following metrics in apps: reflows, warnings,
  * and errors, with security errors reported separately.
--- a/b2g/components/ContentPermissionPrompt.js
+++ b/b2g/components/ContentPermissionPrompt.js
@@ -415,17 +415,34 @@ ContentPermissionPrompt.prototype = {
       isApp: isApp,
       remember: remember,
       isGranted: isGranted,
     };
 
     if (isApp) {
       details.manifestURL = DOMApplicationRegistry.getManifestURLByLocalId(principal.appId);
     }
-    SystemAppProxy.dispatchEvent(details);
+
+    // request.element is defined for OOP content, while request.window
+    // is defined for In-Process content.
+    // In both cases the message needs to be dispatched to the top-level
+    // <iframe mozbrowser> container in the system app.
+    // So the above code iterates over window.realFrameElement in order
+    // to crosss mozbrowser iframes boundaries and find the top-level
+    // one in the system app.
+    // window.realFrameElement will be |null| if the code try to cross
+    // content -> chrome boundaries.
+    let targetElement = request.element;
+    let targetWindow = request.window || targetElement.ownerDocument.defaultView;
+    while (targetWindow.realFrameElement) {
+      targetElement = targetWindow.realFrameElement;
+      targetWindow = targetElement.ownerDocument.defaultView;
+    }
+
+    SystemAppProxy.dispatchEvent(details, targetElement);
   },
 
   classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt])
 };
 
 (function() {
--- a/b2g/components/SystemAppProxy.jsm
+++ b/b2g/components/SystemAppProxy.jsm
@@ -53,17 +53,20 @@ let SystemAppProxy = {
    *     event.details == 'bar'
    *   });
    *
    *   @param type      The custom event type.
    *   @param details   The event details.
    *   @param noPending Set to true to emit this event even before the system
    *                    app is ready.
    */
-  _sendCustomEvent: function systemApp_sendCustomEvent(type, details, noPending) {
+  _sendCustomEvent: function systemApp_sendCustomEvent(type,
+                                                       details,
+                                                       noPending,
+                                                       target) {
     let content = this._frame ? this._frame.contentWindow : null;
 
     // If the system app isn't ready yet,
     // queue events until someone calls setIsReady
     if (!content || (!this._isReady && !noPending)) {
       this._pendingEvents.push([type, details]);
       return null;
     }
@@ -75,24 +78,24 @@ let SystemAppProxy = {
     // we consider the caller already wrapped (correctly) the object.
     if ('__exposedProps__' in details) {
       payload = details;
     } else {
       payload = details ? Cu.cloneInto(details, content) : {};
     }
 
     event.initCustomEvent(type, true, false, payload);
-    content.dispatchEvent(event);
+    (target || content).dispatchEvent(event);
 
     return event;
   },
 
   // Now deprecated, use sendCustomEvent with a custom event name
-  dispatchEvent: function systemApp_sendChromeEvent(details) {
-    return this._sendCustomEvent('mozChromeEvent', details);
+  dispatchEvent: function systemApp_sendChromeEvent(details, target) {
+    return this._sendCustomEvent('mozChromeEvent', details, false, target);
   },
 
   // Listen for dom events on the system app
   addEventListener: function systemApp_addEventListener() {
     let content = this._frame ? this._frame.contentWindow : null;
     if (!content) {
       this._pendingListeners.push(arguments);
       return false;
--- a/b2g/components/test/mochitest/systemapp_helper.js
+++ b/b2g/components/test/mochitest/systemapp_helper.js
@@ -3,16 +3,17 @@ const Cu = Components.utils;
 const { Services } = Cu.import("resource://gre/modules/Services.jsm");
 
 // Load a duplicated copy of the jsm to prevent messing with the currently running one
 let scope = {};
 Services.scriptloader.loadSubScript("resource://gre/modules/SystemAppProxy.jsm", scope);
 const { SystemAppProxy } = scope;
 
 let frame;
+let customEventTarget;
 
 let index = -1;
 function next() {
   index++;
   if (index >= steps.length) {
     assert.ok(false, "Shouldn't get here!");
     return;
   }
@@ -42,16 +43,20 @@ function listener(event) {
 
     next(); // call checkEventDispatching
   } else if (n == 3) {
     assert.equal(event.type, "custom");
     assert.equal(event.detail.name, "third");
   } else if (n == 4) {
     assert.equal(event.type, "mozChromeEvent");
     assert.equal(event.detail.name, "fourth");
+  } else if (n == 5) {
+    assert.equal(event.type, "custom");
+    assert.equal(event.detail.name, "fifth");
+    assert.equal(event.target, customEventTarget);
 
     next(); // call checkEventListening();
   } else {
     assert.ok(false, "Unexpected event of type " + event.type);
   }
 }
 
 
@@ -74,16 +79,18 @@ let steps = [
 
   function createFrame() {
     // Create a fake system app frame
     let win = Services.wm.getMostRecentWindow("navigator:browser");
     let doc = win.document;
     frame = doc.createElement("iframe");
     doc.documentElement.appendChild(frame);
 
+    customEventTarget = frame.contentDocument.body;
+
     // Ensure that events are correctly sent to the frame.
     // `listener` is going to call next()
     frame.contentWindow.addEventListener("mozChromeEvent", listener);
     frame.contentWindow.addEventListener("custom", listener);
 
     // Ensure that listener being registered before the system app is ready
     // are correctly removed from the pending list
     function removedListener() {
@@ -113,17 +120,18 @@ let steps = [
     frame.setAttribute("src", "data:text/html,system app");
   },
 
   function checkEventDispatching() {
     // Send events after the iframe is ready,
     // they should be dispatched right away
     SystemAppProxy._sendCustomEvent("custom", { name: "third" });
     SystemAppProxy.dispatchEvent({ name: "fourth" });
-    // Once this 4th event is received, we will run checkEventListening
+    SystemAppProxy._sendCustomEvent("custom", { name: "fifth" }, false, customEventTarget);
+    // Once this 5th event is received, we will run checkEventListening
   },
 
   function checkEventListening() {
     SystemAppProxy.addEventListener("mozContentEvent", function onContentEvent(event) {
       assert.equal(event.detail.name, "first-content", "received a system app event");
       SystemAppProxy.removeEventListener("mozContentEvent", onContentEvent);
 
       next();
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -666,16 +666,28 @@
 @BINPATH@/res/table-add-row-before-hover.gif
 @BINPATH@/res/table-add-row-before.gif
 @BINPATH@/res/table-remove-column-active.gif
 @BINPATH@/res/table-remove-column-hover.gif
 @BINPATH@/res/table-remove-column.gif
 @BINPATH@/res/table-remove-row-active.gif
 @BINPATH@/res/table-remove-row-hover.gif
 @BINPATH@/res/table-remove-row.gif
+@BINPATH@/res/text_caret.png
+@BINPATH@/res/text_caret@1.5x.png
+@BINPATH@/res/text_caret@2.25x.png
+@BINPATH@/res/text_caret@2x.png
+@BINPATH@/res/text_caret_tilt_left.png
+@BINPATH@/res/text_caret_tilt_left@1.5x.png
+@BINPATH@/res/text_caret_tilt_left@2.25x.png
+@BINPATH@/res/text_caret_tilt_left@2x.png
+@BINPATH@/res/text_caret_tilt_right.png
+@BINPATH@/res/text_caret_tilt_right@1.5x.png
+@BINPATH@/res/text_caret_tilt_right@2.25x.png
+@BINPATH@/res/text_caret_tilt_right@2x.png
 @BINPATH@/res/text_selection_handle.png
 @BINPATH@/res/text_selection_handle@1.5.png
 @BINPATH@/res/text_selection_handle@2.png
 @BINPATH@/res/grabber.gif
 #ifdef XP_MACOSX
 @BINPATH@/res/cursors/*
 #endif
 @BINPATH@/res/fonts/*
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -40,16 +40,17 @@ svg|line.box-model-guide-bottom[hidden] 
   white-space: nowrap;
   text-overflow: ellipsis;
   direction: ltr;
 }
 
 html|*.highlighter-nodeinfobar-id,
 html|*.highlighter-nodeinfobar-classes,
 html|*.highlighter-nodeinfobar-pseudo-classes,
+html|*.highlighter-nodeinfobar-dimensions,
 html|*.highlighter-nodeinfobar-tagname {
   -moz-user-select: text;
   -moz-user-focus: normal;
   cursor: text;
 }
 
 .highlighter-nodeinfobar-arrow {
   display: none;
--- a/browser/base/content/newtab/page.js
+++ b/browser/base/content/newtab/page.js
@@ -205,17 +205,29 @@ let gPage = {
     let directoryCount = {};
     for (let type of DirectoryLinksProvider.linkTypes) {
       directoryCount[type] = 0;
     }
 
     for (let site of gGrid.sites) {
       if (site) {
         site.captureIfMissing();
-        let {type} = site.link;
+
+        // Record which tile index a directory link was shown
+        let {directoryIndex, type} = site.link;
+        if (directoryIndex !== undefined) {
+          let tileIndex = site.cell.index;
+          // For telemetry, only handle the first 9 links in the first 9 cells
+          if (directoryIndex < 9) {
+            let shownId = "NEWTAB_PAGE_DIRECTORY_LINK" + directoryIndex + "_SHOWN";
+            Services.telemetry.getHistogramById(shownId).add(Math.min(9, tileIndex));
+          }
+        }
+
+        // Aggregate tile impression counts into directory types
         if (type in directoryCount) {
           directoryCount[type]++;
         }
       }
     }
 
     DirectoryLinksProvider.reportShownCount(directoryCount);
     // Record how many directory sites were shown, but place counts over the
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2880,42 +2880,65 @@
       <property name="textZoom"
                 onget="return this.mCurrentBrowser.textZoom;"
                 onset="this.mCurrentBrowser.textZoom = val;"/>
 
       <property name="isSyntheticDocument"
                 onget="return this.mCurrentBrowser.isSyntheticDocument;"
                 readonly="true"/>
 
-      <method name="_handleKeyEvent">
+      <method name="_handleKeyDownEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
           if (!aEvent.isTrusted) {
             // Don't let untrusted events mess with tabs.
             return;
           }
 
           if (aEvent.altKey)
             return;
 
+          // Don't check if the event was already consumed because tab
+          // navigation should always work for better user experience.
+
           if (aEvent.ctrlKey && aEvent.shiftKey && !aEvent.metaKey) {
             switch (aEvent.keyCode) {
               case aEvent.DOM_VK_PAGE_UP:
                 this.moveTabBackward();
-                aEvent.stopPropagation();
                 aEvent.preventDefault();
                 return;
               case aEvent.DOM_VK_PAGE_DOWN:
                 this.moveTabForward();
-                aEvent.stopPropagation();
                 aEvent.preventDefault();
                 return;
             }
           }
 
+#ifndef XP_MACOSX
+          if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
+              aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
+              !this.mCurrentTab.pinned) {
+            this.removeCurrentTab({animate: true});
+            aEvent.preventDefault();
+          }
+#endif
+        ]]></body>
+      </method>
+
+      <method name="_handleKeyPressEvent">
+        <parameter name="aEvent"/>
+        <body><![CDATA[
+          if (!aEvent.isTrusted) {
+            // Don't let untrusted events mess with tabs.
+            return;
+          }
+
+          if (aEvent.altKey)
+            return;
+
           // We need to take care of FAYT-watching as long as the findbar
           // isn't initialized.  The checks on aEvent are copied from
           // _shouldFastFind (see findbar.xml).
           if (!gFindBarInitialized &&
               !(aEvent.ctrlKey || aEvent.metaKey) &&
               !aEvent.defaultPrevented) {
             let charCode = aEvent.charCode;
             if (charCode) {
@@ -2935,27 +2958,18 @@
           var offset = 1;
           switch (aEvent.charCode) {
             case '}'.charCodeAt(0):
               offset = -1;
             case '{'.charCodeAt(0):
               if (window.getComputedStyle(this, null).direction == "ltr")
                 offset *= -1;
               this.tabContainer.advanceSelectedTab(offset, true);
-              aEvent.stopPropagation();
               aEvent.preventDefault();
           }
-#else
-          if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
-              aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
-              !this.mCurrentTab.pinned) {
-            this.removeCurrentTab({animate: true});
-            aEvent.stopPropagation();
-            aEvent.preventDefault();
-          }
 #endif
         ]]></body>
       </method>
 
       <property name="userTypedClear"
                 onget="return this.mCurrentBrowser.userTypedClear;"
                 onset="return this.mCurrentBrowser.userTypedClear = val;"/>
 
@@ -2977,18 +2991,21 @@
                                              tab.getAttribute("label"));
         ]]></body>
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
           switch (aEvent.type) {
+            case "keydown":
+              this._handleKeyDownEvent(aEvent);
+              break;
             case "keypress":
-              this._handleKeyEvent(aEvent);
+              this._handleKeyPressEvent(aEvent);
               break;
             case "sizemodechange":
               if (aEvent.target == window) {
                 this.mCurrentBrowser.docShellIsActive =
                   (window.windowState != window.STATE_MINIMIZED);
               }
               break;
           }
@@ -3045,17 +3062,19 @@
       </method>
 
       <constructor>
         <![CDATA[
           let browserStack = document.getAnonymousElementByAttribute(this, "anonid", "browserStack");
           this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser");
 
           this.mCurrentTab = this.tabContainer.firstChild;
-          document.addEventListener("keypress", this, false);
+          let els = Cc["@mozilla.org/eventlistenerservice;1"].getService(Ci.nsIEventListenerService);
+          els.addSystemEventListener(document, "keydown", this, false);
+          els.addSystemEventListener(document, "keypress", this, false);
           window.addEventListener("sizemodechange", this, false);
 
           var uniqueId = this._generateUniquePanelID();
           this.mPanelContainer.childNodes[0].id = uniqueId;
           this.mCurrentTab.linkedPanel = uniqueId;
           this.mCurrentTab._tPos = 0;
           this.mCurrentTab._fullyOpen = true;
           this.mCurrentTab.linkedBrowser = this.mCurrentBrowser;
@@ -3123,17 +3142,19 @@
               delete browser.registeredOpenURI;
             }
             browser.webProgress.removeProgressListener(this.mTabFilters[i]);
             this.mTabFilters[i].removeProgressListener(this.mTabListeners[i]);
             this.mTabFilters[i] = null;
             this.mTabListeners[i].destroy();
             this.mTabListeners[i] = null;
           }
-          document.removeEventListener("keypress", this, false);
+          let els = Cc["@mozilla.org/eventlistenerservice;1"].getService(Ci.nsIEventListenerService);
+          els.removeSystemEventListener(document, "keydown", this, false);
+          els.removeSystemEventListener(document, "keypress", this, false);
           window.removeEventListener("sizemodechange", this, false);
 
           if (gMultiProcessBrowser) {
             messageManager.removeMessageListener("DOMTitleChanged", this);
             messageManager.removeMessageListener("contextmenu", this);
           }
         ]]>
       </destructor>
@@ -4242,25 +4263,28 @@
           BrowserOpenTab();
         } else {
           return;
         }
 
         event.stopPropagation();
       ]]></handler>
 
-      <handler event="keypress"><![CDATA[
+      <handler event="keydown" group="system"><![CDATA[
         if (event.altKey || event.shiftKey ||
 #ifdef XP_MACOSX
             !event.metaKey)
 #else
             !event.ctrlKey || event.metaKey)
 #endif
           return;
 
+        // Don't check if the event was already consumed because tab navigation
+        // should work always for better user experience.
+
         switch (event.keyCode) {
           case KeyEvent.DOM_VK_UP:
             this.tabbrowser.moveTabBackward();
             break;
           case KeyEvent.DOM_VK_DOWN:
             this.tabbrowser.moveTabForward();
             break;
           case KeyEvent.DOM_VK_RIGHT:
@@ -4269,21 +4293,20 @@
             break;
           case KeyEvent.DOM_VK_HOME:
             this.tabbrowser.moveTabToStart();
             break;
           case KeyEvent.DOM_VK_END:
             this.tabbrowser.moveTabToEnd();
             break;
           default:
-            // Stop the keypress event for the above keyboard
+            // Consume the keydown event for the above keyboard
             // shortcuts only.
             return;
         }
-        event.stopPropagation();
         event.preventDefault();
       ]]></handler>
 
       <handler event="dragstart"><![CDATA[
         var tab = this._getDragTargetTab(event);
         if (!tab || this._isCustomizing)
           return;
 
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -375,16 +375,17 @@ skip-if = e10s # Bug 918634 - swapFrameL
 [browser_tab_dragdrop.js]
 skip-if = e10s # Bug 918634 - swapFrameLoaders not implemented for e10s (test uses gBrowser.swapBrowsersAndCloseOther)
 [browser_tab_dragdrop2.js]
 [browser_tabbar_big_widgets.js]
 skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
                                        # Disabled on OS X because of bug 967917
 [browser_tabfocus.js]
 skip-if = e10s # Bug 921935 - focusmanager issues with e10s (test calls getFocusedElementForWindow with a content window)
+[browser_tabkeynavigation.js]
 [browser_tabopen_reflows.js]
 skip-if = e10s # Bug ?????? - test needs to be updated for e10s (captures a stack that isn't correct in e10s)
 [browser_tabs_isActive.js]
 skip-if = e10s # Bug ?????? - test directly manipulates content (tries to get/set attributes directly on content docshell)
 [browser_tabs_owner.js]
 [browser_typeAheadFind.js]
 skip-if = e10s # Bug 921935 - focusmanager issues with e10s (test calls waitForFocus)
 [browser_unloaddialogs.js]
--- a/browser/base/content/test/general/browser_sanitizeDialog.js
+++ b/browser/base/content/test/general/browser_sanitizeDialog.js
@@ -13,16 +13,17 @@
  * test checks the UI of the dialog and makes sure it's correctly connected to
  * the sanitize timespan code.
  *
  * Some of this code, especially the history creation parts, was taken from
  * browser/base/content/test/general/browser_sanitize-timespans.js.
  */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+let {LoadContextInfo} = Cu.import("resource://gre/modules/LoadContextInfo.jsm", {});
 
 XPCOMUtils.defineLazyModuleGetter(this, "FormHistory",
                                   "resource://gre/modules/FormHistory.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
                                   "resource://gre/modules/Downloads.jsm");
 
 let tempScope = {};
 Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
@@ -562,68 +563,64 @@ var gAllTests = [
 
     // Give www.example.com privileges to store offline data
     var pm = Cc["@mozilla.org/permissionmanager;1"]
              .getService(Ci.nsIPermissionManager);
     pm.addFromPrincipal(principal, "offline-app", Ci.nsIPermissionManager.ALLOW_ACTION);
     pm.addFromPrincipal(principal, "offline-app", Ci.nsIOfflineCacheUpdateService.ALLOW_NO_WARN);
 
     // Store something to the offline cache
-    const nsICache = Components.interfaces.nsICache;
-    var cs = Components.classes["@mozilla.org/network/cache-service;1"]
-             .getService(Components.interfaces.nsICacheService);
-    var session = cs.createSession(URL + "/manifest", nsICache.STORE_OFFLINE, nsICache.STREAM_BASED);
+    var appcacheserv = Cc["@mozilla.org/network/application-cache-service;1"]
+                       .getService(Ci.nsIApplicationCacheService);
+    var appcachegroupid = appcacheserv.buildGroupID(makeURI(URL + "/manifest"), LoadContextInfo.default);
+    var appcache = appcacheserv.createApplicationCache(appcachegroupid);
+
+    var cacheserv = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                    .getService(Ci.nsICacheStorageService);
+    var storage = cacheserv.appCacheStorage(LoadContextInfo.default, appcache);
 
     // Open the dialog
     let wh = new WindowHelper();
     wh.onload = function () {
       this.selectDuration(Sanitizer.TIMESPAN_EVERYTHING);
       // Show details
       this.toggleDetails();
       // Clear only offlineApps
       this.uncheckAllCheckboxes();
       this.checkPrefCheckbox("offlineApps", true);
       this.acceptDialog();
     };
     wh.onunload = function () {
       // Check if the cache has been deleted
       var size = -1;
       var visitor = {
-        visitDevice: function (deviceID, deviceInfo)
+        onCacheStorageInfo: function (aEntryCount, aConsumption, aCapacity, aDiskDirectory)
         {
-          if (deviceID == "offline")
-            size = deviceInfo.totalSize;
-
-          // Do not enumerate entries
-          return false;
-        },
-
-        visitEntry: function (deviceID, entryInfo)
-        {
-          // Do not enumerate entries.
-          return false;
+          size = aConsumption;
         }
       };
-      cs.visitEntries(visitor);
+      storage.asyncVisitStorage(visitor, false);
+      // Offline cache visit happens synchronously, since it's forwarded to the old code
       is(size, 0, "offline application cache entries evicted");
     };
 
     var cacheListener = {
-      onCacheEntryAvailable: function (entry, access, status) {
+      onCacheEntryCheck: function() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; },
+      onCacheEntryAvailable: function (entry, isnew, appcache, status) {
         is(status, Cr.NS_OK);
         var stream = entry.openOutputStream(0);
         var content = "content";
         stream.write(content, content.length);
         stream.close();
         entry.close();
         wh.open();
       }
     };
 
-    session.asyncOpenCacheEntry(URL, nsICache.ACCESS_READ_WRITE, cacheListener);
+    storage.asyncOpenURI(makeURI(URL), "", Ci.nsICacheStorage.OPEN_TRUNCATE, cacheListener);
   },
   function () {
     // Test for offline apps permission deletion
 
     // Prepare stuff, we will work with www.example.com
     var URL = "http://www.example.com";
 
     var ios = Cc["@mozilla.org/network/io-service;1"]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_tabkeynavigation.js
@@ -0,0 +1,214 @@
+/*
+ * This test checks that keyboard navigation for tabs isn't blocked by content
+ */
+
+function test() {
+  waitForExplicitFinish();
+
+  let testPage1 = "data:text/html,<html id='tab1'><body><button id='button1'>Tab 1</button></body></html>";
+  let testPage2 = "data:text/html,<html id='tab2'><body><button id='button2'>Tab 2</button><script>function preventDefault(event) { event.preventDefault(); event.stopImmediatePropagation(); } window.addEventListener('keydown', preventDefault, true); window.addEventListener('keypress', preventDefault, true);</script></body></html>";
+  let testPage3 = "data:text/html,<html id='tab3'><body><button id='button3'>Tab 3</button></body></html>";
+
+  let tab1 = gBrowser.addTab();
+  let browser1 = gBrowser.getBrowserForTab(tab1);
+
+  let tab2 = gBrowser.addTab();
+  let browser2 = gBrowser.getBrowserForTab(tab2);
+
+  let tab3 = gBrowser.addTab();
+  let browser3 = gBrowser.getBrowserForTab(tab3);
+
+  let loadCount = 0;
+  function check()
+  {
+    // wait for all tabs to load
+    if (++loadCount != 3) {
+      return;
+    }
+
+    browser1.removeEventListener("load", check, true);
+    browser2.removeEventListener("load", check, true);
+    browser3.removeEventListener("load", check, true);
+    executeSoon(_run_tab_keyboard_navigation_tests);
+  }
+
+  function _run_tab_keyboard_navigation_tests()
+  {
+    // Kill the animation for simpler test.
+    Services.prefs.setBoolPref("browser.tabs.animate", false);
+
+    gBrowser.selectedTab = tab1;
+    browser1.contentWindow.focus();
+
+    is(gBrowser.selectedTab, tab1,
+       "Tab1 should be activated");
+    EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true },
+                             browser1.contentWindow);
+    is(gBrowser.selectedTab, tab2,
+       "Tab2 should be activated by pressing Ctrl+Tab on Tab1");
+
+    EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true },
+                             browser2.contentWindow);
+    is(gBrowser.selectedTab, tab3,
+       "Tab3 should be activated by pressing Ctrl+Tab on Tab2");
+
+    EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true },
+                             browser3.contentWindow);
+    is(gBrowser.selectedTab, tab2,
+       "Tab2 should be activated by pressing Ctrl+Shift+Tab on Tab3");
+
+    EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true },
+                             browser2.contentWindow);
+    is(gBrowser.selectedTab, tab1,
+       "Tab1 should be activated by pressing Ctrl+Shift+Tab on Tab2");
+
+    gBrowser.selectedTab = tab1;
+    browser1.contentWindow.focus();
+
+    is(gBrowser.selectedTab, tab1,
+       "Tab1 should be activated");
+    EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true },
+                             browser1.contentWindow);
+    is(gBrowser.selectedTab, tab2,
+       "Tab2 should be activated by pressing Ctrl+PageDown on Tab1");
+
+    EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true },
+                             browser2.contentWindow);
+    is(gBrowser.selectedTab, tab3,
+       "Tab3 should be activated by pressing Ctrl+PageDown on Tab2");
+
+    EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true },
+                             browser3.contentWindow);
+    is(gBrowser.selectedTab, tab2,
+       "Tab2 should be activated by pressing Ctrl+PageUp on Tab3");
+
+    EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true },
+                             browser2.contentWindow);
+    is(gBrowser.selectedTab, tab1,
+       "Tab1 should be activated by pressing Ctrl+PageUp on Tab2");
+
+    if (gBrowser.mTabBox._handleMetaAltArrows) {
+      gBrowser.selectedTab = tab1;
+      browser1.contentWindow.focus();
+
+      let ltr =
+        window.getComputedStyle(gBrowser.mTabBox, "").direction == "ltr";
+      let advanceKey = ltr ? "VK_RIGHT" : "VK_LEFT";
+      let reverseKey = ltr ? "VK_LEFT" : "VK_RIGHT";
+
+      is(gBrowser.selectedTab, tab1,
+         "Tab1 should be activated");
+      EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true },
+                               browser1.contentWindow);
+      is(gBrowser.selectedTab, tab2,
+         "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1");
+
+      EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true },
+                               browser2.contentWindow);
+      is(gBrowser.selectedTab, tab3,
+         "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2");
+
+      EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true },
+                               browser3.contentWindow);
+      is(gBrowser.selectedTab, tab2,
+         "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3");
+
+      EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true },
+                               browser2.contentWindow);
+      is(gBrowser.selectedTab, tab1,
+         "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2");
+    }
+
+    gBrowser.selectedTab = tab2;
+    is(gBrowser.selectedTab, tab2,
+       "Tab2 should be activated");
+    is(gBrowser.tabContainer.selectedIndex, 2,
+       "Tab2 index should be 2");
+
+    EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true },
+                             browser2.contentWindow);
+    is(gBrowser.selectedTab, tab2,
+       "Tab2 should be activated after Ctrl+Shift+PageDown");
+    is(gBrowser.tabContainer.selectedIndex, 3,
+       "Tab2 index should be 1 after Ctrl+Shift+PageDown");
+
+    EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true },
+                             browser2.contentWindow);
+    is(gBrowser.selectedTab, tab2,
+       "Tab2 should be activated after Ctrl+Shift+PageUp");
+    is(gBrowser.tabContainer.selectedIndex, 2,
+       "Tab2 index should be 2 after Ctrl+Shift+PageUp");
+
+    if (navigator.platform.indexOf("Mac") == 0) {
+      gBrowser.selectedTab = tab1;
+      browser1.contentWindow.focus();
+
+      // XXX Currently, Command + "{" and "}" don't work if keydown event is
+      //     consumed because following keypress event isn't fired.
+
+      let ltr =
+        window.getComputedStyle(gBrowser.mTabBox, "").direction == "ltr";
+      let advanceKey = ltr ? "}" : "{";
+      let reverseKey = ltr ? "{" : "}";
+
+      is(gBrowser.selectedTab, tab1,
+         "Tab1 should be activated");
+      EventUtils.synthesizeKey(advanceKey, { metaKey: true },
+                               browser1.contentWindow);
+      is(gBrowser.selectedTab, tab2,
+         "Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1");
+
+      EventUtils.synthesizeKey(advanceKey, { metaKey: true },
+                               browser2.contentWindow);
+      todo_is(gBrowser.selectedTab, tab3,
+              "Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2");
+
+      if (gBrowser.selectedTab != tab3) {
+        EventUtils.synthesizeKey(reverseKey, { metaKey: true },
+                                 browser3.contentWindow);
+        is(gBrowser.selectedTab, tab2,
+           "Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3");
+      }
+
+      EventUtils.synthesizeKey(reverseKey, { metaKey: true },
+                               browser2.contentWindow);
+      todo_is(gBrowser.selectedTab, tab1,
+              "Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2");
+    } else {
+      gBrowser.selectedTab = tab2;
+      EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true },
+                               browser2.contentWindow);
+
+      isnot(gBrowser.selectedTab, tab2,
+            "Tab2 should be closed by pressing Ctrl+F4 on Tab2");
+      is(gBrowser.tabs.length, 3,
+         "The count of tabs should be 3 since tab2 should be closed");
+
+      let activeWindow =
+        gBrowser.getBrowserForTab(gBrowser.selectedTab).contentWindow;
+      // NOTE: keypress event shouldn't be fired since the keydown event should
+      //       be consumed by tab2.
+      EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true },
+                               activeWindow);
+      is(gBrowser.tabs.length, 3,
+         "The count of tabs should be 3 since renaming key events shouldn't close other tabs");
+    }
+
+    gBrowser.selectedTab = tab3;
+    while (gBrowser.tabs.length > 1) {
+      gBrowser.removeCurrentTab();
+    }
+
+    Services.prefs.clearUserPref("browser.tabs.animate");
+
+    finish();
+  }
+
+  browser1.addEventListener("load", check, true);
+  browser2.addEventListener("load", check, true);
+  browser3.addEventListener("load", check, true);
+
+  browser1.contentWindow.location = testPage1;
+  browser2.contentWindow.location = testPage2;
+  browser3.contentWindow.location = testPage3;
+}
--- a/browser/components/customizableui/test/browser_962069_drag_to_overflow_chevron.js
+++ b/browser/components/customizableui/test/browser_962069_drag_to_overflow_chevron.js
@@ -16,22 +16,26 @@ add_task(function*() {
   window.resizeTo(400, window.outerHeight);
   yield waitForCondition(() => navbar.hasAttribute("overflowing"));
   ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
 
   let widgetOverflowPanel = document.getElementById("widget-overflow");
   let panelShownPromise = promisePanelElementShown(window, widgetOverflowPanel);
   let identityBox = document.getElementById("identity-box");
   let overflowChevron = document.getElementById("nav-bar-overflow-button");
+
+  // Listen for hiding immediately so we don't miss the event because of the
+  // async-ness of the 'shown' yield...
+  let panelHiddenPromise = promisePanelElementHidden(window, widgetOverflowPanel);
+
   ChromeUtils.synthesizeDrop(identityBox, overflowChevron, [], null);
   yield panelShownPromise;
 
   info("Overflow panel is shown.");
 
-  let panelHiddenPromise = promisePanelElementHidden(window, widgetOverflowPanel);
   widgetOverflowPanel.hidePopup();
   yield panelHiddenPromise;
 });
 
 add_task(function*() {
   window.resizeTo(originalWindowWidth, window.outerHeight);
   let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
   yield waitForCondition(() => !navbar.hasAttribute("overflowing"));
--- a/browser/components/preferences/advanced.js
+++ b/browser/components/preferences/advanced.js
@@ -324,40 +324,31 @@ var gAdvancedPane = {
                 .getService(Components.interfaces.nsICacheStorageService);
     cacheService.asyncGetDiskConsumption(this.observer);
   },
 
   // Retrieves the amount of space currently used by offline cache
   updateActualAppCacheSize: function ()
   {
     var visitor = {
-      visitDevice: function (deviceID, deviceInfo)
+      onCacheStorageInfo: function (aEntryCount, aConsumption, aCapacity, aDiskDirectory)
       {
-        if (deviceID == "offline") {
-          var actualSizeLabel = document.getElementById("actualAppCacheSize");
-          var sizeStrings = DownloadUtils.convertByteUnits(deviceInfo.totalSize);
-          var prefStrBundle = document.getElementById("bundlePreferences");
-          var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
-          actualSizeLabel.value = sizeStr;
-        }
-        // Do not enumerate entries
-        return false;
-      },
-
-      visitEntry: function (deviceID, entryInfo)
-      {
-        // Do not enumerate entries.
-        return false;
+        var actualSizeLabel = document.getElementById("actualAppCacheSize");
+        var sizeStrings = DownloadUtils.convertByteUnits(aConsumption);
+        var prefStrBundle = document.getElementById("bundlePreferences");
+        var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
+        actualSizeLabel.value = sizeStr;
       }
     };
 
     var cacheService =
-      Components.classes["@mozilla.org/network/cache-service;1"]
-                .getService(Components.interfaces.nsICacheService);
-    cacheService.visitEntries(visitor);
+      Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
+                .getService(Components.interfaces.nsICacheStorageService);
+    var storage = cacheService.appCacheStorage(LoadContextInfo.default, null);
+    storage.asyncVisitStorage(visitor, false);
   },
 
   updateCacheSizeUI: function (smartSizeEnabled)
   {
     document.getElementById("useCacheBefore").disabled = smartSizeEnabled;
     document.getElementById("cacheSize").disabled = smartSizeEnabled;
     document.getElementById("useCacheAfter").disabled = smartSizeEnabled;
   },
--- a/browser/components/preferences/in-content/advanced.js
+++ b/browser/components/preferences/in-content/advanced.js
@@ -309,40 +309,31 @@ var gAdvancedPane = {
                 .getService(Components.interfaces.nsICacheStorageService);
     cacheService.asyncGetDiskConsumption(this.observer);
   },
 
   // Retrieves the amount of space currently used by offline cache
   updateActualAppCacheSize: function ()
   {
     var visitor = {
-      visitDevice: function (deviceID, deviceInfo)
+      onCacheStorageInfo: function (aEntryCount, aConsumption, aCapacity, aDiskDirectory)
       {
-        if (deviceID == "offline") {
-          var actualSizeLabel = document.getElementById("actualAppCacheSize");
-          var sizeStrings = DownloadUtils.convertByteUnits(deviceInfo.totalSize);
-          var prefStrBundle = document.getElementById("bundlePreferences");
-          var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
-          actualSizeLabel.textContent = sizeStr;
-        }
-        // Do not enumerate entries
-        return false;
-      },
-
-      visitEntry: function (deviceID, entryInfo)
-      {
-        // Do not enumerate entries.
-        return false;
+        var actualSizeLabel = document.getElementById("actualAppCacheSize");
+        var sizeStrings = DownloadUtils.convertByteUnits(aConsumption);
+        var prefStrBundle = document.getElementById("bundlePreferences");
+        var sizeStr = prefStrBundle.getFormattedString("actualAppCacheSize", sizeStrings);
+        actualSizeLabel.value = sizeStr;
       }
     };
 
     var cacheService =
-      Components.classes["@mozilla.org/network/cache-service;1"]
-                .getService(Components.interfaces.nsICacheService);
-    cacheService.visitEntries(visitor);
+      Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
+                .getService(Components.interfaces.nsICacheStorageService);
+    var storage = cacheService.appCacheStorage(LoadContextInfo.default, null);
+    storage.asyncVisitStorage(visitor, false);
   },
 
   updateCacheSizeUI: function (smartSizeEnabled)
   {
     document.getElementById("useCacheBefore").disabled = smartSizeEnabled;
     document.getElementById("cacheSize").disabled = smartSizeEnabled;
     document.getElementById("useCacheAfter").disabled = smartSizeEnabled;
   },
--- a/browser/components/translation/BingTranslator.jsm
+++ b/browser/components/translation/BingTranslator.jsm
@@ -151,19 +151,26 @@ this.BingTranslation.prototype = {
       // of items (from the number of items submitted), we can't use this chunk
       // because all items would be paired incorrectly.
       return false;
     }
 
     let error = false;
     for (let i = 0; i < len; i++) {
       try {
-        bingRequest.translationData[i][0].parseResult(
-          results[i].firstChild.nodeValue
-        );
+        let result = results[i].firstChild.nodeValue;
+        let root = bingRequest.translationData[i][0];
+
+        if (root.isSimpleRoot) {
+          // Workaround for Bing's service problem in which "&" chars in
+          // plain-text TranslationItems are double-escaped.
+          result = result.replace("&amp;", "&", "g");
+        }
+
+        root.parseResult(result);
       } catch (e) { error = true; }
     }
 
     return !error;
   },
 
   /**
    * This function will determine what is the data to be used for
--- a/browser/components/translation/Translation.jsm
+++ b/browser/components/translation/Translation.jsm
@@ -15,16 +15,17 @@ const TRANSLATION_PREF_SHOWUI = "browser
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/Metrics.jsm", this);
 Cu.import("resource://gre/modules/Task.jsm", this);
 
 const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER};
 const DAILY_LAST_TEXT_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_TEXT};
+const DAILY_LAST_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC};
 
 
 this.Translation = {
   supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
   supportedTargetLanguages: ["en", "pl", "tr", "vi"],
 
   _defaultTargetLanguage: "",
   get defaultTargetLanguage() {
@@ -295,16 +296,18 @@ TranslationMeasurement1.prototype = Obje
   fields: {
     translationOpportunityCount: DAILY_COUNTER_FIELD,
     pageTranslatedCount: DAILY_COUNTER_FIELD,
     charactersTranslatedCount: DAILY_COUNTER_FIELD,
     translationOpportunityCountsByLanguage: DAILY_LAST_TEXT_FIELD,
     pageTranslatedCountsByLanguage: DAILY_LAST_TEXT_FIELD,
     detectedLanguageChangedBefore: DAILY_COUNTER_FIELD,
     detectedLanguageChangedAfter: 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.
       return false;
     }
@@ -319,17 +322,17 @@ TranslationMeasurement1.prototype = Obje
       if (data.hasDay(date)) {
         data = JSON.parse(data.getDay(date));
       } else {
         data = {};
       }
 
       return data;
     });
-},
+  },
 
   _wrapJSONSerializer: function (serializer) {
     let _parseInPlace = function(o, k) {
       if (k in o) {
         o[k] = JSON.parse(o[k]);
       }
     };
 
@@ -409,16 +412,29 @@ TranslationProvider.prototype = Object.f
       if (beforeFirstTranslation) {
           yield m.incrementDailyCounter("detectedLanguageChangedBefore");
         } else {
           yield m.incrementDailyCounter("detectedLanguageChangedAfter");
         }
     }.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);
+
+      let showTranslationUI = Services.prefs.getBoolPref("browser.translation.ui.show");
+      yield m.setDailyLastNumeric("showTranslationUI", showTranslationUI ? 1 : 0);
+    }.bind(this));
+  },
+
   _enqueueTelemetryStorageTask: function (task) {
     if (!Services.prefs.getBoolPref("toolkit.telemetry.enabled")) {
       // This measurement should only be included when telemetry is
       // enabled, so don't record any data.
       return Promise.resolve(null);
     }
 
     return this.enqueueStorageOperation(() => {
--- a/browser/components/translation/test/unit/test_healthreport.js
+++ b/browser/components/translation/test/unit/test_healthreport.js
@@ -165,16 +165,54 @@ 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_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";
+  const kPrefShowUI = "browser.translation.ui.show";
+  Services.prefs.setBoolPref(kPrefDetectLanguage, false);
+  Services.prefs.setBoolPref(kPrefShowUI, false);
+
+  // Initially nothing should be configured.
+  yield provider.collectDailyData();
+
+  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("detectLanguageEnabled"));
+  Assert.ok(day.has("showTranslationUI"));
+
+  // Changes to the repective prefs should be picked up.
+  Services.prefs.setBoolPref(kPrefDetectLanguage, true);
+  Services.prefs.setBoolPref(kPrefShowUI, true);
+
+  yield provider.collectDailyData();
+
+  values = yield m.getValues();
+  day = values.days.getDay(now);
+  Assert.equal(day.get("detectLanguageEnabled"), 1);
+  Assert.equal(day.get("showTranslationUI"), 1);
+
+  yield provider.shutdown();
+  yield storage.close();
+});
+
 // Test the payload after recording with telemetry enabled.
 add_task(function* test_healthreporter_json() {
   Services.prefs.setBoolPref("toolkit.telemetry.enabled", true);
 
   let reporter = yield getHealthReporter("healthreporter_json");
   yield reporter.init();
   try {
     let now = new Date();
@@ -222,17 +260,17 @@ add_task(function* test_healthreporter_j
     Assert.ok("detectedLanguageChangedAfter" in translations);
     Assert.equal(translations["detectedLanguageChangedAfter"], 1);
   } finally {
     reporter._shutdown();
   }
 });
 
 // Test the payload after recording with telemetry disabled.
-add_task(function* test_healthreporter_json() {
+add_task(function* test_healthreporter_json2() {
   Services.prefs.setBoolPref("toolkit.telemetry.enabled", false);
 
   let reporter = yield getHealthReporter("healthreporter_json");
   yield reporter.init();
   try {
     let now = new Date();
     let provider = new TranslationProvider();
     yield reporter._providerManager.registerProvider(provider);
--- a/browser/devtools/commandline/test/browser_cmd_appcache_invalid.js
+++ b/browser/devtools/commandline/test/browser_cmd_appcache_invalid.js
@@ -7,30 +7,95 @@
 const TEST_URI = "http://sub1.test1.example.com/browser/browser/devtools/commandline/" +
                  "test/browser_cmd_appcache_invalid_index.html";
 
 function test() {
   return Task.spawn(spawnTest).then(finish, helpers.handleError);
 }
 
 function spawnTest() {
+  let lines = [
+    'Manifest has a character encoding of ISO-8859-1. Manifests must have the ' +
+      'utf-8 character encoding.',
+    'The first line of the manifest must be "CACHE MANIFEST" at line 1.',
+    '"CACHE MANIFEST" is only valid on the first line but was found at line 3.',
+    'images/sound-icon.png points to a resource that is not available at line 9.',
+    'images/background.png points to a resource that is not available at line 10.',
+    '/checking.cgi points to a resource that is not available at line 13.',
+    'Asterisk (*) incorrectly used in the NETWORK section at line 14. If a line ' +
+      'in the NETWORK section contains only a single asterisk character, then any ' +
+      'URI not listed in the manifest will be treated as if the URI was listed in ' +
+      'the NETWORK section. Otherwise such URIs will be treated as unavailable. ' +
+    'Other uses of the * character are prohibited',
+    '../rel.html points to a resource that is not available at line 17.',
+    '../../rel.html points to a resource that is not available at line 18.',
+    '../../../rel.html points to a resource that is not available at line 19.',
+    '../../../../rel.html points to a resource that is not available at line 20.',
+    '../../../../../rel.html points to a resource that is not available at line 21.',
+    '/../ is not a valid URI prefix at line 22.',
+    '/test.css points to a resource that is not available at line 23.',
+    '/test.js points to a resource that is not available at line 24.',
+    'test.png points to a resource that is not available at line 25.',
+    '/main/features.js points to a resource that is not available at line 27.',
+    '/main/settings/index.css points to a resource that is not available at line 28.',
+    'http://example.com/scene.jpg points to a resource that is not available at line 29.',
+    '/section1/blockedbyfallback.html points to a resource that is not available at line 30.',
+    'http://example.com/images/world.jpg points to a resource that is not available at line 31.',
+    '/section2/blockedbyfallback.html points to a resource that is not available at line 32.',
+    '/main/home points to a resource that is not available at line 34.',
+    'main/app.js points to a resource that is not available at line 35.',
+    '/settings/home points to a resource that is not available at line 37.',
+    '/settings/app.js points to a resource that is not available at line 38.',
+    'The file http://sub1.test1.example.com/browser/browser/devtools/' +
+      'commandline/test/browser_cmd_appcache_invalid_page3.html was modified ' +
+      'after http://sub1.test1.example.com/browser/browser/devtools/' +
+      'commandline/test/browser_cmd_appcache_invalid_appcache.appcache. Unless ' +
+      'the text in the manifest file is changed the cached version will be used ' +
+      'instead at line 39.',
+    'browser_cmd_appcache_invalid_page3.html has cache-control set to no-store. ' +
+      'This will prevent the application cache from storing the file at line 39.',
+    'http://example.com/logo.png points to a resource that is not available at line 40.',
+    'http://example.com/check.png points to a resource that is not available at line 41.',
+    'Spaces in URIs need to be replaced with % at line 42.',
+    'http://example.com/cr oss.png points to a resource that is not available at line 42.',
+    'Asterisk (*) incorrectly used in the CACHE section at line 43. If a line ' +
+      'in the NETWORK section contains only a single asterisk character, then ' +
+      'any URI not listed in the manifest will be treated as if the URI was ' +
+      'listed in the NETWORK section. Otherwise such URIs will be treated as ' +
+      'unavailable. Other uses of the * character are prohibited',
+    'The SETTINGS section may only contain a single value, "prefer-online" or "fast" at line 47.',
+    'FALLBACK section line 50 (/section1/ /offline1.html) prevents caching of ' +
+      'line 30 (/section1/blockedbyfallback.html) in the CACHE section.',
+    '/offline1.html points to a resource that is not available at line 50.',
+    'FALLBACK section line 51 (/section2/ offline2.html) prevents caching of ' +
+      'line 32 (/section2/blockedbyfallback.html) in the CACHE section.',
+    'offline2.html points to a resource that is not available at line 51.',
+    'Only two URIs separated by spaces are allowed in the FALLBACK section at line 52.',
+    'Asterisk (*) incorrectly used in the FALLBACK section at line 53. URIs ' +
+      'in the FALLBACK section simply need to match a prefix of the request URI.',
+    'offline3.html points to a resource that is not available at line 53.',
+    'Invalid section name (BLAH) at line 55.',
+    'Only two URIs separated by spaces are allowed in the FALLBACK section at line 55.'
+  ];
+
   let options = yield helpers.openTab(TEST_URI);
   info("window open");
 
   // Wait for site to be cached.
   yield helpers.listenOnce(gBrowser.contentWindow.applicationCache, 'error');
   info("applicationCache error happened");
 
   yield helpers.openToolbar(options);
   info("toolbar open");
 
   // Pages containing an appcache the notification bar gives options to allow
   // or deny permission for the app to save data offline. Let's click Allow.
   let notificationID = "offline-app-requested-sub1.test1.example.com";
-  let notification = PopupNotifications.getNotification(notificationID, gBrowser.selectedBrowser);
+  let notification =
+    PopupNotifications.getNotification(notificationID, gBrowser.selectedBrowser);
 
   if (notification) {
     info("Authorizing offline storage.");
     notification.mainAction.callback();
   } else {
     info("No notification box is available.");
   }
 
@@ -40,61 +105,16 @@ function spawnTest() {
       setup: 'appcache validate',
       check: {
         input:  'appcache validate',
         markup: 'VVVVVVVVVVVVVVVVV',
         status: 'VALID',
         args: {}
       },
       exec: {
-        output: [
-          /Manifest has a character encoding of ISO-8859-1\. Manifests must have the utf-8 character encoding\./,
-          /The first line of the manifest must be "CACHE MANIFEST" at line 1\./,
-          /"CACHE MANIFEST" is only valid on the first line but was found at line 3\./,
-          /images\/sound-icon\.png points to a resource that is not available at line 9\./,
-          /images\/background\.png points to a resource that is not available at line 10\./,
-          /NETWORK section line 13 \(\/checking\.cgi\) prevents caching of line 13 \(\/checking\.cgi\) in the NETWORK section\./,
-          /\/checking\.cgi points to a resource that is not available at line 13\./,
-          /Asterisk \(\*\) incorrectly used in the NETWORK section at line 14\. If a line in the NETWORK section contains only a single asterisk character, then any URI not listed in the manifest will be treated as if the URI was listed in the NETWORK section\. Otherwise such URIs will be treated as unavailable\. Other uses of the \* character are prohibited/,
-          /\.\.\/rel\.html points to a resource that is not available at line 17\./,
-          /\.\.\/\.\.\/rel\.html points to a resource that is not available at line 18\./,
-          /\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 19\./,
-          /\.\.\/\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 20\./,
-          /\.\.\/\.\.\/\.\.\/\.\.\/\.\.\/rel\.html points to a resource that is not available at line 21\./,
-          /\/\.\.\/ is not a valid URI prefix at line 22\./,
-          /\/test\.css points to a resource that is not available at line 23\./,
-          /\/test\.js points to a resource that is not available at line 24\./,
-          /test\.png points to a resource that is not available at line 25\./,
-          /\/main\/features\.js points to a resource that is not available at line 27\./,
-          /\/main\/settings\/index\.css points to a resource that is not available at line 28\./,
-          /http:\/\/example\.com\/scene\.jpg points to a resource that is not available at line 29\./,
-          /\/section1\/blockedbyfallback\.html points to a resource that is not available at line 30\./,
-          /http:\/\/example\.com\/images\/world\.jpg points to a resource that is not available at line 31\./,
-          /\/section2\/blockedbyfallback\.html points to a resource that is not available at line 32\./,
-          /\/main\/home points to a resource that is not available at line 34\./,
-          /main\/app\.js points to a resource that is not available at line 35\./,
-          /\/settings\/home points to a resource that is not available at line 37\./,
-          /\/settings\/app\.js points to a resource that is not available at line 38\./,
-          /The file http:\/\/sub1\.test1\.example\.com\/browser\/browser\/devtools\/commandline\/test\/browser_cmd_appcache_invalid_page3\.html was modified after http:\/\/sub1\.test1\.example\.com\/browser\/browser\/devtools\/commandline\/test\/browser_cmd_appcache_invalid_appcache\.appcache\. Unless the text in the manifest file is changed the cached version will be used instead at line 39\./,
-          /browser_cmd_appcache_invalid_page3\.html has cache-control set to no-store\. This will prevent the application cache from storing the file at line 39\./,
-          /http:\/\/example\.com\/logo\.png points to a resource that is not available at line 40\./,
-          /http:\/\/example\.com\/check\.png points to a resource that is not available at line 41\./,
-          /Spaces in URIs need to be replaced with % at line 42\./,
-          /http:\/\/example\.com\/cr oss\.png points to a resource that is not available at line 42\./,
-          /Asterisk \(\*\) incorrectly used in the CACHE section at line 43\. If a line in the NETWORK section contains only a single asterisk character, then any URI not listed in the manifest will be treated as if the URI was listed in the NETWORK section\. Otherwise such URIs will be treated as unavailable\. Other uses of the \* character are prohibited/,
-          /The SETTINGS section may only contain a single value, "prefer-online" or "fast" at line 47\./,
-          /FALLBACK section line 50 \(\/section1\/ \/offline1\.html\) prevents caching of line 30 \(\/section1\/blockedbyfallback\.html\) in the CACHE section\./,
-          /\/offline1\.html points to a resource that is not available at line 50\./,
-          /FALLBACK section line 51 \(\/section2\/ offline2\.html\) prevents caching of line 32 \(\/section2\/blockedbyfallback\.html\) in the CACHE section\./,
-          /offline2\.html points to a resource that is not available at line 51\./,
-          /Only two URIs separated by spaces are allowed in the FALLBACK section at line 52\./,
-          /Asterisk \(\*\) incorrectly used in the FALLBACK section at line 53\. URIs in the FALLBACK section simply need to match a prefix of the request URI\./,
-          /offline3\.html points to a resource that is not available at line 53\./,
-          /Invalid section name \(BLAH\) at line 55\./,
-          /Only two URIs separated by spaces are allowed in the FALLBACK section at line 55\./
-        ]
+        output: lines.map(getRegexForString)
       },
     },
   ]);
 
   yield helpers.closeToolbar(options);
   yield helpers.closeTab(options);
 }
--- a/browser/devtools/commandline/test/head.js
+++ b/browser/devtools/commandline/test/head.js
@@ -23,16 +23,30 @@ function whenDelayedStartupFinished(aWin
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
       executeSoon(aCallback);
     }
   }, "browser-delayed-startup-finished", false);
 }
 
 /**
+ * Creates a regular expression that matches a string. This greatly simplifies
+ * matching and debugging long strings.
+ *
+ * @param {String} text
+ *        Text to convert
+ * @return {RegExp}
+ *         Regular expression matching text
+ */
+function getRegexForString(str) {
+  str = str.replace(/(\.|\\|\/|\(|\)|\[|\]|\*|\+|\?|\$|\^|\|)/g, "\\$1");
+  return new RegExp(str);
+}
+
+/**
  * Force GC on shutdown, because it seems that GCLI can outrun the garbage
  * collector in some situations, which causes test failures in later tests
  * Bug 774619 is an example.
  */
 registerCleanupFunction(function tearDown() {
   window.QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIDOMWindowUtils)
       .garbageCollect();
--- a/browser/devtools/inspector/test/browser_inspector_highlighter.js
+++ b/browser/devtools/inspector/test/browser_inspector_highlighter.js
@@ -1,115 +1,80 @@
 /* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 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/. */
 
 let doc;
-let h1;
+let div;
+let rotated;
 let inspector;
+let contentViewer;
 
 function createDocument() {
-  let div = doc.createElement("div");
-  h1 = doc.createElement("h1");
-  let p1 = doc.createElement("p");
-  let p2 = doc.createElement("p");
-  let div2 = doc.createElement("div");
-  let p3 = doc.createElement("p");
-  doc.title = "Inspector Highlighter Meatballs";
-  h1.textContent = "Inspector Tree Selection Test";
-  p1.textContent = "This is some example text";
-  p2.textContent = "Lorem ipsum dolor sit amet, consectetur adipisicing " +
-    "elit, sed do eiusmod tempor incididunt ut labore et dolore magna " +
-    "aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
-    "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
-    "dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
-    "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " +
-    "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
-  p3.textContent = "Lorem ipsum dolor sit amet, consectetur adipisicing " +
-    "elit, sed do eiusmod tempor incididunt ut labore et dolore magna " +
-    "aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
-    "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
-    "dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
-    "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " +
-    "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
-  let div3 = doc.createElement("div");
-  div3.id = "checkOutThisWickedSpread";
-  div3.setAttribute("style", "position: absolute; top: 20px; right: 20px; height: 20px; width: 20px; background-color: yellow; border: 1px dashed black;");
-  let p4 = doc.createElement("p");
-  p4.setAttribute("style", "font-weight: 200; font-size: 8px; text-align: center;");
-  p4.textContent = "Smörgåsbord!";
-  div.appendChild(h1);
-  div.appendChild(p1);
-  div.appendChild(p2);
-  div2.appendChild(p3);
-  div3.appendChild(p4);
+  div = doc.createElement("div");
+  div.setAttribute("style",
+                   "padding:5px; border:7px solid red; margin: 9px; " +
+                   "position:absolute; top:30px; left:150px;");
+  let textNode = doc.createTextNode("Gort! Klaatu barada nikto!");
+  rotated = doc.createElement("div");
+  rotated.setAttribute("style",
+                       "padding:5px; border:7px solid red; margin: 9px; " +
+                       "transform:rotate(45deg); " +
+                       "position:absolute; top:30px; left:80px;");
+  div.appendChild(textNode);
   doc.body.appendChild(div);
-  doc.body.appendChild(div2);
-  doc.body.appendChild(div3);
+  doc.body.appendChild(rotated);
 
   openInspector(aInspector => {
     inspector = aInspector;
     inspector.selection.setNode(div, null);
-    inspector.once("inspector-updated", () => {
-      inspector.toolbox.highlighterUtils.startPicker().then(testMouseOverH1Highlights);
-    });
+    inspector.once("inspector-updated", testMouseOverDivHighlights);
   });
 }
 
-function testMouseOverH1Highlights() {
-  inspector.toolbox.once("highlighter-ready", () => {
-    ok(isHighlighting(), "Highlighter is shown");
-    is(getHighlitNode(), h1, "Highlighter's outline correspond to the selected node");
-    testBoxModelDimensions();
-  });
+function testMouseOverDivHighlights() {
+  ok(isHighlighting(), "Highlighter is shown");
+  is(getHighlitNode(), div, "Highlighter's outline correspond to the non-rotated div");
+  testNonTransformedBoxModelDimensionsNoZoom();
+}
 
-  EventUtils.synthesizeMouse(h1, 2, 2, {type: "mousemove"}, content);
+function testNonTransformedBoxModelDimensionsNoZoom() {
+  info("Highlighted the non-rotated div");
+  isNodeCorrectlyHighlighted(div, "non-zoomed");
+
+  inspector.toolbox.once("highlighter-ready", testNonTransformedBoxModelDimensionsZoomed);
+  contentViewer = gBrowser.selectedBrowser.docShell.contentViewer
+                          .QueryInterface(Ci.nsIMarkupDocumentViewer);
+  contentViewer.fullZoom = 2;
 }
 
-function testBoxModelDimensions() {
-  let h1Dims = h1.getBoundingClientRect();
-  let h1Width = Math.ceil(h1Dims.width);
-  let h1Height = Math.ceil(h1Dims.height);
+function testNonTransformedBoxModelDimensionsZoomed() {
+  info("Highlighted the zoomed, non-rotated div");
+  isNodeCorrectlyHighlighted(div, "zoomed");
 
-  let outlineDims = getSimpleBorderRect();
-  let outlineWidth = Math.ceil(outlineDims.width);
-  let outlineHeight = Math.ceil(outlineDims.height);
-
-  // Disabled due to bug 716245
-  is(outlineWidth, h1Width, "outline width matches dimensions of element (no zoom)");
-  is(outlineHeight, h1Height, "outline height matches dimensions of element (no zoom)");
+  inspector.toolbox.once("highlighter-ready", testMouseOverRotatedHighlights);
+  contentViewer.fullZoom = 1;
+}
 
-  // zoom the page by a factor of 2
-  let contentViewer = gBrowser.selectedBrowser.docShell.contentViewer
-                             .QueryInterface(Ci.nsIMarkupDocumentViewer);
-  contentViewer.fullZoom = 2;
+function testMouseOverRotatedHighlights() {
+  inspector.toolbox.once("highlighter-ready", () => {
+    ok(isHighlighting(), "Highlighter is shown");
+    info("Highlighted the rotated div");
+    isNodeCorrectlyHighlighted(rotated, "rotated");
 
-  // simulate the zoomed dimensions of the div element
-  let h1Dims = h1.getBoundingClientRect();
-  // There seems to be some very minor differences in the floats, so let's
-  // floor the values
-  let h1Width = Math.floor(h1Dims.width * contentViewer.fullZoom);
-  let h1Height = Math.floor(h1Dims.height * contentViewer.fullZoom);
-
-  let outlineDims = getSimpleBorderRect();
-  let outlineWidth = Math.floor(outlineDims.width);
-  let outlineHeight = Math.floor(outlineDims.height);
-
-  is(outlineWidth, h1Width, "outline width matches dimensions of element (zoomed)");
-
-  is(outlineHeight, h1Height, "outline height matches dimensions of element (zoomed)");
-
-  executeSoon(finishUp);
+    executeSoon(finishUp);
+  });
+  inspector.selection.setNode(rotated);
 }
 
 function finishUp() {
   inspector.toolbox.highlighterUtils.stopPicker().then(() => {
-    doc = h1 = inspector = null;
+    doc = div = rotated = inspector = contentViewer = null;
     let target = TargetFactory.forTab(gBrowser.selectedTab);
     gDevTools.closeToolbox(target);
     gBrowser.removeCurrentTab();
     finish();
   });
 }
 
 function test() {
--- a/browser/devtools/inspector/test/browser_inspector_infobar.js
+++ b/browser/devtools/inspector/test/browser_inspector_infobar.js
@@ -12,29 +12,68 @@ function test() {
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function onload() {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     doc = content.document;
     waitForFocus(setupInfobarTest, content);
   }, true);
 
-  let style = "body{width:100%;height: 100%} div {position: absolute;height: 100px;width: 500px}#bottom {bottom: 0px}#vertical {height: 100%}#farbottom{bottom: -200px}";
-  let html = "<style>" + style + "</style><div id=vertical></div><div id=top class='class1 class2'></div><div id=bottom></div><div id=farbottom></div>"
+  let style = "body{width:100%;height: 100%} div {position: absolute;" +
+              "height: 100px;width: 500px}#bottom {bottom: 0px}#vertical {"+
+              "height: 100%}#farbottom{bottom: -200px}";
+  let html = "<style>" + style + "</style><div id=vertical></div>" +
+             "<div id=top class='class1 class2'></div><div id=bottom></div>" +
+             "<div id=farbottom></div>"
 
-  content.location = "data:text/html," + encodeURIComponent(html);
+  content.location = "data:text/html;charset=utf-8," + encodeURIComponent(html);
 
   function setupInfobarTest() {
     nodes = [
-      {node: doc.querySelector("#top"), position: "bottom", tag: "DIV", id: "#top", classes: ".class1.class2"},
-      {node: doc.querySelector("#vertical"), position: "overlap", tag: "DIV", id: "#vertical", classes: ""},
-      {node: doc.querySelector("#bottom"), position: "top", tag: "DIV", id: "#bottom", classes: ""},
-      {node: doc.querySelector("body"), position: "overlap", tag: "BODY", id: "", classes: ""},
-      {node: doc.querySelector("#farbottom"), position: "top", tag: "DIV", id: "#farbottom", classes: ""},
-    ]
+      {
+        node: doc.querySelector("#top"),
+        position: "bottom",
+        tag: "DIV",
+        id: "#top",
+        classes: ".class1.class2",
+        dims: "500 x 100"
+      },
+      {
+        node: doc.querySelector("#vertical"),
+        position: "overlap",
+        tag: "DIV",
+        id: "#vertical",
+        classes: ""
+        // No dims as they will vary between computers
+      },
+      {
+        node: doc.querySelector("#bottom"),
+        position: "top",
+        tag: "DIV",
+        id: "#bottom",
+        classes: "",
+        dims: "500 x 100"
+      },
+      {
+        node: doc.querySelector("body"),
+        position: "overlap",
+        tag: "BODY",
+        id: "",
+        classes: ""
+        // No dims as they will vary between computers
+      },
+      {
+        node: doc.querySelector("#farbottom"),
+        position: "top",
+        tag: "DIV",
+        id: "#farbottom",
+        classes: "",
+        dims: "500 x 100"
+      },
+    ];
 
     for (let i = 0; i < nodes.length; i++) {
       ok(nodes[i].node, "node " + i + " found");
     }
 
     openInspector(runTests);
   }
 
@@ -69,26 +108,34 @@ function test() {
     });
   }
 
   function performTest() {
     let browser = gBrowser.selectedBrowser;
     let stack = browser.parentNode;
 
     let container = stack.querySelector(".highlighter-nodeinfobar-positioner");
-    is(container.getAttribute("position"), nodes[cursor].position, "node " + cursor + ": position matches.");
+    is(container.getAttribute("position"),
+      nodes[cursor].position, "node " + cursor + ": position matches.");
 
     let tagNameLabel = stack.querySelector(".highlighter-nodeinfobar-tagname");
-    is(tagNameLabel.textContent, nodes[cursor].tag, "node " + cursor  + ": tagName matches.");
+    is(tagNameLabel.textContent, nodes[cursor].tag,
+      "node " + cursor  + ": tagName matches.");
 
     let idLabel = stack.querySelector(".highlighter-nodeinfobar-id");
     is(idLabel.textContent, nodes[cursor].id, "node " + cursor  + ": id matches.");
 
     let classesBox = stack.querySelector(".highlighter-nodeinfobar-classes");
-    is(classesBox.textContent, nodes[cursor].classes, "node " + cursor  + ": classes match.");
+    is(classesBox.textContent, nodes[cursor].classes,
+      "node " + cursor  + ": classes match.");
+
+    if (nodes[cursor].dims) {
+      let dimBox = stack.querySelector(".highlighter-nodeinfobar-dimensions");
+      is(dimBox.textContent, nodes[cursor].dims, "node " + cursor  + ": dims match.");
+    }
   }
 
   function finishUp() {
     doc = nodes = null;
     gBrowser.removeCurrentTab();
     finish();
   }
 }
--- a/browser/devtools/inspector/test/head.js
+++ b/browser/devtools/inspector/test/head.js
@@ -395,17 +395,17 @@ function focusSearchBoxUsingShortcut(pan
   isnot(name, null, "Successfully retrieved keycode/key");
 
   let modifiers = {
     shiftKey: modifiersAttr.match("shift"),
     ctrlKey: modifiersAttr.match("ctrl"),
     altKey: modifiersAttr.match("alt"),
     metaKey: modifiersAttr.match("meta"),
     accelKey: modifiersAttr.match("accel")
-  }
+  };
 
   let searchBox = panelWin.document.getElementById("inspector-searchbox");
   searchBox.addEventListener("focus", function onFocus() {
     searchBox.removeEventListener("focus", onFocus, false);
     callback && callback();
   }, false);
   EventUtils.synthesizeKey(name, modifiers);
 }
@@ -420,16 +420,70 @@ function getComputedPropertyValue(aName)
 
     if (name.textContent === aName) {
       let value = prop.querySelector(".property-value");
       return value.textContent;
     }
   }
 }
 
+function isNodeCorrectlyHighlighted(node, prefix="") {
+  let boxModel = getBoxModelStatus();
+  let helper = new LayoutHelpers(window.content);
+
+  prefix += (prefix ? " " : "") + node.nodeName;
+  prefix += (node.id ? "#" + node.id : "");
+  prefix += (node.classList.length ? "." + [...node.classList].join(".") : "");
+  prefix += " ";
+
+  let quads = helper.getAdjustedQuads(node, "content");
+  let {p1:cp1, p2:cp2, p3:cp3, p4:cp4} = boxModel.content.points;
+  is(cp1.x, quads.p1.x, prefix + "content point 1 x co-ordinate is correct");
+  is(cp1.y, quads.p1.y, prefix + "content point 1 y co-ordinate is correct");
+  is(cp2.x, quads.p2.x, prefix + "content point 2 x co-ordinate is correct");
+  is(cp2.y, quads.p2.y, prefix + "content point 2 y co-ordinate is correct");
+  is(cp3.x, quads.p3.x, prefix + "content point 3 x co-ordinate is correct");
+  is(cp3.y, quads.p3.y, prefix + "content point 3 y co-ordinate is correct");
+  is(cp4.x, quads.p4.x, prefix + "content point 4 x co-ordinate is correct");
+  is(cp4.y, quads.p4.y, prefix + "content point 4 y co-ordinate is correct");
+
+  quads = helper.getAdjustedQuads(node, "padding");
+  let {p1:pp1, p2:pp2, p3:pp3, p4:pp4} = boxModel.padding.points;
+  is(pp1.x, quads.p1.x, prefix + "padding point 1 x co-ordinate is correct");
+  is(pp1.y, quads.p1.y, prefix + "padding point 1 y co-ordinate is correct");
+  is(pp2.x, quads.p2.x, prefix + "padding point 2 x co-ordinate is correct");
+  is(pp2.y, quads.p2.y, prefix + "padding point 2 y co-ordinate is correct");
+  is(pp3.x, quads.p3.x, prefix + "padding point 3 x co-ordinate is correct");
+  is(pp3.y, quads.p3.y, prefix + "padding point 3 y co-ordinate is correct");
+  is(pp4.x, quads.p4.x, prefix + "padding point 4 x co-ordinate is correct");
+  is(pp4.y, quads.p4.y, prefix + "padding point 4 y co-ordinate is correct");
+
+  quads = helper.getAdjustedQuads(node, "border");
+  let {p1:bp1, p2:bp2, p3:bp3, p4:bp4} = boxModel.border.points;
+  is(bp1.x, quads.p1.x, prefix + "border point 1 x co-ordinate is correct");
+  is(bp1.y, quads.p1.y, prefix + "border point 1 y co-ordinate is correct");
+  is(bp2.x, quads.p2.x, prefix + "border point 2 x co-ordinate is correct");
+  is(bp2.y, quads.p2.y, prefix + "border point 2 y co-ordinate is correct");
+  is(bp3.x, quads.p3.x, prefix + "border point 3 x co-ordinate is correct");
+  is(bp3.y, quads.p3.y, prefix + "border point 3 y co-ordinate is correct");
+  is(bp4.x, quads.p4.x, prefix + "border point 4 x co-ordinate is correct");
+  is(bp4.y, quads.p4.y, prefix + "border point 4 y co-ordinate is correct");
+
+  quads = helper.getAdjustedQuads(node, "margin");
+  let {p1:mp1, p2:mp2, p3:mp3, p4:mp4} = boxModel.margin.points;
+  is(mp1.x, quads.p1.x, prefix + "margin point 1 x co-ordinate is correct");
+  is(mp1.y, quads.p1.y, prefix + "margin point 1 y co-ordinate is correct");
+  is(mp2.x, quads.p2.x, prefix + "margin point 2 x co-ordinate is correct");
+  is(mp2.y, quads.p2.y, prefix + "margin point 2 y co-ordinate is correct");
+  is(mp3.x, quads.p3.x, prefix + "margin point 3 x co-ordinate is correct");
+  is(mp3.y, quads.p3.y, prefix + "margin point 3 y co-ordinate is correct");
+  is(mp4.x, quads.p4.x, prefix + "margin point 4 x co-ordinate is correct");
+  is(mp4.y, quads.p4.y, prefix + "margin point 4 y co-ordinate is correct");
+}
+
 function getContainerForRawNode(markupView, rawNode)
 {
   let front = markupView.walker.frontForRawNode(rawNode);
   let container = markupView.getContainer(front);
   return container;
 }
 
 SimpleTest.registerCleanupFunction(function () {
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -80,16 +80,19 @@ function MarkupView(aInspector, aFrame, 
   this.undo = new UndoStack();
   this.undo.installController(aControllerWindow);
 
   this._containers = new Map();
 
   this._boundMutationObserver = this._mutationObserver.bind(this);
   this.walker.on("mutations", this._boundMutationObserver);
 
+  this._boundOnDisplayChange = this._onDisplayChange.bind(this);
+  this.walker.on("display-change", this._boundOnDisplayChange);
+
   this._boundOnNewSelection = this._onNewSelection.bind(this);
   this._inspector.selection.on("new-node-front", this._boundOnNewSelection);
   this._onNewSelection();
 
   this._boundKeyDown = this._onKeyDown.bind(this);
   this._frame.contentWindow.addEventListener("keydown", this._boundKeyDown, false);
 
   this._boundFocus = this._onFocus.bind(this);
@@ -610,16 +613,29 @@ MarkupView.prototype = {
           }
         });
 
       }
     });
   },
 
   /**
+   * React to display-change events from the walker
+   * @param {Array} nodes An array of nodeFronts
+   */
+  _onDisplayChange: function(nodes) {
+    for (let node of nodes) {
+      let container = this._containers.get(node);
+      if (container) {
+        container.isDisplayed = node.isDisplayed;
+      }
+    }
+  },
+
+  /**
    * Given a list of mutations returned by the mutation observer, flash the
    * corresponding containers to attract attention.
    */
   _flashMutatedNodes: function(aMutations) {
     let addedOrEditedContainers = new Set();
     let removedContainers = new Set();
 
     for (let {type, target, added, removed} of aMutations) {
@@ -1105,16 +1121,19 @@ MarkupView.prototype = {
     this._boundKeyDown = null;
 
     this._inspector.selection.off("new-node-front", this._boundOnNewSelection);
     this._boundOnNewSelection = null;
 
     this.walker.off("mutations", this._boundMutationObserver)
     this._boundMutationObserver = null;
 
+    this.walker.off("display-change", this._boundOnDisplayChange);
+    this._boundOnDisplayChange = null;
+
     this._elt.removeEventListener("mousemove", this._onMouseMove, false);
     this._elt.removeEventListener("mouseleave", this._onMouseLeave, false);
     this._elt = null;
 
     for (let [key, container] of this._containers) {
       container.destroy();
     }
     this._containers = null;
@@ -1263,16 +1282,19 @@ function MarkupContainer(aMarkupView, aN
   // Appending the editor element and attaching event listeners
   this.tagLine.appendChild(this.editor.elt);
 
   this._onMouseDown = this._onMouseDown.bind(this);
   this.elt.addEventListener("mousedown", this._onMouseDown, false);
 
   // Prepare the image preview tooltip data if any
   this._prepareImagePreview();
+
+  // Marking the node as shown or hidden
+  this.isDisplayed = this.node.isDisplayed;
 }
 
 MarkupContainer.prototype = {
   toString: function() {
     return "[MarkupContainer for " + this.node + "]";
   },
 
   isPreviewable: function() {
@@ -1337,16 +1359,26 @@ MarkupContainer.prototype = {
 
     return this.tooltipData.data.then(({data, size}) => {
       tooltip.setImageContent(data, size);
     }, () => {
       tooltip.setBrokenImageContent();
     });
   },
 
+  /**
+   * Show the element has displayed or not
+   */
+  set isDisplayed(isDisplayed) {
+    this.elt.classList.remove("not-displayed");
+    if (!isDisplayed) {
+      this.elt.classList.add("not-displayed");
+    }
+  },
+
   copyImageDataUri: function() {
     // We need to send again a request to gettooltipData even if one was sent for
     // the tooltip, because we want the full-size image
     this.node.getImageData().then(data => {
       data.data.string().then(str => {
         clipboardHelper.copyString(str, this.markup.doc);
       });
     });
--- a/browser/devtools/markupview/test/browser.ini
+++ b/browser/devtools/markupview/test/browser.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
 subsuite = devtools
 support-files =
   doc_markup_edit.html
   doc_markup_flashing.html
   doc_markup_mutation.html
   doc_markup_navigation.html
+  doc_markup_not_displayed.html
   doc_markup_pagesize_01.html
   doc_markup_pagesize_02.html
   doc_markup_search.html
   doc_markup_toggle.html
   doc_markup_tooltip.png
   head.js
   helper_attributes_test_runner.js
   helper_outerhtml_test_runner.js
@@ -21,16 +22,18 @@ support-files =
 [browser_markupview_highlight_hover_02.js]
 [browser_markupview_html_edit_01.js]
 [browser_markupview_html_edit_02.js]
 [browser_markupview_html_edit_03.js]
 [browser_markupview_image_tooltip.js]
 [browser_markupview_mutation_01.js]
 [browser_markupview_mutation_02.js]
 [browser_markupview_navigation.js]
+[browser_markupview_node_not_displayed_01.js]
+[browser_markupview_node_not_displayed_02.js]
 [browser_markupview_pagesize_01.js]
 [browser_markupview_pagesize_02.js]
 [browser_markupview_search_01.js]
 [browser_markupview_tag_edit_01.js]
 [browser_markupview_tag_edit_02.js]
 [browser_markupview_tag_edit_03.js]
 [browser_markupview_tag_edit_04.js]
 [browser_markupview_tag_edit_05.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/browser_markupview_node_not_displayed_01.js
@@ -0,0 +1,33 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that nodes that are not displayed appear differently in the markup-view
+// when these nodes are imported in the view.
+
+// Note that nodes inside a display:none parent are obviously not displayed too
+// but the markup-view uses css inheritance to mark those as hidden instead of
+// having to visit each and every child of a hidden node. So there's no sense
+// testing children nodes.
+
+const TEST_URL = TEST_URL_ROOT + "doc_markup_not_displayed.html";
+const TEST_DATA = [
+  {selector: "#normal-div", isDisplayed: true},
+  {selector: "head", isDisplayed: false},
+  {selector: "#display-none", isDisplayed: false},
+  {selector: "#hidden-true", isDisplayed: false},
+  {selector: "#visibility-hidden", isDisplayed: true}
+];
+
+let test = asyncTest(function*() {
+  let {inspector} = yield addTab(TEST_URL).then(openInspector);
+
+  for (let {selector, isDisplayed} of TEST_DATA) {
+    info("Getting node " + selector);
+    let container = getContainerForRawNode(selector, inspector);
+    is(!container.elt.classList.contains("not-displayed"), isDisplayed,
+      "The container for " + selector + " is marked as displayed " + isDisplayed);
+  }
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/browser_markupview_node_not_displayed_02.js
@@ -0,0 +1,132 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that nodes are marked as displayed and not-displayed dynamically, when
+// their display changes
+
+const TEST_URL = TEST_URL_ROOT + "doc_markup_not_displayed.html";
+const TEST_DATA = [
+  {
+    desc: "Hiding a node by creating a new stylesheet",
+    selector: "#normal-div",
+    before: true,
+    changeStyle: (doc, node) => {
+      let div = doc.createElement("div");
+      div.id = "new-style";
+      div.innerHTML = "<style>#normal-div {display:none;}</style>";
+      doc.body.appendChild(div);
+    },
+    after: false
+  },
+  {
+    desc: "Showing a node by deleting an existing stylesheet",
+    selector: "#normal-div",
+    before: false,
+    changeStyle: (doc, node) => {
+      doc.getElementById("new-style").remove();
+    },
+    after: true
+  },
+  {
+    desc: "Hiding a node by changing its style property",
+    selector: "#display-none",
+    before: false,
+    changeStyle: (doc, node) => {
+      node.style.display = "block";
+    },
+    after: true
+  },
+  {
+    desc: "Showing a node by removing its hidden attribute",
+    selector: "#hidden-true",
+    before: false,
+    changeStyle: (doc, node) => {
+      node.removeAttribute("hidden");
+    },
+    after: true
+  },
+  {
+    desc: "Hiding a node by adding a hidden attribute",
+    selector: "#hidden-true",
+    before: true,
+    changeStyle: (doc, node) => {
+      node.setAttribute("hidden", "true");
+    },
+    after: false
+  },
+  {
+    desc: "Showing a node by changin a stylesheet's rule",
+    selector: "#hidden-via-stylesheet",
+    before: false,
+    changeStyle: (doc, node) => {
+      doc.styleSheets[0].cssRules[0].style.setProperty("display", "inline");
+    },
+    after: true
+  },
+  {
+    desc: "Hiding a node by adding a new rule to a stylesheet",
+    selector: "#hidden-via-stylesheet",
+    before: true,
+    changeStyle: (doc, node) => {
+      doc.styleSheets[0].insertRule(
+        "#hidden-via-stylesheet {display: none;}", 1);
+    },
+    after: false
+  },
+  {
+    desc: "Hiding a node by adding a class that matches an existing rule",
+    selector: "#normal-div",
+    before: true,
+    changeStyle: (doc, node) => {
+      doc.styleSheets[0].insertRule(
+        ".a-new-class {display: none;}", 2);
+      node.classList.add("a-new-class");
+    },
+    after: false
+  }
+];
+
+let test = asyncTest(function*() {
+  let {inspector} = yield addTab(TEST_URL).then(openInspector);
+
+  for (let data of TEST_DATA) {
+    info("Running test case: " + data.desc);
+    yield runTestData(inspector, data);
+  }
+});
+
+function runTestData(inspector, {selector, before, changeStyle, after}) {
+  let def = promise.defer();
+
+  info("Getting the " + selector + " test node");
+  let container = getContainerForRawNode(selector, inspector);
+  is(!container.elt.classList.contains("not-displayed"), before,
+    "The container is marked as " + (before ? "shown" : "hidden"));
+
+  info("Listening for the display-change event");
+  inspector.markup.walker.once("display-change", nodes => {
+    info("Verifying that the list of changed nodes include our container");
+
+    ok(nodes.length, "The display-change event was received with a nodes");
+    let foundContainer = false;
+    for (let node of nodes) {
+      if (inspector.markup.getContainer(node) === container) {
+        foundContainer = true;
+        break;
+      }
+    }
+    ok(foundContainer, "Container is part of the list of changed nodes");
+
+    is(!container.elt.classList.contains("not-displayed"), after,
+      "The container is marked as " + (after ? "shown" : "hidden"));
+    def.resolve();
+  });
+
+  info("Making style changes");
+  changeStyle(content.document, getNode(selector));
+
+  return def.promise;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/doc_markup_not_displayed.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    #hidden-via-stylesheet {
+      display: none;
+    }
+  </style>
+</head>
+<body>
+  <div id="normal-div"></div>
+  <div id="display-none" style="display:none;"></div>
+  <div id="hidden-true" hidden="true"></div>
+  <div id="visibility-hidden" style="visibility:hidden;"></div>
+  <div id="hidden-via-stylesheet"></div>
+</body>
+</html>
\ No newline at end of file
--- a/browser/devtools/shared/AppCacheUtils.jsm
+++ b/browser/devtools/shared/AppCacheUtils.jsm
@@ -24,16 +24,17 @@
  */
 
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 let { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
 let { Services }   = Cu.import("resource://gre/modules/Services.jsm", {});
+let { LoadContextInfo } = Cu.import("resource://gre/modules/LoadContextInfo.jsm", {});
 let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
 
 this.EXPORTED_SYMBOLS = ["AppCacheUtils"];
 
 function AppCacheUtils(documentOrUri) {
   this._parseManifest = this._parseManifest.bind(this);
 
   if (documentOrUri) {
@@ -113,17 +114,18 @@ AppCacheUtils.prototype = {
       }
     }
 
     // Loop through network entries making sure that fallback and cache don't
     // contain uris starting with the network uri.
     for (let neturi of parsed.uris) {
       if (neturi.section == "NETWORK") {
         for (let parsedUri of parsed.uris) {
-          if (parsedUri.uri.startsWith(neturi.uri)) {
+          if (parsedUri.section !== "NETWORK" &&
+              parsedUri.uri.startsWith(neturi.uri)) {
             this._addError(neturi.line, "networkBlocksURI", neturi.line,
                            neturi.original, parsedUri.line, parsedUri.original,
                            parsedUri.section);
           }
         }
       }
     }
 
@@ -159,17 +161,17 @@ AppCacheUtils.prototype = {
           }
 
           // If cache-control: no-store the file will not be added to the
           // appCache.
           if (uriInfo.nocache) {
             this._addError(parsedUri.line, "cacheControlNoStore",
                            parsedUri.original, parsedUri.line);
           }
-        } else {
+        } else if (parsedUri.original !== "*") {
           this._addError(parsedUri.line, "notAvailable",
                          parsedUri.original, parsedUri.line);
         }
 
         if (current == len - 1) {
           deferred.resolve();
         }
       });
@@ -177,17 +179,16 @@ AppCacheUtils.prototype = {
 
     return deferred.promise;
   },
 
   _getURIInfo: function ACU__getURIInfo(uri) {
     let inputStream = Cc["@mozilla.org/scriptableinputstream;1"]
                         .createInstance(Ci.nsIScriptableInputStream);
     let deferred = promise.defer();
-    let channelCharset = "";
     let buffer = "";
     let channel = Services.io.newChannel(uri, null, null);
 
     // Avoid the cache:
     channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
     channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
 
     channel.asyncOpen({
@@ -198,17 +199,17 @@ AppCacheUtils.prototype = {
 
       onDataAvailable: function (request, context, stream, offset, count) {
         request.QueryInterface(Ci.nsIHttpChannel);
         inputStream.init(stream);
         buffer = buffer.concat(inputStream.read(count));
       },
 
       onStopRequest: function onStartRequest(request, context, statusCode) {
-        if (statusCode == 0) {
+        if (statusCode === 0) {
           request.QueryInterface(Ci.nsIHttpChannel);
 
           let result = {
             name: request.name,
             success: request.requestSucceeded,
             status: request.responseStatus + " - " + request.responseStatusText,
             charset: request.contentCharset || "utf-8",
             mimeType: request.contentType,
@@ -242,108 +243,92 @@ AppCacheUtils.prototype = {
 
   listEntries: function ACU_show(searchTerm) {
     if (!Services.prefs.getBoolPref("browser.cache.disk.enable")) {
       throw new Error(l10n.GetStringFromName("cacheDisabled"));
     }
 
     let entries = [];
 
-    Services.cache.visitEntries({
-      visitDevice: function(deviceID, deviceInfo) {
-        return true;
-      },
+    let appCacheStorage = Services.cache2.appCacheStorage(LoadContextInfo.default, null);
+    appCacheStorage.asyncVisitStorage({
+      onCacheStorageInfo: function() {},
 
-      visitEntry: function(deviceID, entryInfo) {
-        if (entryInfo.deviceID == "offline") {
-          let entry = {};
-          let lowerKey = entryInfo.key.toLowerCase();
+      onCacheEntryInfo: function(aURI, aIdEnhance, aDataSize, aFetchCount, aLastModifiedTime, aExpirationTime) {
+        let lowerKey = aURI.asciiSpec.toLowerCase();
 
-          if (searchTerm && lowerKey.indexOf(searchTerm.toLowerCase()) == -1) {
-            return true;
-          }
+        if (searchTerm && lowerKey.indexOf(searchTerm.toLowerCase()) == -1) {
+          return;
+        }
 
-          for (let [key, value] of Iterator(entryInfo)) {
-            if (key == "QueryInterface") {
-              continue;
-            }
-            if (key == "clientID") {
-              entry.key = entryInfo.key;
-            }
-            if (key == "expirationTime" || key == "lastFetched" || key == "lastModified") {
-              value = new Date(value * 1000);
-            }
-            entry[key] = value;
-          }
-          entries.push(entry);
+        if (aIdEnhance) {
+          aIdEnhance += ":";
         }
+
+        let entry = {
+          "deviceID": "offline",
+          "key": aIdEnhance + aURI.asciiSpec,
+          "fetchCount": aFetchCount,
+          "lastFetched": null,
+          "lastModified": new Date(aLastModifiedTime * 1000),
+          "expirationTime": new Date(aExpirationTime * 1000),
+          "dataSize": aDataSize
+        };
+
+        entries.push(entry);
         return true;
       }
-    });
+    }, true);
 
-    if (entries.length == 0) {
+    if (entries.length === 0) {
       throw new Error(l10n.GetStringFromName("noResults"));
     }
     return entries;
   },
 
   viewEntry: function ACU_viewEntry(key) {
-    let uri;
-
-    Services.cache.visitEntries({
-      visitDevice: function(deviceID, deviceInfo) {
-        return true;
-      },
-
-      visitEntry: function(deviceID, entryInfo) {
-        if (entryInfo.deviceID == "offline" && entryInfo.key == key) {
-          uri = "about:cache-entry?client=" + entryInfo.clientID +
-                "&sb=1&key=" + entryInfo.key;
-          return false;
-        }
-        return true;
-      }
-    });
-
-    if (uri) {
-      let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
-                 .getService(Ci.nsIWindowMediator);
-      let win = wm.getMostRecentWindow("navigator:browser");
-      win.gBrowser.selectedTab = win.gBrowser.addTab(uri);
-    } else {
-      return l10n.GetStringFromName("entryNotFound");
-    }
+    let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
+               .getService(Ci.nsIWindowMediator);
+    let win = wm.getMostRecentWindow("navigator:browser");
+    win.gBrowser.selectedTab = win.gBrowser.addTab(
+      "about:cache-entry?storage=appcache&context=&eid=&uri=" + key);
   },
 
   clearAll: function ACU_clearAll() {
     Services.cache.evictEntries(Ci.nsICache.STORE_OFFLINE);
   },
 
   _getManifestURI: function ACU__getManifestURI() {
     let deferred = promise.defer();
 
-    let getURI = node => {
+    let getURI = () => {
       let htmlNode = this.doc.querySelector("html[manifest]");
       if (htmlNode) {
         let pageUri = this.doc.location ? this.doc.location.href : this.uri;
         let origin = pageUri.substr(0, pageUri.lastIndexOf("/") + 1);
-        return origin + htmlNode.getAttribute("manifest");
+        let manifestURI = htmlNode.getAttribute("manifest");
+
+        if (manifestURI.startsWith("/")) {
+          manifestURI = manifestURI.substr(1);
+        }
+
+        return origin + manifestURI;
       }
     };
 
     if (this.doc) {
-      let uri = getURI(this.doc);
+      let uri = getURI();
       return promise.resolve(uri);
     } else {
       this._getURIInfo(this.uri).then(uriInfo => {
         if (uriInfo.success) {
           let html = uriInfo.text;
           let parser = _DOMParser;
           this.doc = parser.parseFromString(html, "text/html");
-          let uri = getURI(this.doc);
+          let uri = getURI();
           deferred.resolve(uri);
         } else {
           this.errors.push({
             line: 0,
             msg: l10n.GetStringFromName("invalidURI")
           });
         }
       });
@@ -389,20 +374,20 @@ ManifestParser.prototype = {
     let fallbacks = this.fallbacks = [];
     let settings = this.settings = [];
     let errors = this.errors = [];
     let uris = this.uris = [];
 
     this.currSection = "CACHE";
 
     for (let i = 0; i < lines.length; i++) {
-      let text = this.text = lines[i].replace(/^\s+|\s+$/g);
+      let text = this.text = lines[i].trim();
       this.currentLine = i + 1;
 
-      if (i == 0 && text != "CACHE MANIFEST") {
+      if (i === 0 && text !== "CACHE MANIFEST") {
         this._addError(1, "firstLineMustBeCacheManifest", 1);
       }
 
       // Ignore comments
       if (/^#/.test(text) || !text.length) {
         continue;
       }
 
@@ -448,17 +433,17 @@ ManifestParser.prototype = {
         this._addError(this.currentLine, "asteriskInWrongSection2",
                        this.currSection, this.currentLine);
         return;
       }
     }
 
     if (/\s/.test(text)) {
       this._addError(this.currentLine, "escapeSpaces", this.currentLine);
-      text = text.replace(/\s/g, "%20")
+      text = text.replace(/\s/g, "%20");
     }
 
     if (text[0] == "/") {
       if (text.substr(0, 4) == "/../") {
         this._addError(this.currentLine, "slashDotDotSlashBad", this.currentLine);
       } else {
         this.uris.push(this._wrapURI(this.origin + text.substring(1)));
       }
@@ -501,17 +486,17 @@ ManifestParser.prototype = {
     let [ namespace, fallback ] = split;
 
     if (namespace.indexOf("*") != -1) {
       this._addError(this.currentLine, "fallbackAsterisk2", this.currentLine);
     }
 
     if (/\s/.test(namespace)) {
       this._addError(this.currentLine, "escapeSpaces", this.currentLine);
-      namespace = namespace.replace(/\s/g, "%20")
+      namespace = namespace.replace(/\s/g, "%20");
     }
 
     if (namespace.substr(0, 4) == "/../") {
       this._addError(this.currentLine, "slashDotDotSlashBad", this.currentLine);
     }
 
     if (namespace.substr(0, 2) == "./") {
       namespace = this.origin + namespace.substring(2);
--- a/browser/devtools/styleeditor/StyleEditorUI.jsm
+++ b/browser/devtools/styleeditor/StyleEditorUI.jsm
@@ -59,17 +59,17 @@ function StyleEditorUI(debuggee, target,
   this._panelDoc = panelDoc;
   this._window = this._panelDoc.defaultView;
   this._root = this._panelDoc.getElementById("style-editor-chrome");
 
   this.editors = [];
   this.selectedEditor = null;
   this.savedLocations = {};
 
-  this._updateContextMenu = this._updateContextMenu.bind(this);
+  this._updateOptionsMenu = this._updateOptionsMenu.bind(this);
   this._onStyleSheetCreated = this._onStyleSheetCreated.bind(this);
   this._onNewDocument = this._onNewDocument.bind(this);
   this._onMediaPrefChanged = this._onMediaPrefChanged.bind(this);
   this._updateMediaList = this._updateMediaList.bind(this);
   this._clear = this._clear.bind(this);
   this._onError = this._onError.bind(this);
 
   this._prefObserver = new PrefObserver("devtools.styleeditor.");
@@ -137,46 +137,36 @@ StyleEditorUI.prototype = {
     wire(this._view.rootElement, ".style-editor-newButton", function onNew() {
       this._debuggee.addStyleSheet(null).then(this._onStyleSheetCreated);
     }.bind(this));
 
     wire(this._view.rootElement, ".style-editor-importButton", function onImport() {
       this._importFromFile(this._mockImportFile || null, this._window);
     }.bind(this));
 
-    this._contextMenu = this._panelDoc.getElementById("sidebar-context");
-    this._contextMenu.addEventListener("popupshowing",
-                                       this._updateContextMenu);
+    this._optionsMenu = this._panelDoc.getElementById("style-editor-options-popup");
+    this._optionsMenu.addEventListener("popupshowing",
+                                       this._updateOptionsMenu);
 
-    this._sourcesItem = this._panelDoc.getElementById("context-origsources");
+    this._sourcesItem = this._panelDoc.getElementById("options-origsources");
     this._sourcesItem.addEventListener("command",
                                        this._toggleOrigSources);
-    this._mediaItem = this._panelDoc.getElementById("context-show-media");
+    this._mediaItem = this._panelDoc.getElementById("options-show-media");
     this._mediaItem.addEventListener("command",
                                      this._toggleMediaSidebar);
   },
 
   /**
-   * Update text of context menu option to reflect current preference
-   * settings
+   * Update options menu items to reflect current preference settings.
    */
-  _updateContextMenu: function() {
-    let sourceString = "showOriginalSources";
-    if (Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
-      sourceString = "showCSSSources";
-    }
-    this._sourcesItem.setAttribute("label", _(sourceString + ".label"));
-    this._sourcesItem.setAttribute("accesskey", _(sourceString + ".accesskey"));
-
-    let mediaString = "showMediaSidebar"
-    if (Services.prefs.getBoolPref(PREF_MEDIA_SIDEBAR)) {
-      mediaString = "hideMediaSidebar";
-    }
-    this._mediaItem.setAttribute("label", _(mediaString + ".label"));
-    this._mediaItem.setAttribute("accesskey", _(mediaString + ".accesskey"));
+  _updateOptionsMenu: function() {
+    this._sourcesItem.setAttribute("checked",
+      Services.prefs.getBoolPref(PREF_ORIG_SOURCES));
+    this._mediaItem.setAttribute("checked",
+      Services.prefs.getBoolPref(PREF_MEDIA_SIDEBAR));
   },
 
   /**
    * Refresh editors to reflect the stylesheets in the document.
    *
    * @param {string} event
    *        Event name
    * @param {StyleSheet} styleSheet
@@ -766,13 +756,16 @@ StyleEditorUI.prototype = {
    */
   _jumpToMediaRule: function(rule) {
     this.selectStyleSheet(rule.parentStyleSheet, rule.line - 1, rule.column - 1);
   },
 
   destroy: function() {
     this._clearStyleSheetEditors();
 
+    this._optionsMenu.removeEventListener("popupshowing",
+                                          this._updateOptionsMenu);
+
     this._prefObserver.off(PREF_ORIG_SOURCES, this._onNewDocument);
     this._prefObserver.off(PREF_MEDIA_SIDEBAR, this._onMediaPrefChanged);
     this._prefObserver.destroy();
   }
 }
--- a/browser/devtools/styleeditor/styleeditor.css
+++ b/browser/devtools/styleeditor/styleeditor.css
@@ -10,16 +10,20 @@
 .stylesheet-error-message {
   display: none;
 }
 
 li.error > .stylesheet-info > .stylesheet-more  > .stylesheet-error-message {
   display: block;
 }
 
+.devtools-toolbar > spacer {
+  -moz-box-flex: 1;
+}
+
 .splitview-nav > li,
 .stylesheet-info,
 .stylesheet-more {
   display: -moz-box;
 }
 
 .stylesheet-details-container {
   -moz-box-flex: 1;
--- a/browser/devtools/styleeditor/styleeditor.xul
+++ b/browser/devtools/styleeditor/styleeditor.xul
@@ -56,19 +56,26 @@
       <xul:menuitem id="cMenu_findAgain"/>
       <xul:menuseparator/>
       <xul:menuitem id="se-menu-gotoLine"
           label="&gotoLineCmd.label;"
           accesskey="&gotoLineCmd.accesskey;"
           key="key_gotoLine"
           command="cmd_gotoLine"/>
     </xul:menupopup>
-    <xul:menupopup id="sidebar-context">
-      <xul:menuitem id="context-origsources"/>
-      <xul:menuitem id="context-show-media"/>
+    <xul:menupopup id="style-editor-options-popup"
+                   position="before_start">
+      <xul:menuitem id="options-origsources"
+                    type="checkbox"
+                    label="&showOriginalSources.label;"
+                    accesskey="&showOriginalSources.accesskey;"/>
+      <xul:menuitem id="options-show-media"
+                    type="checkbox"
+                    label="&showMediaSidebar.label;"
+                    accesskey="&showMediaSidebar.accesskey;"/>
     </xul:menupopup>
   </xul:popupset>
 
   <xul:commandset id="editMenuCommands"/>
 
   <xul:commandset id="sourceEditorCommands">
     <xul:command id="cmd_gotoLine" oncommand="goDoCommand('cmd_gotoLine')"/>
     <xul:command id="cmd_find" oncommand="goDoCommand('cmd_find')"/>
@@ -86,16 +93,21 @@
             <xul:toolbarbutton class="style-editor-newButton devtools-toolbarbutton"
                         accesskey="&newButton.accesskey;"
                         tooltiptext="&newButton.tooltip;"
                         label="&newButton.label;"/>
             <xul:toolbarbutton class="style-editor-importButton devtools-toolbarbutton"
                         accesskey="&importButton.accesskey;"
                         tooltiptext="&importButton.tooltip;"
                         label="&importButton.label;"/>
+            <xul:spacer/>
+            <xul:toolbarbutton id="style-editor-options"
+                        class="devtools-option-toolbarbutton"
+                        tooltiptext="&optionsButton.tooltip;"
+                        popup="style-editor-options-popup"/>
           </xul:toolbar>
         </xul:box>
         <xul:box id="splitview-resizer-target" class="theme-sidebar splitview-nav-container"
                 persist="height">
           <ol class="splitview-nav" tabindex="0"></ol>
           <div class="splitview-nav placeholder empty">
             <p><strong>&noStyleSheet.label;</strong></p>
             <p>&noStyleSheet-tip-start.label;
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -1464,34 +1464,36 @@ CssRuleView.prototype = {
         };
       }
     }).then(null, console.error);
   },
 
   /**
    * Update the rules for the currently highlighted element.
    */
-  nodeChanged: function() {
+  refreshPanel: function() {
     // Ignore refreshes during editing or when no element is selected.
     if (this.isEditing || !this._elementStyle) {
       return;
     }
 
-    this._clearRules();
-
     // Repopulate the element style.
-    this._populate();
+    this._populate(true);
   },
 
-  _populate: function() {
+  _populate: function(clearRules = false) {
     let elementStyle = this._elementStyle;
     return this._elementStyle.populate().then(() => {
       if (this._elementStyle != elementStyle) {
         return;
       }
+
+      if (clearRules) {
+        this._clearRules();
+      }
       this._createEditors();
 
       // Notify anyone that cares that we refreshed.
       var evt = this.doc.createEvent("Events");
       evt.initEvent("CssRuleViewRefreshed", true, false);
       this.element.dispatchEvent(evt);
       return undefined;
     }).then(null, promiseWarn);
--- a/browser/devtools/styleinspector/style-inspector.js
+++ b/browser/devtools/styleinspector/style-inspector.js
@@ -104,17 +104,17 @@ RuleViewTool.prototype = {
 
     if (!aEvent || aEvent == "new-node-front") {
       let done = this.inspector.updating("rule-view");
       this.view.highlight(this.inspector.selection.nodeFront).then(done, done);
     }
   },
 
   refresh: function RVT_refresh() {
-    this.view.nodeChanged();
+    this.view.refreshPanel();
   },
 
   destroy: function RVT_destroy() {
     this.inspector.off("layout-change", this.refresh);
     this.inspector.selection.off("pseudoclass", this.refresh);
     this.inspector.selection.off("new-node-front", this._onSelect);
 
     this.view.element.removeEventListener("CssRuleViewCSSLinkClicked",
--- a/browser/locales/en-US/chrome/browser/devtools/styleeditor.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/styleeditor.dtd
@@ -19,16 +19,34 @@
 <!ENTITY importButton.accesskey     "I">
 
 <!ENTITY visibilityToggle.tooltip   "Toggle style sheet visibility">
 
 <!ENTITY saveButton.label           "Save">
 <!ENTITY saveButton.tooltip         "Save this style sheet to a file">
 <!ENTITY saveButton.accesskey       "S">
 
+<!ENTITY optionsButton.tooltip      "Style Editor options">
+
+<!-- LOCALIZATION NOTE  (showOriginalSources.label): This is the label on the context
+     menu item to toggle showing original sources in the editor. -->
+<!ENTITY showOriginalSources.label     "Show original sources">
+
+<!-- LOCALIZATION NOTE  (showOriginalSources.accesskey): This is the access key for
+     the menu item to toggle showing original sources in the editor. -->
+<!ENTITY showOriginalSources.accesskey  "o">
+
+<!-- LOCALIZATION NOTE  (showMediaSidebar.label): This is the label on the context
+     menu item to toggle showing @media rule shortcuts in a sidebar. -->
+<!ENTITY showMediaSidebar.label     "Show @media sidebar">
+
+<!-- LOCALIZATION NOTE  (showMediaSidebar.accesskey): This is the access key for
+     the menu item to toggle showing the @media sidebar. -->
+<!ENTITY showMediaSidebar.accesskey     "m">
+
 <!-- LOCALICATION NOTE  (mediaRules.label): This is shown above the list of @media rules
      in each stylesheet editor sidebar. -->
 <!ENTITY mediaRules.label           "@media rules">
 
 <!ENTITY editorTextbox.placeholder  "Type CSS here.">
 
 <!-- LOCALICATION NOTE  (noStyleSheet.label): This is shown when a page has no
      stylesheet. -->
--- a/browser/locales/en-US/chrome/browser/devtools/styleeditor.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/styleeditor.properties
@@ -63,48 +63,16 @@ open.commandkey=VK_F7
 # LOCALIZATION NOTE (open.accesskey): The access key used to open the style
 # editor.
 open.accesskey=l
 
 # LOCALIZATION NOTE  (saveStyleSheet.commandkey): This the key to use in
 # conjunction with accel (Command on Mac or Ctrl on other platforms) to Save
 saveStyleSheet.commandkey=S
 
-# LOCALIZATION NOTE  (showOriginalSources.label): This is the label on the context
-# menu item to toggle showing original sources in the editor.
-showOriginalSources.label=Show original sources
-
-# LOCALIZATION NOTE  (showOriginalSources.accesskey): This is the access key for
-# the menu item to toggle showing original sources in the editor.
-showOriginalSources.accesskey=O
-
-# LOCALIZATION NOTE  (showCSSSources.label): This is the label on the context
-# menu item to toggle back to showing only CSS sources in the editor.
-showCSSSources.label=Show CSS sources
-
-# LOCALIZATION NOTE  (showCSSSources.accesskey): This is the access key for the
-# menu item to toggle back to showing only CSS sources in the editor.
-showCSSSources.accesskey=C
-
-# LOCALIZATION NOTE  (showMediaSidebar.label): This is the label on the context
-# menu item to toggle showing @media rule shortcuts in a sidebar.
-showMediaSidebar.label=Show @media sidebar
-
-# LOCALIZATION NOTE  (showMediaSidebar.accesskey): This is the access key for
-# the menu item to toggle showing the @media sidebar.
-showMediaSidebar.accesskey=M
-
-# LOCALIZATION NOTE  (hideMediaSidebar.label): This is the label on the context
-# menu item to stop showing @media rule shortcuts in a sidebar.
-hideMediaSidebar.label=Hide @media sidebar
-
-# LOCALIZATION NOTE  (hideMediaSidebar.accesskey): This is the access key for
-# the menu item to stop showing the @media sidebar.
-hideMediaSidebar.accesskey=H
-
 # LOCALIZATION NOTE (ToolboxStyleEditor.label):
 # This string is displayed in the title of the tab when the style editor is
 # displayed inside the developer tools window and in the Developer Tools Menu.
 ToolboxStyleEditor.label=Style Editor
 
 # LOCALIZATION NOTE (ToolboxStyleEditor.tooltip2):
 # This string is displayed in the tooltip of the tab when the style editor is
 # displayed inside the developer tools window.
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -280,16 +280,17 @@ browser.jar:
   skin/classic/browser/devtools/responsive-horizontal-resizer@2x.png  (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
   skin/classic/browser/devtools/responsiveui-rotate.png          (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
   skin/classic/browser/devtools/responsiveui-rotate@2x.png       (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
   skin/classic/browser/devtools/responsiveui-touch.png           (../shared/devtools/images/responsivemode/responsiveui-touch.png)
   skin/classic/browser/devtools/responsiveui-touch@2x.png        (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
   skin/classic/browser/devtools/responsiveui-screenshot.png      (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
   skin/classic/browser/devtools/responsiveui-screenshot@2x.png   (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
   skin/classic/browser/devtools/toggle-tools.png          (../shared/devtools/images/toggle-tools.png)
+  skin/classic/browser/devtools/toggle-tools@2x.png       (../shared/devtools/images/toggle-tools@2x.png)
   skin/classic/browser/devtools/dock-bottom@2x.png        (../shared/devtools/images/dock-bottom@2x.png)
   skin/classic/browser/devtools/dock-side@2x.png          (../shared/devtools/images/dock-side@2x.png)
   skin/classic/browser/devtools/floating-scrollbars.css   (devtools/floating-scrollbars.css)
   skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
 * skin/classic/browser/devtools/inspector.css               (../shared/devtools/inspector.css)
   skin/classic/browser/devtools/profiler-stopwatch.svg      (../shared/devtools/images/profiler-stopwatch.svg)
   skin/classic/browser/devtools/profiler-stopwatch-checked.svg      (../shared/devtools/images/profiler-stopwatch-checked.svg)
   skin/classic/browser/devtools/tool-options.svg            (../shared/devtools/images/tool-options.svg)
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -400,16 +400,17 @@ browser.jar:
   skin/classic/browser/devtools/responsive-horizontal-resizer@2x.png  (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
   skin/classic/browser/devtools/responsiveui-rotate.png          (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
   skin/classic/browser/devtools/responsiveui-rotate@2x.png       (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
   skin/classic/browser/devtools/responsiveui-touch.png           (../shared/devtools/images/responsivemode/responsiveui-touch.png)
   skin/classic/browser/devtools/responsiveui-touch@2x.png        (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
   skin/classic/browser/devtools/responsiveui-screenshot.png      (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
   skin/classic/browser/devtools/responsiveui-screenshot@2x.png   (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
   skin/classic/browser/devtools/toggle-tools.png            (../shared/devtools/images/toggle-tools.png)
+  skin/classic/browser/devtools/toggle-tools@2x.png         (../shared/devtools/images/toggle-tools@2x.png)
   skin/classic/browser/devtools/dock-bottom@2x.png          (../shared/devtools/images/dock-bottom@2x.png)
   skin/classic/browser/devtools/dock-side@2x.png          (../shared/devtools/images/dock-side@2x.png)
 * skin/classic/browser/devtools/inspector.css               (../shared/devtools/inspector.css)
   skin/classic/browser/devtools/profiler-stopwatch.svg      (../shared/devtools/images/profiler-stopwatch.svg)
   skin/classic/browser/devtools/profiler-stopwatch-checked.svg      (../shared/devtools/images/profiler-stopwatch-checked.svg)
   skin/classic/browser/devtools/tool-options.svg            (../shared/devtools/images/tool-options.svg)
   skin/classic/browser/devtools/tool-webconsole.svg         (../shared/devtools/images/tool-webconsole.svg)
   skin/classic/browser/devtools/tool-debugger.svg           (../shared/devtools/images/tool-debugger.svg)
--- a/browser/themes/shared/devtools/commandline.inc.css
+++ b/browser/themes/shared/devtools/commandline.inc.css
@@ -23,16 +23,22 @@
   padding: 0 10px;
   width: 32px;
 }
 
 .developer-toolbar-button > image {
   margin: auto 10px;
 }
 
+.developer-toolbar-button > .toolbarbutton-icon,
+#developer-toolbar-closebutton > .toolbarbutton-icon {
+  width: 16px;
+  height: 16px;
+}
+
 #developer-toolbar-toolbox-button {
   list-style-image: url("chrome://browser/skin/devtools/toggle-tools.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
 #developer-toolbar-toolbox-button > label {
   display: none;
 }
@@ -44,26 +50,51 @@
 #developer-toolbar-toolbox-button:hover:active {
   -moz-image-region: rect(0px, 48px, 16px, 32px);
 }
 
 #developer-toolbar-toolbox-button[checked=true] {
   -moz-image-region: rect(0px, 64px, 16px, 48px);
 }
 
+@media (min-resolution: 2dppx) {
+  #developer-toolbar-toolbox-button {
+    list-style-image: url("chrome://browser/skin/devtools/toggle-tools@2x.png");
+    -moz-image-region: rect(0px, 32px, 32px, 0px);
+  }
+
+  #developer-toolbar-toolbox-button:hover {
+    -moz-image-region: rect(0px, 64px, 32px, 32px);
+  }
+
+  #developer-toolbar-toolbox-button:hover:active {
+    -moz-image-region: rect(0px, 96px, 32px, 64px);
+  }
+
+  #developer-toolbar-toolbox-button[checked=true] {
+    -moz-image-region: rect(0px, 128px, 32px, 96px);
+  }
+}
+
 #developer-toolbar-closebutton {
   list-style-image: url("chrome://browser/skin/devtools/close.png");
   -moz-appearance: none;
   border: none;
   margin: 0 4px;
   min-width: 16px;
   width: 16px;
   opacity: 0.6;
 }
 
+@media (min-resolution: 2dppx) {
+  #developer-toolbar-closebutton {
+    list-style-image: url("chrome://browser/skin/devtools/close@2x.png");
+  }
+}
+
 #developer-toolbar-closebutton > .toolbarbutton-icon {
   /* XXX Buttons have padding in widget/ that we don't want here but can't override with good CSS, so we must
      use evil CSS to give the impression of smaller content */
   margin: -4px;
 }
 
 #developer-toolbar-closebutton > .toolbarbutton-text {
   display: none;
@@ -104,33 +135,53 @@ html|*#gcli-output-frame {
   box-shadow: none;
   border-width: 0;
   background-color: transparent;
 }
 
 .gclitoolbar-input-node {
   -moz-appearance: none;
   color: hsl(210,30%,85%);
-  padding-left: 20px;
   background-color: #242b33;
   background-repeat: no-repeat;
   background-position: 4px center;
   box-shadow: 0 1px 1px hsla(206,37%,4%,.2) inset,
               1px 0 0 hsla(206,37%,4%,.2) inset,
               -1px 0 0 hsla(206,37%,4%,.2) inset;
   line-height: 32px;
   outline-style: none;
-  background-image: -moz-image-rect(url("chrome://browser/skin/devtools/commandline-icon.png"), 0, 16, 16, 0);
+  padding: 0;
 }
 
 .gclitoolbar-input-node[focused="true"] {
-  background-image: -moz-image-rect(url("chrome://browser/skin/devtools/commandline-icon.png"), 0, 32, 16, 16);
   background-color: #232e38;
 }
 
+.gclitoolbar-input-node::before {
+  content: "";
+  display: inline-block;
+  -moz-box-ordinal-group: 0;
+  width: 16px;
+  height: 16px;
+  margin: 0 2px;
+  background-image: url("chrome://browser/skin/devtools/commandline-icon.png");
+  background-position: 0 center;
+  background-size: 32px 16px;
+}
+
+.gclitoolbar-input-node[focused="true"]::before {
+  background-position: -16px center;
+}
+
+@media (min-resolution: 2dppx) {
+  .gclitoolbar-input-node::before {
+    background-image: url("chrome://browser/skin/devtools/commandline-icon@2x.png");
+  }
+}
+
 .gclitoolbar-input-node > .textbox-input-box > html|*.textbox-input::-moz-selection {
   background-color: hsl(210,30%,85%);
   color: hsl(210,24%,16%);
   text-shadow: none;
 }
 
 .gclitoolbar-complete-node {
   padding-left: 21px;
--- a/browser/themes/shared/devtools/highlighter.inc.css
+++ b/browser/themes/shared/devtools/highlighter.inc.css
@@ -69,16 +69,23 @@ html|*.highlighter-nodeinfobar-id {
   color: hsl(103,46%,54%);
 }
 
 html|*.highlighter-nodeinfobar-classes,
 html|*.highlighter-nodeinfobar-pseudo-classes {
   color: hsl(200,74%,57%);
 }
 
+html|*.highlighter-nodeinfobar-dimensions {
+  color: hsl(210,30%,85%);
+  -moz-border-start: 1px solid #5a6169;
+  -moz-margin-start: 6px;
+  -moz-padding-start: 6px;
+}
+
 /* Highlighter - Node Infobar - box & arrow */
 
 .highlighter-nodeinfobar-arrow {
   width: 14px;
   height: 14px;
   -moz-margin-start: calc(50% - 7px);
   transform: rotate(-45deg);
   background-clip: padding-box;
index 8a40d0d116d76c6ec4a77a459797f9f5e112df69..495439391c7bb38528ca205248f14554325de0b7
GIT binary patch
literal 883
zc$@)q1C0EMP)<h;3K|Lk000e1NJLTq002M$000mO1^@s6rssJn0009zNkl<Zc-rlj
z-%C_M6vsD6`$hEJOT8E&T2Tt=?vsx__c!zsy%k7NL_{Km5G2`;Cp8JzyM~JP5GsZb
z3K_JZ5*k9aKXk#&duQ&<++C(~Y>yeT)1BL^1BY{WcE7NnGv9mW#KJDd^l{(!Pin2J
zViDF4&<deXfxbG5e(k5I$-A<CN$Ueq^v%g{HSxi(^_Rw$?DSH~S|-#}#^nfxFN0e)
zddAcRCW0}~SD!JsP@OjV)y*JLV5NmMR@CJfw9z-EGKuC?cA?qHY7BS|uZI&q0e{{h
zc;?Fo+TsL+&@~>Hp9r4$svGnN!|HRctOH<1@C9BR&uV=*tUlr7>HwM%d_0vIZy3pj
z*2g>^v=Y3>WE;U_W`1yIWyK8R3H6xZxvzQ%9y1i<8RSDo+w)@o4)_Uz$6R2=;k?#I
zjJ9_&{oC+Pc7otB!*|1Hd-6to%=N`fDgd4)!J`v??}^hUJrwC36~L9Ueg}Lv?kT0u
znF~-_-Yx)BjRcQQz`Z<IO(uOjm0hL+B%Ev`!J`wl_EO(LZvx<|bK3!aa8pWs1}xo9
zd-#eN^{6BJbM=ICbrGEKiuSOm#saWXnhF4JaB^<Y0(pw|@D(vTAe-Ld00)3u;Cbp#
zQF4{_TI>B>s1AbN6~5|%-|RE!tGEaT%CNfv-0{|=pNHE5Y(7h{yMmV%P5Qdzd^I$@
zSp=;Ri!snwgokc_yCS>@lCCRjP4HNtits{xWJ;a?2mDZF_~Pa&58@{Hcq%t!fZuE$
z$iyw+RVP^gAvQIat7|wD*ua-xh1ZbZxJ=&1nZORdlm_T&$a8QdKF68B5<U$v4UU+D
zzVIApg3$0DR~_1T^_bx~xTR1i95u*{@bGzNeO(_j3eE5{4aqNm>G$A6+1?M@BEnPj
zMueyLeDXixClNm6z$32X(BpC0A7$d>LO#O&z=Zk`W#WT-y|+B{Y($y(;EL-l4?P=^
zCO)ugJ7xg5Y6VYvU-e-I?LA9)n)u#hh6dMV2~P#s(gS>#9XtWZ;$^V>UCx6W1aGqd
z`U=Dg>=^`aRRAw&g_9oz_&$QSD!@Rd6^bwlUA}J%es6_ezW{VdF*q5<m|Oq=002ov
JPDHLkV1h=;q`3e9
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..971f414316f576158c83eb021122b9835f336801
GIT binary patch
literal 1834
zc$@($2i5qAP)<h;3K|Lk000e1NJLTq004jh001Be1^@s6+9Gfz000K@Nkl<Zc-rln
ze~4676vwU16r!*+HBD1Q`)NkjI;#s&L?mQIp%7$(SzzRkeqc!p8WdS5)kaut80sp`
z&ZyWQN)e)hzfw#|G8C8Cnc3N=ZL>S~-Cu9k+xI}a<L;Z8_T7Cm|ICHM&b)VdUuHk&
z-gnMDXHa!i$AArE%ynH#-6f^>gzL(=LU^+oGo#9>&$OP-xq5*Ky}*_7DbD%0GU^X*
z=Uyc3>P2a$mpR$oytEJ#%ccM5UNg8hnutW=$wiS^YT3+KV%{UsbolzGPoEybRc<~P
zdb7*bk9|z2H3TQbfBX%u)Jt5h4+8w3z0DQ6F--jyV}`c7UcKYy(lFy=yU9611HZ9l
zXrwt&ABm^Z0B?F5uJ49(grlF$nvqQE&wRnd;1pY=G?T*m@vbprptFNO7l3~#n^pIO
zrJoXJyyJEsC(s4Vaa{diSo*W0sqp}O+!s8oHkNWCv1B;<jxjg7LT@MrUkEcH#Fc*&
zc9%WH;7ci|gr%R!nBflZK2r>SnyLFkgWvSmZ~#726n?Z7`XLR@y|;tF2e@knLZ5NH
zE(m<+Upo-`7kI9z6#OvtvGSV&!CyT9`ha_<E4^L)g-_RA;jOXN?~-yVbk6h_K3&KC
z?`-wknVJU3m--8zuH*h5Tm70?>okDA)L-~?9doSp0W!DH4?YuWYccrb95jz}bBEpP
z_ueT0|40e=hiG1Br<`oJ`n%T_fPb+Bd<SOQEaQ^ec-vb4)t|gr3_dvr&8vyF*~LXz
z#UJ@O0Ht8Q?@K8s5&RxU@gBEw0Aw7#4j}cb{=urc`!akoWG&BG#Xmf^*Vh4<_pa}J
zrl%A9o_TtqjXogmEwKIj>LWdzei=SlZ9D;ei@~M$xt{}Mg?Oy*$}>|KS3g`eSE*;L
z98h{YeI3A6&-QT^rXPS~9J_k19RNiBC;S|so#htvS@~So;9e$wUYh9@Ry#l}dBWEL
zniGBWXU1A<a4(ZT4`&1`EFD0v^K$?S%sM(cZY~O+Oy=fTI$*P(1K@hJv$OM-67XT_
zMXOhUn>*s?0Jwg*4XJT4_+;%_y~HvAJW^l>I9wNP8(9oKS#5K2iCzBB^-==qZ@R&i
z@@ZG-R|u5f9Bj$=+P#9*hXpeL?(Gsnzr=+1p3C)b{yT-9VdntdjfFFS?vqYdFGZZN
z9^aYooG!1<(g7L?q`xIkV!L08&+B2#Z_cddRGnQEF1$Jd8N?V@TWn9}TvyH^kU@+K
zebDw~4#&Ln31mQPhyL|8`ZJ@+`2;ecwLkRrvEcf&#bafC8Pox={m-@e@wCO$a|mWY
zd)Y>xws@@aQvu=A`+vEOK5g-Ucq$-#iW8Ps3_h1?Ev^1a!RJD6rPW_4_{bg((CV)g
z{MvZx0ImLtz-L^qr)N|OJ~D?GJ)=_a5g;C=XH*J4>?l1W*gL<=+-d=T2L*)i{2_t!
ze#S-xg%9oDDIjcVX&D++{~|YIgTe=RMFC-}F~frD;}B<TaQI0@0U@3-EFk=@5w6hR
z6oX9BKJ@_zq*si~w}kRmxl+GQ>0Tz28BWi!fIk|m_ot$e5$)3<6qou9F4d=8!dZp-
zfYLoU-Uu80zquKQqR-h9pc(Z6AUjx%8o_3K-;U24DBW|I8Etj!8&8Y_#Iq$pGwK7t
z3E^sF0Gp8|Y=>>2bnoG))1w~-e9H4F-w!BZ4<C6x<@**gw(v8Q?_0>&!p|VzFQ{LI
zUxi<VUxi<VUxokwPT0&Cz~4xaOSE}S4&%rFBLtO<_YvfxZC*;<7lyurGBMz`mVobE
zC~=f*5$#U~{MKUdsj4?CmYPv9_*B=gBz&stR}wze^}~i=_BO9<HhWto;lufEuO$2w
zepe;o<AiR4HGIqJ+WT};#+ZDPDs^0XAD6Si6L7y`T%F8vHIFKF&}#|+-=@5~6M$Xh
z@{6fb=kVPAayEDZ?oL2<@pmy*>hO1eSsOeV)$FByt*7DBjLi%9LWNI*f;u>1eNX$C
zn3!L^3llyK3hEH}eR0Jhy5!XS>Rp)dX;4syL!2x6v!cnV`PI7~_~EU<?>YD0%x~l%
z`1D$!*kDk|1CaM~sXobX<oFN%K8g*()(7MSPVhGMYUD7mR*DV6*2ngrz-wSruSO0-
zuLZz|e%Jt1?s)*;MY{l%YXQE|2Y#3ixR^`*hfrQUm1_b1mvX_U;V^F{V0U8|XrOW}
z&i&7q3qB1T*{%fe?nu0?fy%Y`d_F|@{=NFtr<WD-TQ2lAY{#o8FvP90=~JJcE4-gw
zu7Bk+*Fb?`IrXVe4-Rk+;5!fl#8dRzE7yQN_32?3I9D4_cEADR6c`Swj_Rn6>IiN8
Y3rJqitcexp<p2Nx07*qoM6N<$g3TP1MgRZ+
--- a/browser/themes/shared/devtools/markup-view.css
+++ b/browser/themes/shared/devtools/markup-view.css
@@ -25,16 +25,22 @@
 .theme-selected ~ .editor .theme-fg-color3,
 .theme-selected ~ .editor .theme-fg-color4,
 .theme-selected ~ .editor .theme-fg-color5,
 .theme-selected ~ .editor .theme-fg-color6,
 .theme-selected ~ .editor .theme-fg-color7 {
   color: #f5f7fa; /* Light foreground text */
 }
 
+/* In case a node isn't displayed in the page, we fade the syntax highlighting */
+.not-displayed .open,
+.not-displayed .close {
+  opacity: .7;
+}
+
 .tag-line {
   padding-left: 2px;
 }
 
 /* Preview */
 
 #previewbar {
   position: fixed;
--- a/browser/themes/shared/devtools/styleeditor.css
+++ b/browser/themes/shared/devtools/styleeditor.css
@@ -114,16 +114,21 @@
     background-image: url(itemToggle@2x.png);
   }
 }
 
 .disabled > .stylesheet-enabled {
   background-position: -24px 8px;
 }
 
+#style-editor-options {
+  width: 20px;
+  overflow: hidden;
+}
+
 /* Invert all toggle icons but the one in the active row for light theme */
 .theme-light .splitview-nav > li:not(.splitview-active) .stylesheet-enabled {
   filter: url(filters.svg#invert);
 }
 
 .splitview-nav > li > .stylesheet-enabled:focus,
 .splitview-nav > li:hover > .stylesheet-enabled {
   outline: 0;
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -318,16 +318,17 @@ browser.jar:
         skin/classic/browser/devtools/responsive-horizontal-resizer@2x.png  (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
         skin/classic/browser/devtools/responsiveui-rotate.png       (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
         skin/classic/browser/devtools/responsiveui-rotate@2x.png       (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
         skin/classic/browser/devtools/responsiveui-touch.png        (../shared/devtools/images/responsivemode/responsiveui-touch.png)
         skin/classic/browser/devtools/responsiveui-touch@2x.png        (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
         skin/classic/browser/devtools/responsiveui-screenshot.png   (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
         skin/classic/browser/devtools/responsiveui-screenshot@2x.png   (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
         skin/classic/browser/devtools/toggle-tools.png              (../shared/devtools/images/toggle-tools.png)
+        skin/classic/browser/devtools/toggle-tools@2x.png              (../shared/devtools/images/toggle-tools@2x.png)
         skin/classic/browser/devtools/dock-bottom@2x.png            (../shared/devtools/images/dock-bottom@2x.png)
         skin/classic/browser/devtools/dock-side@2x.png              (../shared/devtools/images/dock-side@2x.png)
         skin/classic/browser/devtools/floating-scrollbars.css       (devtools/floating-scrollbars.css)
         skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
 *       skin/classic/browser/devtools/inspector.css                 (../shared/devtools/inspector.css)
         skin/classic/browser/devtools/profiler-stopwatch.svg        (../shared/devtools/images/profiler-stopwatch.svg)
         skin/classic/browser/devtools/profiler-stopwatch-checked.svg  (../shared/devtools/images/profiler-stopwatch-checked.svg)
         skin/classic/browser/devtools/tool-options.svg              (../shared/devtools/images/tool-options.svg)
@@ -718,16 +719,17 @@ browser.jar:
         skin/classic/aero/browser/devtools/responsive-horizontal-resizer@2x.png  (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
         skin/classic/aero/browser/devtools/responsiveui-rotate.png          (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
         skin/classic/aero/browser/devtools/responsiveui-rotate@2x.png       (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
         skin/classic/aero/browser/devtools/responsiveui-touch.png           (../shared/devtools/images/responsivemode/responsiveui-touch.png)
         skin/classic/aero/browser/devtools/responsiveui-touch@2x.png        (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
         skin/classic/aero/browser/devtools/responsiveui-screenshot.png      (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
         skin/classic/aero/browser/devtools/responsiveui-screenshot@2x.png   (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
         skin/classic/aero/browser/devtools/toggle-tools.png          (../shared/devtools/images/toggle-tools.png)
+        skin/classic/aero/browser/devtools/toggle-tools@2x.png       (../shared/devtools/images/toggle-tools@2x.png)
         skin/classic/aero/browser/devtools/dock-bottom@2x.png        (../shared/devtools/images/dock-bottom@2x.png)
         skin/classic/aero/browser/devtools/dock-side@2x.png          (../shared/devtools/images/dock-side@2x.png)
         skin/classic/aero/browser/devtools/floating-scrollbars.css   (devtools/floating-scrollbars.css)
         skin/classic/aero/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
 *       skin/classic/aero/browser/devtools/inspector.css             (../shared/devtools/inspector.css)
         skin/classic/aero/browser/devtools/profiler-stopwatch.svg    (../shared/devtools/images/profiler-stopwatch.svg)
         skin/classic/aero/browser/devtools/profiler-stopwatch-checked.svg      (../shared/devtools/images/profiler-stopwatch-checked.svg)
         skin/classic/aero/browser/devtools/tool-options.svg          (../shared/devtools/images/tool-options.svg)
--- a/configure.in
+++ b/configure.in
@@ -3465,17 +3465,17 @@ dnl ====================================
 dnl = If NSPR was not detected in the system,
 dnl = use the one in the source tree (mozilla/nsprpub)
 dnl ========================================================
 MOZ_ARG_WITH_BOOL(system-nspr,
 [  --with-system-nspr      Use system installed NSPR],
     _USE_SYSTEM_NSPR=1 )
 
 if test -n "$_USE_SYSTEM_NSPR"; then
-    AM_PATH_NSPR(4.10.3, [MOZ_NATIVE_NSPR=1], [AC_MSG_ERROR([your don't have NSPR installed or your version is too old])])
+    AM_PATH_NSPR(4.10.6, [MOZ_NATIVE_NSPR=1], [AC_MSG_ERROR([your don't have NSPR installed or your version is too old])])
 fi
 
 if test -n "$MOZ_NATIVE_NSPR"; then
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS $NSPR_CFLAGS"
     AC_TRY_COMPILE([#include "prtypes.h"],
                 [#ifndef PR_STATIC_ASSERT
                  #error PR_STATIC_ASSERT not defined or requires including prtypes.h
@@ -3933,16 +3933,17 @@ if test -n "$MOZ_RTSP"; then
 fi
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 MOZ_ANDROID_HISTORY=
 MOZ_WEBSMS_BACKEND=
 MOZ_ANDROID_BEAM=
 MOZ_ANDROID_SYNTHAPKS=
+MOZ_LOCALE_SWITCHER=
 ACCESSIBILITY=1
 MOZ_TIME_MANAGER=
 MOZ_PAY=
 MOZ_AUDIO_CHANNEL_MANAGER=
 NSS_NO_LIBPKIX=
 MOZ_CONTENT_SANDBOX=
 MOZ_CONTENT_SANDBOX_REPORTER=1
 JSGC_USE_EXACT_ROOTING=
@@ -4943,16 +4944,23 @@ MOZ_ARG_DISABLE_BOOL(websms-backend,
     MOZ_WEBSMS_BACKEND=,
     MOZ_WEBSMS_BACKEND=1)
 
 if test -n "$MOZ_WEBSMS_BACKEND"; then
     AC_DEFINE(MOZ_WEBSMS_BACKEND)
 fi
 
 dnl ========================================================
+dnl = Enable runtime locale switching on Android
+dnl ========================================================
+if test -n "$MOZ_LOCALE_SWITCHER"; then
+    AC_DEFINE(MOZ_LOCALE_SWITCHER)
+fi
+
+dnl ========================================================
 dnl = Enable NFC permission on Android
 dnl ========================================================
 if test -n "$MOZ_ANDROID_BEAM"; then
     AC_DEFINE(MOZ_ANDROID_BEAM)
 fi
 
 dnl ========================================================
 dnl = Synthesized Webapp APKs on Android
@@ -6310,27 +6318,23 @@ fi
 if test "$OS_ARCH" = "WINNT" -a -z "$MAKENSISU" -a -n "$CROSS_COMPILE"; then
     MOZ_WEBAPP_RUNTIME=
 fi
 AC_SUBST(MOZ_WEBAPP_RUNTIME)
 if test "$MOZ_WEBAPP_RUNTIME"; then
     AC_DEFINE(MOZ_WEBAPP_RUNTIME)
 fi
 
-AC_MSG_CHECKING([for tar archiver])
 AC_CHECK_PROGS(TAR, gnutar gtar tar, "")
 if test -z "$TAR"; then
     AC_MSG_ERROR([no tar archiver found in \$PATH])
 fi
-AC_MSG_RESULT([$TAR])
 AC_SUBST(TAR)
 
-AC_MSG_CHECKING([for wget])
 AC_CHECK_PROGS(WGET, wget, "")
-AC_MSG_RESULT([$WGET])
 AC_SUBST(WGET)
 
 dnl ========================================================
 dnl Signing
 dnl ========================================================
 
 if test -n "$MOZ_SIGN_CMD"; then
     AC_DEFINE(MOZ_SIGNING)
@@ -8562,16 +8566,17 @@ AC_SUBST(MOZ_D3DCOMPILER_XP_DLL)
 AC_SUBST(MOZ_D3DCOMPILER_XP_CAB)
 
 AC_SUBST(MOZ_METRO)
 
 AC_SUBST(MOZ_ANDROID_HISTORY)
 AC_SUBST(MOZ_WEBSMS_BACKEND)
 AC_SUBST(MOZ_ANDROID_BEAM)
 AC_SUBST(MOZ_ANDROID_SYNTHAPKS)
+AC_SUBST(MOZ_LOCALE_SWITCHER)
 AC_SUBST(MOZ_DISABLE_GECKOVIEW)
 AC_SUBST(ENABLE_STRIP)
 AC_SUBST(PKG_SKIP_STRIP)
 AC_SUBST(STRIP_FLAGS)
 AC_SUBST(USE_ELF_HACK)
 AC_SUBST(INCREMENTAL_LINKER)
 AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
 AC_SUBST(MOZ_COMPONENT_NSPR_LIBS)
@@ -9018,25 +9023,27 @@ HAVE_SYS_MOUNT_H
 "
 
 AC_SUBST(STLPORT_LIBS)
 
 dnl ========================================================
 dnl ICU Support
 dnl ========================================================
 
-if test "$MOZ_BUILD_APP" = "browser"; then
-    _INTL_API=yes
+# Internationalization isn't built or exposed by default in non-desktop
+# builds.  Bugs to enable:
+#
+#   Android:  bug 864843
+#   B2G:      bug 866301
+
+if test "$MOZ_WIDGET_TOOLKIT" = "android" ||
+   test "$MOZ_BUILD_APP" = "b2g"; then
+    _INTL_API=no
 else
-    # Internationalization isn't built or exposed by default in non-desktop
-    # builds.  Bugs to enable:
-    #
-    #   Android:  bug 864843
-    #   B2G:      bug 866301
-    _INTL_API=no
+    _INTL_API=yes
 fi
 
 MOZ_CONFIG_ICU()
 
 if test -n "$MOZ_NATIVE_ICU"; then
     MOZ_JS_STATIC_LIBS="$MOZ_JS_STATIC_LIBS $MOZ_ICU_LIBS"
 fi
 
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -2592,19 +2592,20 @@ Serialize(FragmentOrElement* aRoot, bool
 
       if ((next = current->GetNextSibling())) {
         current = next;
         break;
       }
 
       current = current->GetParentNode();
 
-      // Template case, if we are in a template's content, then the parent
-      // should be the host template element.
-      if (current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+      // Handle template element. If the parent is a template's content,
+      // then adjust the parent to be the template element.
+      if (current != aRoot &&
+          current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
         DocumentFragment* frag = static_cast<DocumentFragment*>(current);
         nsIContent* fragHost = frag->GetHost();
         if (fragHost && nsNodeUtils::IsTemplateElement(fragHost)) {
           current = fragHost;
         }
       }
 
       if (aDescendentsOnly && current == aRoot) {
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -435,16 +435,21 @@ struct TraceClosure
 };
 
 static PLDHashOperator
 TraceActiveWindowGlobal(const uint64_t& aId, nsGlobalWindow*& aWindow, void* aClosure)
 {
   if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
     TraceClosure* closure = static_cast<TraceClosure*>(aClosure);
     aWindow->TraceGlobalJSObject(closure->mTrc);
+    EventListenerManager* elm = aWindow->GetExistingListenerManager();
+    if (elm) {
+      elm->TraceListeners(closure->mTrc);
+    }
+
 #ifdef MOZ_XUL
     nsIDocument* doc = aWindow->GetExtantDoc();
     if (doc && doc->IsXUL()) {
       XULDocument* xulDoc = static_cast<XULDocument*>(doc);
       xulDoc->TraceProtos(closure->mTrc, closure->mGCNumber);
     }
 #endif
   }
--- a/content/base/src/nsCSPParser.cpp
+++ b/content/base/src/nsCSPParser.cpp
@@ -226,18 +226,18 @@ nsCSPParser::port()
 
   // Port might be "*"
   if (accept(WILDCARD)) {
     return true;
   }
 
   // Port must start with a number
   if (!accept(isNumberToken)) {
-    const char16_t* params[] = { mCurValue.get() };
-    logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
+    const char16_t* params[] = { mCurToken.get() };
+    logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParsePort",
                              params, ArrayLength(params));
     return false;
   }
   // Consume more numbers and set parsed port to the nsCSPHost
   while (accept(isNumberToken)) { /* consume */ }
   return true;
 }
 
@@ -255,16 +255,24 @@ nsCSPParser::subPath(nsCSPHostSrc* aCspH
 
   while (!atEnd() && !peek(DOT)) {
     ++charCounter;
     while (hostChar() || accept(UNDERLINE)) {
       /* consume */
       ++charCounter;
     }
     if (accept(SLASH)) {
+      // do not accept double slashes
+      // see http://tools.ietf.org/html/rfc3986#section-3.3
+      if (accept(SLASH)) {
+        const char16_t* params[] = { mCurToken.get() };
+        logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
+                                 params, ArrayLength(params));
+        return false;
+      }
       aCspHost->appendPath(mCurValue);
       // Resetting current value since we are appending parts of the path
       // to aCspHost, e.g; "http://www.example.com/path1/path2" then the
       // first part is "/path1", second part "/path2"
       resetCurValue();
     }
     if (charCounter > kSubHostPathCharacterCutoff) {
       return false;
@@ -284,22 +292,28 @@ nsCSPParser::path(nsCSPHostSrc* aCspHost
 
   // Resetting current value and forgetting everything we have parsed so far
   // e.g. parsing "http://www.example.com/path1/path2", then
   // "http://www.example.com" has already been parsed so far
   // forget about it.
   resetCurValue();
 
   if (!accept(SLASH)) {
+    const char16_t* params[] = { mCurToken.get() };
+    logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
+                             params, ArrayLength(params));
     return false;
   }
   if (atEnd()) {
     return true;
   }
   if (!hostChar()) {
+    const char16_t* params[] = { mCurToken.get() };
+    logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
+                             params, ArrayLength(params));
     return false;
   }
   return subPath(aCspHost);
 }
 
 bool
 nsCSPParser::subHost()
 {
@@ -342,44 +356,44 @@ nsCSPParser::host()
   // "https://*", "*.example.com", "*:*", etc.
   if (accept(WILDCARD)) {
     // Might solely be the wildcard
     if (atEnd() || peek(COLON)) {
       return new nsCSPHostSrc(mCurValue);
     }
     // If the token is not only the "*", a "." must follow right after
     if (!accept(DOT)) {
-      const char16_t* params[] = { mCurValue.get() };
-      logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
+      const char16_t* params[] = { mCurToken.get() };
+      logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidHost",
                                params, ArrayLength(params));
       return nullptr;
     }
   }
 
   // Expecting at least one Character
   if (!accept(isCharacterToken)) {
-    const char16_t* params[] = { mCurValue.get() };
-    logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
+    const char16_t* params[] = { mCurToken.get() };
+    logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidHost",
                              params, ArrayLength(params));
     return nullptr;
   }
 
   // There might be several sub hosts defined.
   if (!subHost()) {
-    const char16_t* params[] = { mCurValue.get() };
-    logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
+    const char16_t* params[] = { mCurToken.get() };
+    logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidHost",
                              params, ArrayLength(params));
     return nullptr;
   }
 
   // HostName might match a keyword, log to the console.
   if (CSP_IsQuotelessKeyword(mCurValue)) {
     nsString keyword = mCurValue;
     ToLowerCase(keyword);
-    const char16_t* params[] = { mCurValue.get(), keyword.get() };
+    const char16_t* params[] = { mCurToken.get(), keyword.get() };
     logWarningErrorToConsole(nsIScriptError::warningFlag, "hostNameMightBeKeyword",
                              params, ArrayLength(params));
   }
 
   // Create a new nsCSPHostSrc with the parsed host.
   return new nsCSPHostSrc(mCurValue);
 }
 
@@ -390,18 +404,18 @@ nsCSPParser::appHost()
   CSPPARSERLOG(("nsCSPParser::appHost, mCurToken: %s, mCurValue: %s",
                NS_ConvertUTF16toUTF8(mCurToken).get(),
                NS_ConvertUTF16toUTF8(mCurValue).get()));
 
   while (hostChar()) { /* consume */ }
 
   // appHosts have to end with "}", otherwise we have to report an error
   if (!accept(CLOSE_CURL)) {
-    const char16_t* params[] = { mCurValue.get() };
-    logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
+    const char16_t* params[] = { mCurToken.get() };
+    logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
                              params, ArrayLength(params));
     return nullptr;
   }
   return new nsCSPHostSrc(mCurValue);
 }
 
 // keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
 nsCSPBaseSrc*
@@ -459,17 +473,21 @@ nsCSPParser::hostSource()
   if (atEnd()) {
     return cspHost;
   }
 
   // Calling path() to see if there is a path to parse, if an error
   // occurs, path() reports the error; handing cspHost as an argument
   // which simplifies parsing of several paths.
   if (!path(cspHost)) {
-    return cspHost;
+    // If the host [port] is followed by a path, it has to be a valid path,
+    // otherwise we pass the nullptr, indicating an error, up the callstack.
+    // see also http://www.w3.org/TR/CSP11/#source-list
+    delete cspHost;
+    return nullptr;
   }
 
   // Calling fileAndArguments to see if there are any files to parse;
   // if an error occurs, fileAndArguments() reports the error; if
   // fileAndArguments returns true, we have a valid file, so we add it.
   if (fileAndArguments()) {
     cspHost->setFileAndArguments(mCurValue);
   }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3946,27 +3946,16 @@ nsDocument::InsertChildAt(nsIContent* aK
   if (aKid->IsElement() && GetRootElement()) {
     NS_ERROR("Inserting element child when we already have one");
     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
   }
 
   return doInsertChildAt(aKid, aIndex, aNotify, mChildren);
 }
 
-nsresult
-nsDocument::AppendChildTo(nsIContent* aKid, bool aNotify)
-{
-  // Make sure to _not_ call the subclass InsertChildAt here.  If
-  // subclasses wanted to hook into this stuff, they would have
-  // overridden AppendChildTo.
-  // XXXbz maybe this should just be a non-virtual method on nsINode?
-  // Feels that way to me...
-  return nsDocument::InsertChildAt(aKid, GetChildCount(), aNotify);
-}
-
 void
 nsDocument::RemoveChildAt(uint32_t aIndex, bool aNotify)
 {
   nsCOMPtr<nsIContent> oldKid = GetChildAt(aIndex);
   if (!oldKid) {
     return;
   }
 
@@ -4508,16 +4497,21 @@ nsDocument::SetScriptGlobalObject(nsIScr
   }
 
   // Set our visibility state, but do not fire the event.  This is correct
   // because either we're coming out of bfcache (in which case IsVisible() will
   // still test false at this point and no state change will happen) or we're
   // doing the initial document load and don't want to fire the event for this
   // change.
   mVisibilityState = GetVisibilityState();
+
+  // The global in the template contents owner document should be the same.
+  if (mTemplateContentsOwner && mTemplateContentsOwner != this) {
+    mTemplateContentsOwner->SetScriptGlobalObject(aScriptGlobalObject);
+  }
 }
 
 nsIScriptGlobalObject*
 nsDocument::GetScriptHandlingObjectInternal() const
 {
   MOZ_ASSERT(!mScriptGlobalObject,
              "Do not call this when mScriptGlobalObject is set!");
   if (mHasHadDefaultView) {
@@ -9438,17 +9432,16 @@ nsDocument::GetCurrentContentSink()
 
 nsIDocument*
 nsDocument::GetTemplateContentsOwner()
 {
   if (!mTemplateContentsOwner) {
     bool hasHadScriptObject = true;
     nsIScriptGlobalObject* scriptObject =
       GetScriptHandlingObject(hasHadScriptObject);
-    NS_ENSURE_TRUE(scriptObject || !hasHadScriptObject, nullptr);
 
     nsCOMPtr<nsIDOMDocument> domDocument;
     nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
                                     EmptyString(), // aNamespaceURI
                                     EmptyString(), // aQualifiedName
                                     nullptr, // aDoctype
                                     nsIDocument::GetDocumentURI(),
                                     nsIDocument::GetDocBaseURI(),
@@ -9456,22 +9449,26 @@ nsDocument::GetTemplateContentsOwner()
                                     true, // aLoadedAsData
                                     scriptObject, // aEventObject
                                     DocumentFlavorHTML);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     mTemplateContentsOwner = do_QueryInterface(domDocument);
     NS_ENSURE_TRUE(mTemplateContentsOwner, nullptr);
 
-    mTemplateContentsOwner->SetScriptHandlingObject(scriptObject);
+    nsDocument* doc = static_cast<nsDocument*>(mTemplateContentsOwner.get());
+    doc->mHasHadScriptHandlingObject = hasHadScriptObject;
+
+    if (!scriptObject) {
+      mTemplateContentsOwner->SetScopeObject(GetScopeObject());
+    }
 
     // Set |doc| as the template contents owner of itself so that
     // |doc| is the template contents owner of template elements created
     // by |doc|.
-    nsDocument* doc = static_cast<nsDocument*>(mTemplateContentsOwner.get());
     doc->mTemplateContentsOwner = doc;
   }
 
   return mTemplateContentsOwner;
 }
 
 void
 nsDocument::RegisterHostObjectUri(const nsACString& aUri)
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -884,17 +884,16 @@ public:
   // nsINode
   virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
   virtual nsIContent *GetChildAt(uint32_t aIndex) const MOZ_OVERRIDE;
   virtual nsIContent * const * GetChildArray(uint32_t* aChildCount) const MOZ_OVERRIDE;
   virtual int32_t IndexOf(const nsINode* aPossibleChild) const MOZ_OVERRIDE;
   virtual uint32_t GetChildCount() const MOZ_OVERRIDE;
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
                                  bool aNotify) MOZ_OVERRIDE;
-  virtual nsresult AppendChildTo(nsIContent* aKid, bool aNotify);
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) MOZ_OVERRIDE;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // nsIRadioGroupContainer
   NS_IMETHOD WalkRadioGroup(const nsAString& aName,
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -517,30 +517,41 @@ nsDocumentEncoder::SerializeToStringRecu
 }
 
 nsresult
 nsDocumentEncoder::SerializeToStringIterative(nsINode* aNode,
                                               nsAString& aStr)
 {
   nsresult rv;
 
-  nsINode* node = aNode->GetFirstChild();
+  nsINode* node = nsNodeUtils::GetFirstChildOfTemplateOrNode(aNode);
   while (node) {
     nsINode* current = node;
     rv = SerializeNodeStart(current, 0, -1, aStr, current);
     NS_ENSURE_SUCCESS(rv, rv);
-    node = current->GetFirstChild();
+    node = nsNodeUtils::GetFirstChildOfTemplateOrNode(current);
     while (!node && current && current != aNode) {
       rv = SerializeNodeEnd(current, aStr);
       NS_ENSURE_SUCCESS(rv, rv);
       // Check if we have siblings.
       node = current->GetNextSibling();
       if (!node) {
         // Perhaps parent node has siblings.
         current = current->GetParentNode();
+
+        // Handle template element. If the parent is a template's content,
+        // then adjust the parent to be the template element.
+        if (current && current != aNode &&
+            current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+          DocumentFragment* frag = static_cast<DocumentFragment*>(current);
+          nsIContent* host = frag->GetHost();
+          if (host && host->IsHTML(nsGkAtoms::_template)) {
+            current = host;
+          }
+        }
       }
     }
   }
 
   return NS_OK;
 }
 
 bool 
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -18,17 +18,16 @@
 #include "nsIDocument.h"
 #include "nsIDOMText.h"
 #include "nsError.h"
 #include "nsIContentIterator.h"
 #include "nsIDOMNodeList.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsGenericDOMDataNode.h"
-#include "nsLayoutUtils.h"
 #include "nsTextFrame.h"
 #include "nsFontFaceList.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/RangeBinding.h"
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/Telemetry.h"
@@ -2787,20 +2786,21 @@ static nsresult GetPartialTextRect(nsLay
         ExtractRectFromOffset(f, relativeTo, aEndOffset, &r, !rtl);
       }
       aCallback->AddRect(r);
     }
   }
   return NS_OK;
 }
 
-static void CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
-                               nsRange* aRange,
-                               nsINode* aStartParent, int32_t aStartOffset,
-                               nsINode* aEndParent, int32_t aEndOffset)
+/* static */ void
+nsRange::CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
+                            nsRange* aRange,
+                            nsINode* aStartParent, int32_t aStartOffset,
+                            nsINode* aEndParent, int32_t aEndOffset)
 {
   // Hold strong pointers across the flush
   nsCOMPtr<nsINode> startContainer = aStartParent;
   nsCOMPtr<nsINode> endContainer = aEndParent;
 
   // Flush out layout so our frames are up to date.
   if (!aStartParent->IsInDoc()) {
     return;
@@ -2821,17 +2821,17 @@ static void CollectClientRects(nsLayoutU
   if (iter.IsDone()) {
     // the range is collapsed, only continue if the cursor is in a text node
     nsCOMPtr<nsIContent> content = do_QueryInterface(aStartParent);
     if (content && content->IsNodeOfType(nsINode::eTEXT)) {
       nsTextFrame* textFrame = GetTextFrameForContent(content);
       if (textFrame) {
         int32_t outOffset;
         nsIFrame* outFrame;
-        textFrame->GetChildFrameContainingOffset(aStartOffset, false, 
+        textFrame->GetChildFrameContainingOffset(aStartOffset, false,
           &outOffset, &outFrame);
         if (outFrame) {
            nsIFrame* relativeTo =
              nsLayoutUtils::GetContainingBlockForClientRect(outFrame);
            nsRect r(outFrame->GetOffsetTo(relativeTo), outFrame->GetSize());
            ExtractRectFromOffset(outFrame, relativeTo, aStartOffset, &r, false);
            r.width = 0;
            aCollector->AddRect(r);
--- a/content/base/src/nsRange.h
+++ b/content/base/src/nsRange.h
@@ -10,16 +10,17 @@
 #ifndef nsRange_h___
 #define nsRange_h___
 
 #include "nsIDOMRange.h"
 #include "nsCOMPtr.h"
 #include "nsINode.h"
 #include "nsIDocument.h"
 #include "nsIDOMNode.h"
+#include "nsLayoutUtils.h"
 #include "prmon.h"
 #include "nsStubMutationObserver.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
 
 namespace mozilla {
 class ErrorResult;
 namespace dom {
@@ -249,16 +250,21 @@ public:
  *****************************************************************************/
   static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
                                      bool *outNodeBefore,
                                      bool *outNodeAfter);
 
   static bool IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
                              uint32_t aEndOffset);
 
+  static void CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
+                                 nsRange* aRange,
+                                 nsINode* aStartParent, int32_t aStartOffset,
+                                 nsINode* aEndParent, int32_t aEndOffset);
+
   typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
 protected:
   void RegisterCommonAncestor(nsINode* aNode);
   void UnregisterCommonAncestor(nsINode* aNode);
   nsINode* IsValidBoundary(nsINode* aNode);
 
   // CharacterDataChanged set aNotInsertedYet to true to disable an assertion
   // and suppress re-registering a range common ancestor node since
--- a/content/base/src/nsStyleLinkElement.cpp
+++ b/content/base/src/nsStyleLinkElement.cpp
@@ -10,16 +10,17 @@
  * stylesheets (<style>, <link>, processing instructions, etc).
  */
 
 #include "nsStyleLinkElement.h"
 
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/Element.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"
@@ -115,29 +116,44 @@ nsStyleLinkElement::OverrideBaseURI(nsIU
 }
 
 /* virtual */ void
 nsStyleLinkElement::SetLineNumber(uint32_t aLineNumber)
 {
   mLineNumber = aLineNumber;
 }
 
+/* static */ bool
+nsStyleLinkElement::IsImportEnabled()
+{
+  static bool sAdded = false;
+  static bool sImportEnabled;
+  if (!sAdded) {
+    // This part runs only once because of the static flag.
+    Preferences::AddBoolVarCache(&sImportEnabled,
+                                 "dom.webcomponents.enabled",
+                                 false);
+    sAdded = true;
+  }
+  return sImportEnabled;
+}
+
 static uint32_t ToLinkMask(const nsAString& aLink)
 { 
   if (aLink.EqualsLiteral("prefetch"))
     return nsStyleLinkElement::ePREFETCH;
   else if (aLink.EqualsLiteral("dns-prefetch"))
     return nsStyleLinkElement::eDNS_PREFETCH;
   else if (aLink.EqualsLiteral("stylesheet"))
     return nsStyleLinkElement::eSTYLESHEET;
   else if (aLink.EqualsLiteral("next"))
     return nsStyleLinkElement::eNEXT;
   else if (aLink.EqualsLiteral("alternate"))
     return nsStyleLinkElement::eALTERNATE;
-  else if (aLink.EqualsLiteral("import"))
+  else if (aLink.EqualsLiteral("import") && nsStyleLinkElement::IsImportEnabled())
     return nsStyleLinkElement::eHTMLIMPORT;
   else 
     return 0;
 }
 
 uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
 {
   uint32_t linkMask = 0;
--- a/content/base/src/nsStyleLinkElement.h
+++ b/content/base/src/nsStyleLinkElement.h
@@ -59,16 +59,18 @@ public:
     eNEXT =         0x00000008,
     eALTERNATE =    0x00000010,
     eHTMLIMPORT =   0x00000020
   };
 
   // The return value is a bitwise or of 0 or more RelValues
   static uint32_t ParseLinkTypes(const nsAString& aTypes);
 
+  static bool IsImportEnabled();
+  
   void UpdateStyleSheetInternal()
   {
     UpdateStyleSheetInternal(nullptr, nullptr);
   }
 protected:
   /**
    * @param aOldDocument should be non-null only if we're updating because we
    *                     removed the node from the document.
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -2520,18 +2520,18 @@ GetRequestBody(nsIVariant* aBody, nsIInp
 
     // ArrayBuffer?
     AutoSafeJSContext cx;
     JS::Rooted<JS::Value> realVal(cx);
 
     nsresult rv = aBody->GetAsJSVal(&realVal);
     if (NS_SUCCEEDED(rv) && !realVal.isPrimitive()) {
       JS::Rooted<JSObject*> obj(cx, realVal.toObjectOrNull());
-      if (JS_IsArrayBufferObject(obj)) {
-          ArrayBuffer buf(obj);
+      ArrayBuffer buf;
+      if (buf.Init(obj)) {
           buf.ComputeLengthAndData();
           return GetRequestBody(buf.Data(), buf.Length(), aResult,
                                 aContentLength, aContentType, aCharset);
       }
     }
   }
   else if (dataType == nsIDataType::VTYPE_VOID ||
            dataType == nsIDataType::VTYPE_EMPTY) {
--- a/content/base/test/TestCSPParser.cpp
+++ b/content/base/test/TestCSPParser.cpp
@@ -402,38 +402,16 @@ nsresult TestSimplePolicies() {
 nsresult TestPoliciesThatLogWarning() {
 
   static const PolicyTest policies[] =
   {
     { "script-src 'self'; SCRIPT-SRC http://www.example.com",
       "script-src http://www.selfuri.com" },
     { "script-src 'none' test.com; script-src example.com",
       "script-src http://test.com" },
-    { "script-src http://www.example.com//",
-      "script-src http://www.example.com" },
-    { "script-src http://www.example.com/path-1//",
-      "script-src http://www.example.com" },
-    { "script-src http://www.example.com/path-1//path_2",
-      "script-src http://www.example.com" },
-    { "script-src http://www.example.com:88path-1/",
-      "script-src http://www.example.com:88" },
-    { "script-src http://www.example.com:88//",
-      "script-src http://www.example.com:88" },
-    { "script-src http://www.example.com:88//path-1",
-      "script-src http://www.example.com:88" },
-    { "script-src http://www.example.com:88//path-1",
-      "script-src http://www.example.com:88" },
-    { "script-src http://www.example.com:88/.js",
-      "script-src http://www.example.com:88" },
-    { "script-src http://www.example.com:88.js",
-      "script-src http://www.example.com:88" },
-    { "script-src http://www.example.com:*.js",
-      "script-src http://www.example.com:*" },
-    { "script-src http://www.example.com:*.",
-      "script-src http://www.example.com:*" }
   };
 
   uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
   return runTestSuite(policies, policyCount, 1);
 }
 
 // ============================= TestBadPolicies ========================
 
@@ -456,17 +434,28 @@ nsresult TestBadPolicies() {
     { "default-src 'unsafe-inlin' ", "" },
     { "default-src :88", "" },
     { "script-src abc::::::88", "" },
     { "asdf http://test.com", ""},
     { "script-src *.*:*", "" },
     { "img-src *::88", "" },
     { "object-src http://localhost:", "" },
     { "script-src test..com", "" },
-    { "script-src sub1.sub2.example+", "" }
+    { "script-src sub1.sub2.example+", "" },
+    { "script-src http://www.example.com//", "" },
+    { "script-src http://www.example.com/path-1//", "" },
+    { "script-src http://www.example.com/path-1//path_2", "" },
+    { "script-src http://www.example.com:88path-1/", "" },
+    { "script-src http://www.example.com:88//", "" },
+    { "script-src http://www.example.com:88//path-1", "" },
+    { "script-src http://www.example.com:88//path-1", "" },
+    { "script-src http://www.example.com:88/.js", "" },
+    { "script-src http://www.example.com:88.js", "" },
+    { "script-src http://www.example.com:*.js", "" },
+    { "script-src http://www.example.com:*.", "" },
   };
 
   uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
   return runTestSuite(policies, policyCount, 0);
 }
 
 // ============================= TestGoodGeneratedPolicies ========================
 
--- a/content/base/test/unit/xpcshell.ini
+++ b/content/base/test/unit/xpcshell.ini
@@ -22,12 +22,14 @@ support-files =
 
 [test_bug553888.js]
 [test_bug558431.js]
 [test_bug737966.js]
 [test_csputils.js]
 [test_cspreports.js]
 [test_error_codes.js]
 run-sequentially = Hardcoded 4444 port.
+# Bug 1018414: hardcoded localhost doesn't work properly on some OS X installs
+skip-if = os == 'mac'
 [test_thirdpartyutil.js]
 [test_xhr_standalone.js]
 [test_xmlserializer.js]
 [test_csp_ignores_path.js]
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -65,16 +65,17 @@
 #include <algorithm>
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 
 #include "mozilla/Alignment.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/CheckedInt.h"
+#include "mozilla/DebugOnly.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/Endian.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
@@ -4001,31 +4002,35 @@ CanvasRenderingContext2D::FillRuleChange
     mPath = nullptr;
   }
 }
 
 void
 CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
                                        double dy, ErrorResult& error)
 {
-  dom::Uint8ClampedArray arr(imageData.GetDataObject());
+  dom::Uint8ClampedArray arr;
+  DebugOnly<bool> inited = arr.Init(imageData.GetDataObject());
+  MOZ_ASSERT(inited);
 
   error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
                                 imageData.Width(), imageData.Height(),
                                 &arr, false, 0, 0, 0, 0);
 }
 
 void
 CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
                                        double dy, double dirtyX,
                                        double dirtyY, double dirtyWidth,
                                        double dirtyHeight,
                                        ErrorResult& error)
 {
-  dom::Uint8ClampedArray arr(imageData.GetDataObject());
+  dom::Uint8ClampedArray arr;
+  DebugOnly<bool> inited = arr.Init(imageData.GetDataObject());
+  MOZ_ASSERT(inited);
 
   error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
                                 imageData.Width(), imageData.Height(),
                                 &arr, true,
                                 JS_DoubleToInt32(dirtyX),
                                 JS_DoubleToInt32(dirtyY),
                                 JS_DoubleToInt32(dirtyWidth),
                                 JS_DoubleToInt32(dirtyHeight));
--- a/content/canvas/src/WebGLBuffer.cpp
+++ b/content/canvas/src/WebGLBuffer.cpp
@@ -67,16 +67,21 @@ WebGLBuffer::SizeOfIncludingThis(mozilla
 bool
 WebGLBuffer::Validate(GLenum type, uint32_t max_allowed,
                       size_t first, size_t count,
                       uint32_t* out_upperBound)
 {
     return mCache->Validate(type, max_allowed, first, count, out_upperBound);
 }
 
+bool
+WebGLBuffer::IsElementArrayUsedWithMultipleTypes() const
+{
+    return mCache->BeenUsedWithMultipleTypes();
+}
 
 JSObject*
 WebGLBuffer::WrapObject(JSContext *cx) {
     return dom::WebGLBufferBinding::Wrap(cx, this);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLBuffer)
 
--- a/content/canvas/src/WebGLBuffer.h
+++ b/content/canvas/src/WebGLBuffer.h
@@ -44,16 +44,18 @@ public:
 
     bool ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes);
 
     void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes);
 
     bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count,
                   uint32_t* out_upperBound);
 
+    bool IsElementArrayUsedWithMultipleTypes() const;
+
     WebGLContext *GetParentObject() const {
         return Context();
     }
 
     virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBuffer)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLBuffer)
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -208,16 +208,24 @@ public:
     void ErrorInvalidEnum(const char *fmt = 0, ...);
     void ErrorInvalidOperation(const char *fmt = 0, ...);
     void ErrorInvalidValue(const char *fmt = 0, ...);
     void ErrorInvalidFramebufferOperation(const char *fmt = 0, ...);
     void ErrorInvalidEnumInfo(const char *info, GLenum enumvalue);
     void ErrorOutOfMemory(const char *fmt = 0, ...);
 
     const char *ErrorName(GLenum error);
+
+    /**
+     * Return displayable name for GLenum.
+     * This version is like gl::GLenumToStr but with out the GL_ prefix to
+     * keep consistency with how errors are reported from WebGL.
+     */
+    static const char *EnumName(GLenum glenum);
+
     bool IsTextureFormatCompressed(GLenum format);
 
     void DummyFramebufferOperation(const char *info);
 
     WebGLTexture* activeBoundTextureForTarget(GLenum target) const {
         MOZ_ASSERT(!IsTextureBinding(target));
         return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
                                              : mBoundCubeMapTextures[mActiveTexture];
--- a/content/canvas/src/WebGLContextDraw.cpp
+++ b/content/canvas/src/WebGLContextDraw.cpp
@@ -255,16 +255,24 @@ WebGLContext::DrawElements_check(GLsizei
         return false;
     }
 
     if (uint32_t(primcount) > mMaxFetchedInstances) {
         ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
         return false;
     }
 
+    // Bug 1008310 - Check if buffer has been used with a different previous type
+    if (elemArrayBuffer.IsElementArrayUsedWithMultipleTypes()) {
+        GenerateWarning("%s: bound element array buffer previously used with a type other than "
+                        "%s, this will affect performance.",
+                        info,
+                        WebGLContext::EnumName(type));
+    }
+
     MakeContextCurrent();
 
     if (mBoundFramebuffer) {
         if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
             ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
             return false;
         }
     } else {
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -37,16 +37,17 @@
 #include "WebGLValidateStrings.h"
 #include <algorithm>
 
 // needed to check if current OS is lower than 10.7
 #if defined(MOZ_WIDGET_COCOA)
 #include "nsCocoaFeatures.h"
 #endif
 
+#include "mozilla/DebugOnly.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/Endian.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gl;
@@ -3708,17 +3709,19 @@ WebGLContext::TexImage2D(GLenum target, 
     if (IsContextLost())
         return;
 
     if (!pixels) {
         // Spec says to generate an INVALID_VALUE error
         return ErrorInvalidValue("texImage2D: null ImageData");
     }
 
-    Uint8ClampedArray arr(pixels->GetDataObject());
+    Uint8ClampedArray arr;
+    DebugOnly<bool> inited = arr.Init(pixels->GetDataObject());
+    MOZ_ASSERT(inited);
     arr.ComputeLengthAndData();
 
     return TexImage2D_base(target, level, internalformat, pixels->Width(),
                            pixels->Height(), 4*pixels->Width(), 0,
                            format, type, arr.Data(), arr.Length(), -1,
                            WebGLTexelFormat::RGBA8, false);
 }
 
@@ -3841,17 +3844,19 @@ WebGLContext::TexSubImage2D(GLenum targe
                             ErrorResult& rv)
 {
     if (IsContextLost())
         return;
 
     if (!pixels)
         return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
 
-    Uint8ClampedArray arr(pixels->GetDataObject());
+    Uint8ClampedArray arr;
+    DebugOnly<bool> inited = arr.Init(pixels->GetDataObject());
+    MOZ_ASSERT(inited);
     arr.ComputeLengthAndData();
 
     return TexSubImage2D_base(target, level, xoffset, yoffset,
                               pixels->Width(), pixels->Height(),
                               4*pixels->Width(), format, type,
                               arr.Data(), arr.Length(),
                               -1,
                               WebGLTexelFormat::RGBA8, false);
--- a/content/canvas/src/WebGLContextUtils.cpp
+++ b/content/canvas/src/WebGLContextUtils.cpp
@@ -357,16 +357,74 @@ WebGLContext::ErrorName(GLenum error)
         case LOCAL_GL_NO_ERROR:
             return "NO_ERROR";
         default:
             MOZ_ASSERT(false);
             return "[unknown WebGL error!]";
     }
 }
 
+const char*
+WebGLContext::EnumName(GLenum glenum)
+{
+    switch (glenum) {
+#define XX(x) case LOCAL_GL_##x: return #x
+        XX(ALPHA);
+        XX(ATC_RGB);
+        XX(ATC_RGBA_EXPLICIT_ALPHA);
+        XX(ATC_RGBA_INTERPOLATED_ALPHA);
+        XX(COMPRESSED_RGBA_PVRTC_2BPPV1);
+        XX(COMPRESSED_RGBA_PVRTC_4BPPV1);
+        XX(COMPRESSED_RGBA_S3TC_DXT1_EXT);
+        XX(COMPRESSED_RGBA_S3TC_DXT3_EXT);
+        XX(COMPRESSED_RGBA_S3TC_DXT5_EXT);
+        XX(COMPRESSED_RGB_PVRTC_2BPPV1);
+        XX(COMPRESSED_RGB_PVRTC_4BPPV1);
+        XX(COMPRESSED_RGB_S3TC_DXT1_EXT);
+        XX(DEPTH_COMPONENT);
+        XX(DEPTH_COMPONENT16);
+        XX(DEPTH_COMPONENT32);
+        XX(DEPTH_STENCIL);
+        XX(DEPTH24_STENCIL8);
+        XX(ETC1_RGB8_OES);
+        XX(FLOAT);
+        XX(HALF_FLOAT);
+        XX(LUMINANCE);
+        XX(LUMINANCE_ALPHA);
+        XX(RGB);
+        XX(RGB16F);
+        XX(RGB32F);
+        XX(RGBA);
+        XX(RGBA16F);
+        XX(RGBA32F);
+        XX(SRGB);
+        XX(SRGB_ALPHA);
+        XX(TEXTURE_2D);
+        XX(TEXTURE_3D);
+        XX(TEXTURE_CUBE_MAP);
+        XX(TEXTURE_CUBE_MAP_NEGATIVE_X);
+        XX(TEXTURE_CUBE_MAP_NEGATIVE_Y);
+        XX(TEXTURE_CUBE_MAP_NEGATIVE_Z);
+        XX(TEXTURE_CUBE_MAP_POSITIVE_X);
+        XX(TEXTURE_CUBE_MAP_POSITIVE_Y);
+        XX(TEXTURE_CUBE_MAP_POSITIVE_Z);
+        XX(UNSIGNED_BYTE);
+        XX(UNSIGNED_INT);
+        XX(UNSIGNED_INT_24_8);
+        XX(UNSIGNED_SHORT);
+        XX(UNSIGNED_SHORT_4_4_4_4);
+        XX(UNSIGNED_SHORT_5_5_5_1);
+        XX(UNSIGNED_SHORT_5_6_5);
+#undef XX
+    }
+
+    return "[Unknown enum name]";
+}
+
+
 bool
 WebGLContext::IsTextureFormatCompressed(GLenum format)
 {
     switch (format) {
         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -77,85 +77,23 @@ InfoFrom(WebGLTexImageFunc func)
     case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage2D";
     default:
         MOZ_ASSERT(false, "Missing case for WebGLTexImageSource");
         return "(error)";
     }
 }
 
 /**
- * Return displayable name for GLenum.
- * This version is like gl::GLenumToStr but with out the GL_ prefix to
- * keep consistency with how errors are reported from WebGL.
- */
-static const char*
-NameFrom(GLenum glenum)
-{
-    switch (glenum) {
-#define XX(x) case LOCAL_GL_##x: return #x
-        XX(ALPHA);
-        XX(ATC_RGB);
-        XX(ATC_RGBA_EXPLICIT_ALPHA);
-        XX(ATC_RGBA_INTERPOLATED_ALPHA);
-        XX(COMPRESSED_RGBA_PVRTC_2BPPV1);
-        XX(COMPRESSED_RGBA_PVRTC_4BPPV1);
-        XX(COMPRESSED_RGBA_S3TC_DXT1_EXT);
-        XX(COMPRESSED_RGBA_S3TC_DXT3_EXT);
-        XX(COMPRESSED_RGBA_S3TC_DXT5_EXT);
-        XX(COMPRESSED_RGB_PVRTC_2BPPV1);
-        XX(COMPRESSED_RGB_PVRTC_4BPPV1);
-        XX(COMPRESSED_RGB_S3TC_DXT1_EXT);
-        XX(DEPTH_COMPONENT);
-        XX(DEPTH_COMPONENT16);
-        XX(DEPTH_COMPONENT32);
-        XX(DEPTH_STENCIL);
-        XX(DEPTH24_STENCIL8);
-        XX(ETC1_RGB8_OES);
-        XX(FLOAT);
-        XX(HALF_FLOAT);
-        XX(LUMINANCE);
-        XX(LUMINANCE_ALPHA);
-        XX(RGB);
-        XX(RGB16F);
-        XX(RGB32F);
-        XX(RGBA);
-        XX(RGBA16F);
-        XX(RGBA32F);
-        XX(SRGB);
-        XX(SRGB_ALPHA);
-        XX(TEXTURE_2D);
-        XX(TEXTURE_3D);
-        XX(TEXTURE_CUBE_MAP);
-        XX(TEXTURE_CUBE_MAP_NEGATIVE_X);
-        XX(TEXTURE_CUBE_MAP_NEGATIVE_Y);
-        XX(TEXTURE_CUBE_MAP_NEGATIVE_Z);
-        XX(TEXTURE_CUBE_MAP_POSITIVE_X);
-        XX(TEXTURE_CUBE_MAP_POSITIVE_Y);
-        XX(TEXTURE_CUBE_MAP_POSITIVE_Z);
-        XX(UNSIGNED_BYTE);
-        XX(UNSIGNED_INT);
-        XX(UNSIGNED_INT_24_8);
-        XX(UNSIGNED_SHORT);
-        XX(UNSIGNED_SHORT_4_4_4_4);
-        XX(UNSIGNED_SHORT_5_5_5_1);
-        XX(UNSIGNED_SHORT_5_6_5);
-#undef XX
-    }
-
-    return nullptr;
-}
-
-/**
- * Same as ErrorInvalidEnum but uses NameFrom to print displayable
+ * Same as ErrorInvalidEnum but uses WebGLContext::EnumName to print displayable
  * name for \a glenum.
  */
 static void
 ErrorInvalidEnumWithName(WebGLContext* ctx, const char* msg, GLenum glenum, WebGLTexImageFunc func)
 {
-    const char* name = NameFrom(glenum);
+    const char* name = WebGLContext::EnumName(glenum);
     if (name)
         ctx->ErrorInvalidEnum("%s: %s %s", InfoFrom(func), msg, name);
     else
         ctx->ErrorInvalidEnum("%s: %s 0x%04X", InfoFrom(func), msg, glenum);
 }
 
 /**
  * Return true if the format is valid for source calls.
@@ -599,75 +537,75 @@ WebGLContext::ValidateTexImageFormat(GLe
 
     /* WEBGL_depth_texture added formats */
     if (format == LOCAL_GL_DEPTH_COMPONENT ||
         format == LOCAL_GL_DEPTH_STENCIL)
     {
         bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture);
         if (!validFormat)
             ErrorInvalidEnum("%s: invalid format %s: need WEBGL_depth_texture enabled",
-                             InfoFrom(func), NameFrom(format));
+                             InfoFrom(func), WebGLContext::EnumName(format));
         return validFormat;
     }
 
     /* EXT_sRGB added formats */
     if (format == LOCAL_GL_SRGB ||
         format == LOCAL_GL_SRGB_ALPHA)
     {
         bool validFormat = IsExtensionEnabled(WebGLExtensionID::EXT_sRGB);
         if (!validFormat)
             ErrorInvalidEnum("%s: invalid format %s: need EXT_sRGB enabled",
-                             InfoFrom(func), NameFrom(format));
+                             InfoFrom(func), WebGLContext::EnumName(format));
         return validFormat;
     }
 
     /* WEBGL_compressed_texture_atc added formats */
     if (format == LOCAL_GL_ATC_RGB ||
         format == LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA ||
         format == LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA)
     {
         bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_atc);
         if (!validFormat)
             ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_atc enabled",
-                             InfoFrom(func), NameFrom(format));
+                             InfoFrom(func), WebGLContext::EnumName(format));
         return validFormat;
     }
 
     // WEBGL_compressed_texture_etc1
     if (format == LOCAL_GL_ETC1_RGB8_OES) {
         bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_etc1);
         if (!validFormat)
             ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_etc1 enabled",
-                             InfoFrom(func), NameFrom(format));
+                             InfoFrom(func), WebGLContext::EnumName(format));
         return validFormat;
     }
 
 
     if (format == LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1 ||
         format == LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1 ||
         format == LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1 ||
         format == LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1)
     {
         bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_pvrtc);
         if (!validFormat)
             ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_pvrtc enabled",
-                             InfoFrom(func), NameFrom(format));
+                             InfoFrom(func), WebGLContext::EnumName(format));
         return validFormat;
     }
 
 
     if (format == LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
         format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
         format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
         format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
     {
         bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_s3tc);
         if (!validFormat)
             ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_s3tc enabled",
-                             InfoFrom(func), NameFrom(format));
+                             InfoFrom(func), WebGLContext::EnumName(format));
         return validFormat;
     }
 
     ErrorInvalidEnumWithName(this, "invalid format", format, func);
 
     return false;
 }
 
@@ -711,38 +649,38 @@ WebGLContext::ValidateTexImageType(GLenu
         return true;
     }
 
     /* OES_texture_float added types */
     if (type == LOCAL_GL_FLOAT) {
         bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_float);
         if (!validType)
             ErrorInvalidEnum("%s: invalid type %s: need OES_texture_float enabled",
-                             InfoFrom(func), NameFrom(type));
+                             InfoFrom(func), WebGLContext::EnumName(type));
         return validType;
     }
 
     /* OES_texture_half_float add types */
     if (type == LOCAL_GL_HALF_FLOAT_OES) {
         bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float);
         if (!validType)
             ErrorInvalidEnum("%s: invalid type %s: need OES_texture_half_float enabled",
-                             InfoFrom(func), NameFrom(type));
+                             InfoFrom(func), WebGLContext::EnumName(type));
         return validType;
     }
 
     /* WEBGL_depth_texture added types */
     if (type == LOCAL_GL_UNSIGNED_SHORT ||
         type == LOCAL_GL_UNSIGNED_INT ||
         type == LOCAL_GL_UNSIGNED_INT_24_8)
     {
         bool validType = IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture);
         if (!validType)
             ErrorInvalidEnum("%s: invalid type %s: need WEBGL_depth_texture enabled",
-                             InfoFrom(func), NameFrom(type));
+                             InfoFrom(func), WebGLContext::EnumName(type));
         return validType;
     }
 
     ErrorInvalidEnumWithName(this, "invalid type", type, func);
     return false;
 }
 
 /**
@@ -1239,17 +1177,17 @@ WebGLContext::ValidateTexImageFormatAndT
         MOZ_ASSERT(false, "Unexpected format and type combo. How'd this happen?");
         validCombo = false;
         // Fall through to return an InvalidOperations. This will alert us to the
         // unexpected case that needs fixing in builds without asserts.
     }
 
     if (!validCombo)
         ErrorInvalidOperation("%s: invalid combination of format %s and type %s",
-                              InfoFrom(func), NameFrom(format), NameFrom(type));
+                              InfoFrom(func), WebGLContext::EnumName(format), WebGLContext::EnumName(type));
 
     return validCombo;
 }
 
 /**
  * Return true if format, type and jsArrayType are a valid combination.
  * Also returns the size for texel of format and type (in bytes) via
  * \a texelSize.
@@ -1361,24 +1299,24 @@ WebGLContext::ValidateTexImage(GLuint di
     /* 5.14.8 Texture objects - WebGL Spec.
      *   "If an attempt is made to call these functions with no
      *    WebGLTexture bound (see above), an INVALID_OPERATION error
      *    is generated."
      */
     WebGLTexture* tex = activeBoundTextureForTarget(target);
     if (!tex) {
         ErrorInvalidOperation("%s: no texture is bound to target %s",
-                              info, NameFrom(target));
+                              info, WebGLContext::EnumName(target));
         return false;
     }
 
     if (IsSubFunc(func)) {
         if (!tex->HasImageInfoAt(target, level)) {
             ErrorInvalidOperation("%s: no texture image previously defined for target %s at level %d",
-                                  info, NameFrom(target), level);
+                                  info, WebGLContext::EnumName(target), level);
             return false;
         }
 
         const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(target, level);
         if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset,
                                      width, height, depth,
                                      imageInfo.Width(), imageInfo.Height(), 0,
                                      func))
@@ -1399,24 +1337,24 @@ WebGLContext::ValidateTexImage(GLuint di
     }
 
     /* Additional checks for depth textures */
     if (target != LOCAL_GL_TEXTURE_2D &&
         (format == LOCAL_GL_DEPTH_COMPONENT ||
          format == LOCAL_GL_DEPTH_STENCIL))
     {
         ErrorInvalidOperation("%s: with format of %s target must be TEXTURE_2D",
-                              info, NameFrom(format));
+                              info, WebGLContext::EnumName(format));
         return false;
     }
 
     /* Additional checks for compressed textures */
     if (!IsAllowedFromSource(format, func)) {
         ErrorInvalidOperation("%s: Invalid format %s for this operation",
-                              info, NameFrom(format));
+                              info, WebGLContext::EnumName(format));
         return false;
     }
 
     /* Parameters are OK */
     return true;
 }
 
 bool
--- a/content/canvas/src/WebGLElementArrayCache.cpp
+++ b/content/canvas/src/WebGLElementArrayCache.cpp
@@ -599,9 +599,21 @@ WebGLElementArrayCache::SizeOfIncludingT
   size_t uint32TreeSize = mUint32Tree ? mUint32Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
   return aMallocSizeOf(this) +
           mBytes.SizeOfExcludingThis(aMallocSizeOf) +
           uint8TreeSize +
           uint16TreeSize +
           uint32TreeSize;
 }
 
+bool
+WebGLElementArrayCache::BeenUsedWithMultipleTypes() const
+{
+  // C++ Standard ($4.7)
+  // "If the source type is bool, the value false is converted to zero and
+  //  the value true is converted to one."
+  const int num_types_used = (mUint8Tree  != nullptr) +
+                             (mUint16Tree != nullptr) +
+                             (mUint32Tree != nullptr);
+  return num_types_used > 1;
+}
+
 } // end namespace mozilla
--- a/content/canvas/src/WebGLElementArrayCache.h
+++ b/content/canvas/src/WebGLElementArrayCache.h
@@ -42,16 +42,18 @@ public:
   T Element(size_t i) const { return Elements<T>()[i]; }
 
   WebGLElementArrayCache();
 
   ~WebGLElementArrayCache();
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
+  bool BeenUsedWithMultipleTypes() const;
+
 private:
 
   template<typename T>
   bool Validate(uint32_t maxAllowed, size_t first, size_t count,
                 uint32_t* out_upperBound);
 
   template<typename T>
   const T* Elements() const { return reinterpret_cast<const T*>(mBytes.Elements()); }
--- a/content/html/content/src/HTMLLinkElement.cpp
+++ b/content/html/content/src/HTMLLinkElement.cpp
@@ -284,17 +284,17 @@ HTMLLinkElement::UpdateImport()
   }
 
   nsCOMPtr<nsIURI> uri = GetHrefURI();
   if (!uri) {
     mImportLoader = nullptr;
     return;
   }
 
-  if (!Preferences::GetBool("dom.webcomponents.enabled")) {
+  if (!nsStyleLinkElement::IsImportEnabled()) {
     // For now imports are hidden behind a pref...
     return;
   }
 
   nsRefPtr<ImportManager> manager = doc->ImportManager();
   MOZ_ASSERT(manager, "ImportManager should be created lazily when needed");
 
   {
--- a/content/html/content/src/HTMLTemplateElement.cpp
+++ b/content/html/content/src/HTMLTemplateElement.cpp
@@ -6,51 +6,33 @@
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/HTMLTemplateElementBinding.h"
 
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIAtom.h"
 #include "nsRuleData.h"
 
-using namespace mozilla::dom;
-
-nsGenericHTMLElement*
-NS_NewHTMLTemplateElement(already_AddRefed<nsINodeInfo>&& aNodeInfo,
-                          FromParser aFromParser)
-{
-  HTMLTemplateElement* it = new HTMLTemplateElement(aNodeInfo);
-  nsresult rv = it->Init();
-  if (NS_FAILED(rv)) {
-    delete it;
-    return nullptr;
-  }
-
-  return it;
-}
+NS_IMPL_NS_NEW_HTML_ELEMENT(Template)
 
 namespace mozilla {
 namespace dom {
 
 HTMLTemplateElement::HTMLTemplateElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
   SetHasWeirdParserInsertionMode();
-}
 
-nsresult
-HTMLTemplateElement::Init()
-{
   nsIDocument* contentsOwner = OwnerDoc()->GetTemplateContentsOwner();
-  NS_ENSURE_TRUE(contentsOwner, NS_ERROR_UNEXPECTED);
+  if (!contentsOwner) {
+    MOZ_CRASH("There should always be a template contents owner.");
+  }
 
   mContent = contentsOwner->CreateDocumentFragment();
   mContent->SetHost(this);
-
-  return NS_OK;
 }
 
 HTMLTemplateElement::~HTMLTemplateElement()
 {
   if (mContent) {
     mContent->SetHost(nullptr);
   }
 }
@@ -72,17 +54,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // QueryInterface implementation for HTMLTemplateElement
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTemplateElement)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(HTMLTemplateElement)
+NS_IMPL_ELEMENT_CLONE(HTMLTemplateElement)
 
 JSObject*
 HTMLTemplateElement::WrapNode(JSContext *aCx)
 {
   return HTMLTemplateElementBinding::Wrap(aCx, this);
 }
 
 } // namespace dom
--- a/content/html/content/src/HTMLTemplateElement.h
+++ b/content/html/content/src/HTMLTemplateElement.h
@@ -23,18 +23,16 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTemplateElement,
                                            nsGenericHTMLElement)
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
-  nsresult Init();
-
   DocumentFragment* Content()
   {
     return mContent;
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE;
 
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -8,16 +8,17 @@
 #include "prlog.h"
 #include "prdtoa.h"
 #include "AudioStream.h"
 #include "VideoUtils.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Mutex.h"
 #include <algorithm>
 #include "mozilla/Preferences.h"
+#include "mozilla/Telemetry.h"
 #include "soundtouch/SoundTouch.h"
 #include "Latency.h"
 
 namespace mozilla {
 
 #ifdef LOG
 #undef LOG
 #endif
@@ -67,16 +68,26 @@ bool AudioStream::sCubebLatencyPrefSet;
     // audible.
     sCubebLatencyPrefSet = Preferences::HasUserValue(aPref);
     uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_MS);
     StaticMutexAutoLock lock(sMutex);
     sCubebLatency = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000);
   }
 }
 
+/*static*/ bool AudioStream::GetFirstStream()
+{
+  static bool sFirstStream = true;
+
+  StaticMutexAutoLock lock(sMutex);
+  bool result = sFirstStream;
+  sFirstStream = false;
+  return result;
+}
+
 /*static*/ double AudioStream::GetVolumeScale()
 {
   StaticMutexAutoLock lock(sMutex);
   return sVolumeScale;
 }
 
 /*static*/ cubeb* AudioStream::GetCubebContext()
 {
@@ -379,16 +390,19 @@ WriteDumpFile(FILE* aDumpFile, AudioStre
 
 // NOTE: this must not block a LowLatency stream for any significant amount
 // of time, or it will block the entirety of MSG
 nsresult
 AudioStream::Init(int32_t aNumChannels, int32_t aRate,
                   const dom::AudioChannel aAudioChannel,
                   LatencyRequest aLatencyRequest)
 {
+  mStartTime = TimeStamp::Now();
+  mIsFirst = GetFirstStream();
+
   if (!GetCubebContext() || aNumChannels < 0 || aRate < 0) {
     return NS_ERROR_FAILURE;
   }
 
   PR_LOG(gAudioStreamLog, PR_LOG_DEBUG,
     ("%s  channels: %d, rate: %d for %p", __FUNCTION__, aNumChannels, aRate, this));
   mInRate = mOutRate = aRate;
   mChannels = aNumChannels;
@@ -489,16 +503,24 @@ AudioStream::OpenCubeb(cubeb_stream_para
     } else {
       MonitorAutoLock mon(mMonitor);
       mState = ERRORED;
       LOG(("AudioStream::OpenCubeb() %p failed to init cubeb", this));
       return NS_ERROR_FAILURE;
     }
   }
 
+  if (!mStartTime.IsNull()) {
+		TimeDuration timeDelta = TimeStamp::Now() - mStartTime;
+    LOG(("AudioStream creation time %sfirst: %u ms", mIsFirst ? "" : "not ",
+         (uint32_t) timeDelta.ToMilliseconds()));
+		Telemetry::Accumulate(mIsFirst ? Telemetry::AUDIOSTREAM_FIRST_OPEN_MS :
+                          Telemetry::AUDIOSTREAM_LATER_OPEN_MS, timeDelta.ToMilliseconds());
+  }
+
   return NS_OK;
 }
 
 void
 AudioStream::CheckForStart()
 {
   if (mState == INITIALIZED) {
     // Start the stream right away when low latency has been requested. This means
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -302,16 +302,17 @@ private:
   // So we can call it asynchronously from AudioInitTask
   nsresult OpenCubeb(cubeb_stream_params &aParams,
                      LatencyRequest aLatencyRequest);
 
   void CheckForStart();
 
   static void PrefChanged(const char* aPref, void* aClosure);
   static double GetVolumeScale();
+  static bool GetFirstStream();
   static cubeb* GetCubebContext();
   static cubeb* GetCubebContextUnlocked();
   static uint32_t GetCubebLatency();
   static bool CubebLatencyPrefSet();
 
   static long DataCallback_S(cubeb_stream*, void* aThis, void* aBuffer, long aFrames)
   {
     return static_cast<AudioStream*>(aThis)->DataCallback(aBuffer, aFrames);
@@ -418,16 +419,17 @@ private:
                  // completion.
     DRAINED,     // StateCallback has indicated that the drain is complete.
     ERRORED,     // Stream disabled due to an internal error.
     SHUTDOWN     // Shutdown has been called
   };
 
   StreamState mState;
   bool mNeedsStart; // needed in case Start() is called before cubeb is open
+  bool mIsFirst;
 
   // This mutex protects the static members below.
   static StaticMutex sMutex;
   static cubeb* sCubebContext;
 
   // Prefered samplerate, in Hz (characteristic of the
   // hardware/mixer/platform/API used).
   static uint32_t sPreferredSampleRate;
--- a/content/media/mediasource/test/mochitest.ini
+++ b/content/media/mediasource/test/mochitest.ini
@@ -1,6 +1,6 @@
 [DEFAULT]
 skip-if = e10s
 support-files = seek.webm seek.webm^headers^
 
 [test_MediaSource.html]
-skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined) b2g-debug( ReferenceError: MediaSource is not defined) b2g-desktop( ReferenceError: MediaSource is not defined)
+skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
--- a/content/media/omx/OMXCodecProxy.cpp
+++ b/content/media/omx/OMXCodecProxy.cpp
@@ -75,17 +75,17 @@ OMXCodecProxy::~OMXCodecProxy()
         // this value come from stagefrigh's AwesomePlayer.
         usleep(1000);
     }
   }
   // Complete all pending Binder ipc transactions
   IPCThreadState::self()->flushCommands();
 
   if (mManagerService.get() && mClient.get()) {
-    mManagerService->cancelClient(mClient);
+    mManagerService->cancelClient(mClient, IMediaResourceManagerService::HW_VIDEO_DECODER);
   }
 
   mSource.clear();
   free(mComponentName);
   mComponentName = nullptr;
 }
 
 MediaResourceManagerClient::State OMXCodecProxy::getState()
@@ -121,17 +121,17 @@ void OMXCodecProxy::requestResource()
   mClient = new MediaResourceManagerClient(listener);
 
   mManagerService = mClient->getMediaResourceManagerService();
   if (!mManagerService.get()) {
     mClient = nullptr;
     return;
   }
 
-  mManagerService->requestMediaResource(mClient, MediaResourceManagerClient::HW_VIDEO_DECODER);
+  mManagerService->requestMediaResource(mClient, IMediaResourceManagerService::HW_VIDEO_DECODER, true /* will wait */);
 }
 
 bool OMXCodecProxy::IsWaitingResources()
 {
   Mutex::Autolock autoLock(mLock);
   return mState == MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE;
 }
 
--- a/content/media/omx/OMXCodecWrapper.cpp
+++ b/content/media/omx/OMXCodecWrapper.cpp
@@ -29,16 +29,42 @@ using namespace mozilla::layers;
 
 #define CODEC_ERROR(args...)                                                   \
   do {                                                                         \
     __android_log_print(ANDROID_LOG_ERROR, "OMXCodecWrapper", ##args);         \
   } while (0)
 
 namespace android {
 
+bool
+OMXCodecReservation::ReserveOMXCodec()
+{
+  if (!mManagerService.get()) {
+    sp<MediaResourceManagerClient::EventListener> listener = this;
+    mClient = new MediaResourceManagerClient(listener);
+
+    mManagerService = mClient->getMediaResourceManagerService();
+    if (!mManagerService.get()) {
+      mClient = nullptr;
+      return true; // not really in use, but not usable
+    }
+  }
+  return (mManagerService->requestMediaResource(mClient, mType, false) == OK); // don't wait
+}
+
+void
+OMXCodecReservation::ReleaseOMXCodec()
+{
+  if (!mManagerService.get() || !mClient.get()) {
+    return;
+  }
+
+  mManagerService->cancelClient(mClient, mType);
+}
+
 OMXAudioEncoder*
 OMXCodecWrapper::CreateAACEncoder()
 {
   nsAutoPtr<OMXAudioEncoder> aac(new OMXAudioEncoder(CodecType::AAC_ENC));
   // Return the object only when media codec is valid.
   NS_ENSURE_TRUE(aac->IsValid(), nullptr);
 
   return aac.forget();
--- a/content/media/omx/OMXCodecWrapper.h
+++ b/content/media/omx/OMXCodecWrapper.h
@@ -2,28 +2,64 @@
 /* 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 OMXCodecWrapper_h_
 #define OMXCodecWrapper_h_
 
 #include <gui/Surface.h>
+#include <utils/RefBase.h>
 #include <stagefright/foundation/ABuffer.h>
 #include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaCodec.h>
 
 #include "AudioSegment.h"
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 
+#include "IMediaResourceManagerService.h"
+#include "MediaResourceManagerClient.h"
+
 #include <speex/speex_resampler.h>
 
 namespace android {
 
+// Wrapper class for managing HW codec reservations
+class OMXCodecReservation : public MediaResourceManagerClient::EventListener
+{
+public:
+  OMXCodecReservation(bool aEncoder)
+  {
+    mType = aEncoder ? IMediaResourceManagerService::HW_VIDEO_ENCODER :
+            IMediaResourceManagerService::HW_VIDEO_DECODER;
+  }
+
+  virtual ~OMXCodecReservation()
+  {
+    ReleaseOMXCodec();
+  }
+
+  /** Reserve the Encode or Decode resource for this instance */
+  virtual bool ReserveOMXCodec();
+
+  /** Release the Encode or Decode resource for this instance */
+  virtual void ReleaseOMXCodec();
+
+  // MediaResourceManagerClient::EventListener
+  virtual void statusChanged(int event) {}
+
+private:
+  IMediaResourceManagerService::ResourceType mType;
+
+  sp<MediaResourceManagerClient> mClient;
+  sp<IMediaResourceManagerService> mManagerService;
+};
+
+
 class OMXAudioEncoder;
 class OMXVideoEncoder;
 
 /**
  * This class (and its subclasses) wraps the video and audio codec from
  * MediaCodec API in libstagefright. Currently only AVC/H.264 video encoder and
  * AAC audio encoder are supported.
  *
--- a/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.cpp
+++ b/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.cpp
@@ -29,30 +29,33 @@ enum {
 class BpMediaResourceManagerService : public BpInterface<IMediaResourceManagerService>
 {
 public:
     BpMediaResourceManagerService(const sp<IBinder>& impl)
         : BpInterface<IMediaResourceManagerService>(impl)
     {
     }
 
-    virtual void requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType)
+    virtual status_t requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType, bool willWait)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaResourceManagerService::getInterfaceDescriptor());
         data.writeStrongBinder(client->asBinder());
         data.writeInt32(resourceType);
+        data.writeInt32(willWait ? 1 : 0);
         remote()->transact(REQUEST_MEDIA_RESOURCE, data, &reply);
+        return reply.readInt32();
     }
 
-    virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client)
+    virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client, int resourceType)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaResourceManagerService::getInterfaceDescriptor());
         data.writeStrongBinder(client->asBinder());
+        data.writeInt32(resourceType);
         remote()->transact(DEREGISTER_CLIENT, data, &reply);
         return reply.readInt32();
     }
 };
 
 IMPLEMENT_META_INTERFACE(MediaResourceManagerService, "android.media.IMediaResourceManagerService");
 
 // ----------------------------------------------------------------------
@@ -61,24 +64,27 @@ status_t BnMediaResourceManagerService::
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
 
         case REQUEST_MEDIA_RESOURCE: {
             CHECK_INTERFACE(IMediaResourceManagerService, data, reply);
             sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(data.readStrongBinder());
             int resourceType = data.readInt32();
-            requestMediaResource(client, resourceType);
+            bool willWait = (data.readInt32() == 1);
+            status_t result = requestMediaResource(client, resourceType, willWait);
+            reply->writeInt32(result);
             return NO_ERROR;
         } break;
         case DEREGISTER_CLIENT: {
             CHECK_INTERFACE(IMediaResourceManagerService, data, reply);
             sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(data.readStrongBinder());
-            cancelClient(client);
-            reply->writeInt32(NO_ERROR);
+            int resourceType = data.readInt32();
+            status_t result = cancelClient(client, resourceType);
+            reply->writeInt32(result);
             return NO_ERROR;
         } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
 }
 
 // ----------------------------------------------------------------------------
--- a/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.h
+++ b/content/media/omx/mediaresourcemanager/IMediaResourceManagerService.h
@@ -17,20 +17,46 @@ namespace android {
 
 // ----------------------------------------------------------------------------
 
 class IMediaResourceManagerService : public IInterface
 {
 public:
     DECLARE_META_INTERFACE(MediaResourceManagerService);
 
+    // Enumeration for the resource types
+    enum ResourceType {
+      HW_VIDEO_DECODER = 0,
+      HW_AUDIO_DECODER,  // Not supported currently.
+      HW_VIDEO_ENCODER,
+      HW_CAMERA,          // Not supported currently.
+      NUM_OF_RESOURCE_TYPES,
+      INVALID_RESOURCE_TYPE = -1
+    };
+
+    enum ErrorCode {
+        RESOURCE_NOT_AVAILABLE = -EAGAIN
+    };
+
     // Request a media resource for IMediaResourceManagerClient.
-    virtual void requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType) = 0;
+    // client is the binder that service will notify (through
+    // IMediaResourceManagerClient::statusChanged()) when request status changed.
+    // resourceType is type of resource that client would like to request.
+    // willWait indicates that, when the resource is not currently available
+    // (i.e., already in use by another client), if the client wants to wait. If
+    // true, client will be put into a (FIFO) waiting list and be notified when
+    // resource is available.
+    // For unsupported types, this function returns BAD_TYPE. For supported
+    // types, it always returns OK when willWait is true; otherwise it will
+    // return true when resouce is available, or RESOURCE_NOT_AVAILABLE when
+    // resouce is in use.
+    virtual status_t requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType, bool willWait) = 0;
     // Cancel a media resource request and a resource allocated to IMediaResourceManagerClient.
-    virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client) = 0;
+    // Client must call this function after it's done with the media resource requested.
+    virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client, int resourceType) = 0;
 };
 
 
 // ----------------------------------------------------------------------------
 
 class BnMediaResourceManagerService : public BnInterface<IMediaResourceManagerService>
 {
 public:
--- a/content/media/omx/mediaresourcemanager/MediaResourceManagerClient.h
+++ b/content/media/omx/mediaresourcemanager/MediaResourceManagerClient.h
@@ -17,22 +17,16 @@ class MediaResourceManagerClient: public
 {
 public:
   // Enumeration for the valid decoding states
   enum State {
     CLIENT_STATE_WAIT_FOR_RESOURCE,
     CLIENT_STATE_RESOURCE_ASSIGNED,
     CLIENT_STATE_SHUTDOWN
   };
-  // Enumeration for the resource types
-  enum ResourceType {
-    HW_VIDEO_DECODER,
-    HW_AUDIO_DECODER,
-    HW_CAMERA
-  };
 
   struct EventListener : public virtual RefBase {
     // Notifies a change of media resource request status.
     virtual void statusChanged(int event) = 0;
   };
 
   MediaResourceManagerClient(const wp<EventListener>& listener);
 
--- a/content/media/omx/mediaresourcemanager/MediaResourceManagerService.cpp
+++ b/content/media/omx/mediaresourcemanager/MediaResourceManagerService.cpp
@@ -2,33 +2,37 @@
 /* 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/. */
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaResourceManagerService"
 
+#include <mozilla/Assertions.h>
+
 #include <binder/IServiceManager.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <utils/Log.h>
 
 #include "MediaResourceManagerClient.h"
 #include "MediaResourceManagerService.h"
 
 namespace android {
 
+const char* MediaResourceManagerService::kMsgKeyResourceType = "res-type";
+
 /* static */
 void MediaResourceManagerService::instantiate() {
   defaultServiceManager()->addService(
-            String16("media.resource_manager"), new MediaResourceManagerService());
+            String16("media.resource_manager"),
+            new MediaResourceManagerService());
 }
 
 MediaResourceManagerService::MediaResourceManagerService()
-  : mVideoDecoderCount(VIDEO_DECODER_COUNT)
 {
   mLooper = new ALooper;
   mLooper->setName("MediaResourceManagerService");
 
   mReflector = new AHandlerReflector<MediaResourceManagerService>(this);
   // Register AMessage handler to ALooper.
   mLooper->registerHandler(mReflector);
   // Start ALooper thread.
@@ -44,104 +48,324 @@ MediaResourceManagerService::~MediaResou
 }
 
 void MediaResourceManagerService::binderDied(const wp<IBinder>& who)
 {
   if (who != NULL) {
     Mutex::Autolock autoLock(mLock);
     sp<IBinder> binder = who.promote();
     if (binder != NULL) {
-      cancelClientLocked(binder);
+      mResources.forgetClient(binder);
     }
   }
 }
 
-void MediaResourceManagerService::requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType)
+status_t MediaResourceManagerService::requestMediaResource(const sp<IMediaResourceManagerClient>& client,
+                                                           int resourceType, bool willWait)
 {
-  if (resourceType != MediaResourceManagerClient::HW_VIDEO_DECODER) {
-    // Support only HW_VIDEO_DECODER
-    return;
-  }
-
-  {
-    Mutex::Autolock autoLock(mLock);
-    sp<IBinder> binder = client->asBinder();
-    mVideoCodecRequestQueue.push_back(binder);
-    binder->linkToDeath(this);
+  ResourceType type = static_cast<ResourceType>(resourceType);
+  // Support only HW_VIDEO_DECODER and HW_VIDEO_ENCODER.
+  switch (type) {
+    case HW_VIDEO_DECODER:
+    case HW_VIDEO_ENCODER:
+      break;
+    default:
+      // Type not supported.
+      return BAD_TYPE;
   }
 
-  sp<AMessage> notify =
-            new AMessage(kNotifyRequest, mReflector->id());
-  // Post AMessage to MediaResourceManagerService via ALooper.
-  notify->post();
-}
+  Mutex::Autolock autoLock(mLock);
 
-status_t MediaResourceManagerService::cancelClient(const sp<IMediaResourceManagerClient>& client)
-{
-  {
-    Mutex::Autolock autoLock(mLock);
-    sp<IBinder> binder = client->asBinder();
-    cancelClientLocked(binder);
+  // Must know if it will be granted or not - if there are enough unfufilled requests to
+  // use up the resource, fail.  Otherwise we know that enqueuing under lock will succeed.
+  if (!willWait &&
+      (mResources.findAvailableResource(type, mResources.countRequests(type) + 1) ==
+       NAME_NOT_FOUND)) {
+    return RESOURCE_NOT_AVAILABLE;
   }
+  // We could early-return here without enqueuing IF we can do the rest of
+  // the allocation safely here.  However, enqueuing ensures there's only
+  // one copy of that code, and that any callbacks are made from the same
+  // context.
 
-  sp<AMessage> notify =
-            new AMessage(kNotifyRequest, mReflector->id());
+  sp<IBinder> binder = client->asBinder();
+  mResources.enqueueRequest(binder, type);
+  binder->linkToDeath(this);
+
+  sp<AMessage> notify = new AMessage(kNotifyRequest, mReflector->id());
+  notify->setInt32(kMsgKeyResourceType, resourceType);
   // Post AMessage to MediaResourceManagerService via ALooper.
   notify->post();
 
+  return OK;
+}
+
+status_t MediaResourceManagerService::cancelClient(const sp<IMediaResourceManagerClient>& client,
+                                                   int resourceType)
+{
+  Mutex::Autolock autoLock(mLock);
+
+  sp<IBinder> binder = client->asBinder();
+  cancelClientLocked(binder, static_cast<ResourceType>(resourceType));
+
+  sp<AMessage> notify = new AMessage(kNotifyRequest, mReflector->id());
+  notify->setInt32(kMsgKeyResourceType, resourceType);
+  // Next!
+  // Note: since we held the lock while releasing and then posting, if there is
+  // a queue, no willWait==false entries can jump into the queue thinking they'll
+  // get the resource.
+  notify->post();
+
   return NO_ERROR;
 }
 
+// Extract resource type from message.
+static int32_t getResourceType(const sp<AMessage>& message)
+{
+  int32_t resourceType = MediaResourceManagerService::INVALID_RESOURCE_TYPE;
+  return message->findInt32(MediaResourceManagerService::kMsgKeyResourceType, &resourceType) ?
+          resourceType : MediaResourceManagerService::INVALID_RESOURCE_TYPE;
+}
+
 // Called on ALooper thread.
 void MediaResourceManagerService::onMessageReceived(const sp<AMessage> &msg)
 {
   Mutex::Autolock autoLock(mLock);
+  ResourceType type = static_cast<ResourceType>(getResourceType(msg));
+
+  // Note: a message is sent both for "I added an entry to the queue"
+  // (which may succeed, typically if the queue is empty), and for "I gave
+  // up the resource", in which case it's "give to the next waiting client,
+  // or no one".
+
+  // Exit if no resource is available, but leave the client in the waiting
+  // list.
+  int found = mResources.findAvailableResource(type);
+  if (found == NAME_NOT_FOUND) {
+    return;
+  }
 
   // Exit if no request.
-  if (mVideoCodecRequestQueue.empty()) {
+  if (!mResources.hasRequest(type)) {
     return;
   }
 
-  // Check if resource is available
-  int found = -1;
-  for (int i=0 ; i<mVideoDecoderCount ; i++) {
-    if (!mVideoDecoderSlots[i].mClient.get()) {
+  const sp<IBinder>& req = mResources.nextRequest(type);
+  mResources.aquireResource(req, type, found);
+  // Notify resource assignment to the client.
+  sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(req);
+  client->statusChanged(MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED);
+  mResources.dequeueRequest(type);
+}
+
+void MediaResourceManagerService::cancelClientLocked(const sp<IBinder>& binder,
+                                                     ResourceType resourceType)
+{
+  mResources.forgetClient(binder, resourceType);
+  binder->unlinkToDeath(this);
+}
+
+MediaResourceManagerService::ResourceTable::ResourceTable()
+{
+  // Populate types of resources.
+  for (int type = 0; type < NUM_OF_RESOURCE_TYPES; type++) {
+    ssize_t index = mMap.add(static_cast<ResourceType>(type), Resources());
+    Resources& resources = mMap.editValueAt(index);
+    int available;
+    switch (type) {
+      case HW_VIDEO_DECODER:
+        available = VIDEO_DECODER_COUNT;
+        break;
+      case HW_VIDEO_ENCODER:
+        available = VIDEO_ENCODER_COUNT;
+        break;
+      default:
+        available = 0;
+        break;
+    }
+    resources.mSlots.insertAt(0, available);
+  }
+}
+
+MediaResourceManagerService::ResourceTable::~ResourceTable() {
+  // Remove resouces.
+  mMap.clear();
+}
+
+bool MediaResourceManagerService::ResourceTable::supportsType(ResourceType type)
+{
+  return mMap.indexOfKey(type) != NAME_NOT_FOUND;
+}
+
+ssize_t MediaResourceManagerService::ResourceTable::findAvailableResource(ResourceType type,
+                                                                          size_t numberNeeded)
+{
+  MOZ_ASSERT(numberNeeded > 0);
+  ssize_t found = mMap.indexOfKey(type);
+  if (found == NAME_NOT_FOUND) {
+    // Unsupported type.
+    return found;
+  }
+  const Slots& slots = mMap.valueAt(found).mSlots;
+
+  found = NAME_NOT_FOUND;
+  for (size_t i = 0; i < slots.size(); i++) {
+    if (slots[i].mClient != nullptr) {
+      // Already in use.
+      continue;
+    }
+    if (--numberNeeded == 0) {
       found = i;
+      break;
     }
   }
 
-  // Exit if no resource is available.
-  if (found == -1) {
-    return;
+  return found;
+}
+
+bool MediaResourceManagerService::ResourceTable::isOwnedByClient(const sp<IBinder>& client,
+                                                                 ResourceType type,
+                                                                 size_t index)
+{
+  ResourceSlot* slot = resourceOfTypeAt(type, index);
+  return slot && slot->mClient == client;
+}
+
+status_t MediaResourceManagerService::ResourceTable::aquireResource(const sp<IBinder>& client,
+                                                                    ResourceType type,
+                                                                    size_t index)
+{
+  ResourceSlot* slot = resourceOfTypeAt(type, index);
+  // Resouce should not be in use.
+  MOZ_ASSERT(slot && slot->mClient == nullptr);
+  if (!slot) {
+    return NAME_NOT_FOUND;
+  } else if (slot->mClient != nullptr) {
+    // Resource already in use by other client.
+    return PERMISSION_DENIED;
+  }
+
+  slot->mClient = client;
+
+
+  return OK;
+}
+
+MediaResourceManagerService::ResourceSlot*
+MediaResourceManagerService::ResourceTable::resourceOfTypeAt(ResourceType type,
+                                                             size_t index)
+{
+  ssize_t found = mMap.indexOfKey(type);
+  if (found == NAME_NOT_FOUND) {
+    // Unsupported type.
+    return nullptr;
+  }
+
+  Slots& slots = mMap.editValueAt(found).mSlots;
+  MOZ_ASSERT(index < slots.size());
+  if (index >= slots.size()) {
+    // Index out of range.
+    return nullptr;
+  }
+  return &(slots.editItemAt(index));
+}
+
+bool MediaResourceManagerService::ResourceTable::hasRequest(ResourceType type)
+{
+  ssize_t found = mMap.indexOfKey(type);
+  if (found == NAME_NOT_FOUND) {
+    // Unsupported type.
+    return nullptr;
   }
 
-  // Assign resource to IMediaResourceManagerClient
-  Fifo::iterator front(mVideoCodecRequestQueue.begin());
-  mVideoDecoderSlots[found].mClient = *front;
-  mVideoCodecRequestQueue.erase(front);
-  // Notify resource assignment to the client.
-  sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(mVideoDecoderSlots[found].mClient);
-  client->statusChanged(MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED);
+  const Fifo& queue = mMap.valueAt(found).mRequestQueue;
+  return !queue.empty();
+}
+
+uint32_t MediaResourceManagerService::ResourceTable::countRequests(ResourceType type)
+{
+  ssize_t found = mMap.indexOfKey(type);
+  if (found == NAME_NOT_FOUND) {
+    // Unsupported type.
+    return 0;
+  }
+
+  const Fifo& queue = mMap.valueAt(found).mRequestQueue;
+  return queue.size();
+}
+
+const sp<IBinder>& MediaResourceManagerService::ResourceTable::nextRequest(ResourceType type)
+{
+  ssize_t found = mMap.indexOfKey(type);
+  if (found == NAME_NOT_FOUND) {
+    // Unsupported type.
+    return nullptr;
+  }
+
+  const Fifo& queue = mMap.valueAt(found).mRequestQueue;
+  return *(queue.begin());
 }
 
-void MediaResourceManagerService::cancelClientLocked(const sp<IBinder>& binder)
+status_t MediaResourceManagerService::ResourceTable::enqueueRequest(const sp<IBinder>& client,
+                                                                    ResourceType type)
+{
+  ssize_t found = mMap.indexOfKey(type);
+  if (found == NAME_NOT_FOUND) {
+    // Unsupported type.
+    return found;
+  }
+
+  mMap.editValueAt(found).mRequestQueue.push_back(client);
+  return OK;
+}
+
+status_t MediaResourceManagerService::ResourceTable::dequeueRequest(ResourceType type)
 {
-  // Clear the request from request queue.
-  Fifo::iterator it(mVideoCodecRequestQueue.begin());
-  while (it != mVideoCodecRequestQueue.end()) {
-    if ((*it).get() == binder.get()) {
-      mVideoCodecRequestQueue.erase(it);
+  ssize_t found = mMap.indexOfKey(type);
+  if (found == NAME_NOT_FOUND) {
+    // Unsupported type.
+    return found;
+  }
+
+  Fifo& queue = mMap.editValueAt(found).mRequestQueue;
+  queue.erase(queue.begin());
+  return OK;
+}
+
+status_t MediaResourceManagerService::ResourceTable::forgetClient(const sp<IBinder>& client)
+{
+  // Traverse all resources.
+  for (int i = 0; i < mMap.size(); i++) {
+    forgetClient(client, mMap.keyAt(i));
+  }
+  return OK;
+}
+
+status_t MediaResourceManagerService::ResourceTable::forgetClient(const sp<IBinder>& client, ResourceType type)
+{
+  MOZ_ASSERT(supportsType(type));
+
+  Resources& resources = mMap.editValueFor(type);
+
+  // Remove pending requests for given client.
+  Fifo& queue = resources.mRequestQueue;
+  Fifo::iterator it(queue.begin());
+  while (it != queue.end()) {
+    if ((*it).get() == client.get()) {
+      queue.erase(it);
       break;
     }
     it++;
   }
 
-  // Clear the client from the resource
-  for (int i=0 ; i<mVideoDecoderCount ; i++) {
-    if (mVideoDecoderSlots[i].mClient.get() == binder.get()) {
-      mVideoDecoderSlots[i].mClient = NULL;
+  // Revoke ownership for given client.
+  Slots& slots = resources.mSlots;
+  for (int i = 0; i < slots.size(); i++) {
+    ResourceSlot& slot = slots.editItemAt(i);
+    if (client.get() == slot.mClient.get()) {
+      slot.mClient = nullptr;
     }
   }
-  binder->unlinkToDeath(this);
+
+  return OK;
 }
 
 }; // namespace android
-
--- a/content/media/omx/mediaresourcemanager/MediaResourceManagerService.h
+++ b/content/media/omx/mediaresourcemanager/MediaResourceManagerService.h
@@ -5,91 +5,131 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ANDROID_MEDIARESOURCEMANAGERSERVICE_H
 #define ANDROID_MEDIARESOURCEMANAGERSERVICE_H
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AHandlerReflector.h>
 #include <media/stagefright/foundation/ALooper.h>
+#include <utils/KeyedVector.h>
 #include <utils/List.h>
 #include <utils/RefBase.h>
+#include <utils/Vector.h>
 
 #include "IMediaResourceManagerClient.h"
 #include "IMediaResourceManagerService.h"
 
 namespace android {
 
 /**
  * Manage permissions of using media resources(hw decoder, hw encoder, camera)
- * XXX Current implementaion support only one hw video decoder.
+ * XXX Current implementation supports only one hw video codec.
  *     Need to extend to support multiple instance and other resources.
  */
 class MediaResourceManagerService: public BnMediaResourceManagerService,
                                    public IBinder::DeathRecipient
 {
 public:
-  // The maximum number of hardware decoders available.
-  enum { VIDEO_DECODER_COUNT = 1 };
+  // The maximum number of hardware resoureces available.
+  enum
+  {
+    VIDEO_DECODER_COUNT = 1,
+    VIDEO_ENCODER_COUNT = 1
+  };
 
-  enum {
-    kNotifyRequest = 'noti'
+  enum
+  {
+    kNotifyRequest = 'noti',
   };
 
+  static const char* kMsgKeyResourceType;
+
   // Instantiate MediaResourceManagerService and register to service manager.
   // If service manager is not present, wait until service manager becomes present.
   static  void instantiate();
 
   // DeathRecipient
   virtual void binderDied(const wp<IBinder>& who);
 
   // derived from IMediaResourceManagerService
-  virtual void requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType);
-  virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client);
+  virtual status_t requestMediaResource(const sp<IMediaResourceManagerClient>& client,
+                                        int resourceType, bool willWait);
+  virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client,
+                                int resourceType);
 
   // Receive a message from AHandlerReflector.
   // Called on ALooper thread.
   void onMessageReceived(const sp<AMessage> &msg);
 
 protected:
   MediaResourceManagerService();
   virtual ~MediaResourceManagerService();
 
-protected:
+private:
   // Represent a media resouce.
   // Hold a IMediaResourceManagerClient that got a media resource as IBinder.
-  struct ResourceSlot {
-    ResourceSlot ()
-      {
-      }
-      sp<IBinder> mClient;
-    };
+  struct ResourceSlot
+  {
+    sp<IBinder> mClient;
+  };
+  typedef Vector<ResourceSlot> Slots;
 
-  void cancelClientLocked(const sp<IBinder>& binder);
+  typedef List<sp<IBinder> > Fifo;
+  struct Resources
+  {
+    // Queue of media resource requests. Hold IMediaResourceManagerClient that
+    // requesting a media resource as IBinder.
+    Fifo mRequestQueue;
+    // All resources that can be requested. Hold |ResourceSlot|s that track
+    // their usage.
+    Slots mSlots;
+  };
 
-  // mVideoDecoderSlots is the array of slots that represent a media resource.
-  ResourceSlot mVideoDecoderSlots[VIDEO_DECODER_COUNT];
-  // The maximum number of hardware decoders available on the device.
-  int mVideoDecoderCount;
+  typedef KeyedVector<ResourceType, Resources> ResourcesMap;
+  // Manages requests from clients and availability of resources.
+  class ResourceTable
+  {
+    ResourceTable();
+    ~ResourceTable();
+    // Resource operations.
+    bool supportsType(ResourceType type);
+    ssize_t findAvailableResource(ResourceType type, size_t number_needed = 1);
+    bool isOwnedByClient(const sp<IBinder>& client, ResourceType type, size_t index);
+    status_t aquireResource(const sp<IBinder>& client, ResourceType type, size_t index);
+    ResourceSlot* resourceOfTypeAt(ResourceType type, size_t index);
+    // Request operations.
+    bool hasRequest(ResourceType type);
+    uint32_t countRequests(ResourceType type);
+    const sp<IBinder>& nextRequest(ResourceType type);
+    status_t enqueueRequest(const sp<IBinder>& client, ResourceType type);
+    status_t dequeueRequest(ResourceType type);
+    status_t forgetClient(const sp<IBinder>& client, ResourceType type);
+    status_t forgetClient(const sp<IBinder>& client);
 
-  // The lock protects mVideoDecoderSlots and mVideoCodecRequestQueue called
-  //  from multiple threads.
-  Mutex mLock;
-  typedef List<sp<IBinder> > Fifo;
-  // Queue of media resource requests.
-  // Hold IMediaResourceManagerClient that requesting a media resource as IBinder.
-  Fifo mVideoCodecRequestQueue;
+    friend class MediaResourceManagerService;
+
+    // A map for all types of supported resources.
+    ResourcesMap mMap;
+  };
+
+  void cancelClientLocked(const sp<IBinder>& binder, ResourceType resourceType);
 
   // ALooper is a message loop used in stagefright.
   // It creates a thread for messages and handles messages in the thread.
   // ALooper is a clone of Looper in android Java.
   // http://developer.android.com/reference/android/os/Looper.html
   sp<ALooper> mLooper;
   // deliver a message to a wrapped object(OmxDecoder).
   // AHandlerReflector is similar to Handler in android Java.
   // http://developer.android.com/reference/android/os/Handler.html
   sp<AHandlerReflector<MediaResourceManagerService> > mReflector;
 
+  // The lock protects manager operations called from multiple threads.
+  Mutex mLock;
+
+  // Keeps all the records.
+  ResourceTable mResources;
 };
 
 }; // namespace android
 
 #endif // ANDROID_MEDIARESOURCEMANAGERSERVICE_H
--- a/content/media/omx/mediaresourcemanager/moz.build
+++ b/content/media/omx/mediaresourcemanager/moz.build
@@ -1,14 +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 += [
+    'IMediaResourceManagerClient.h',
+    'IMediaResourceManagerDeathNotifier.h',
+    'IMediaResourceManagerService.h',
+    'MediaResourceManagerClient.h',
+    'MediaResourceManagerService.h',
+]
+
 SOURCES += [
     'IMediaResourceManagerClient.cpp',
     'IMediaResourceManagerDeathNotifier.cpp',
     'IMediaResourceManagerService.cpp',
     'MediaResourceManagerClient.cpp',
     'MediaResourceManagerService.cpp',
 ]
 
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -17,18 +17,17 @@
 # throws an error (and does not cause a crash or hang), just add it to
 # gErrorTests in manifest.js.
 
 # To test for a specific bug in handling a specific resource type, make the
 # test first check canPlayType for the type, and if it's not supported, just
 # do ok(true, "Type not supported") and stop the test.
 
 [DEFAULT]
-#bug 918299
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug,b2g-desktop(bug 918299)
 support-files =
   320x240.ogv
   320x240.ogv^headers^
   448636.ogv
   448636.ogv^headers^
   VID_0001.ogg
   VID_0001.ogg^headers^
   allowed.sjs
@@ -295,208 +294,186 @@ support-files =
   wavedata_s16.wav^headers^
   wavedata_u8.wav
   wavedata_u8.wav^headers^
 
 [test_access_control.html]
 [test_aspectratio_mp4.html]
 [test_audio1.html]
 [test_audio2.html]
+[test_audioDocumentTitle.html]
+skip-if = true # bug 475110
 [test_autoplay.html]
+[test_autoplay_contentEditable.html]
+skip-if = buildapp == 'b2g' # bug 899074 - timeouts
+[test_buffered.html]
+skip-if = toolkit == 'android' || os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682, b2g(assertion failures)
 [test_bug448534.html]
-skip-if = buildapp == 'b2g' # b2g(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests) b2g-debug(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests) b2g-desktop(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests)
+skip-if = buildapp == 'b2g' # b2g(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests)
 [test_bug463162.xhtml]
+[test_bug465498.html]
+skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682
+[test_bug493187.html]
+skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 707777
 [test_bug495145.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
 [test_bug495300.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_bug654550.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
 [test_bug686942.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
-# [test_bug726904.html] # disabled - See bug 754860
+[test_bug726904.html]
+skip-if = true # bug 754860
 [test_bug874897.html]
 [test_bug883173.html]
+[test_bug895091.html]
 [test_bug895305.html]
-[test_bug895091.html]
 [test_bug919265.html]
 [test_bug957847.html]
+[test_can_play_type.html]
+[test_can_play_type_mpeg.html]
+skip-if = buildapp == 'b2g' # b2g(7 failures out of 27)
+[test_can_play_type_no_ogg.html]
+[test_can_play_type_ogg.html]
+skip-if = buildapp == 'b2g' || e10s
 [test_chaining.html]
-skip-if = buildapp == 'b2g' # b2g(timed out) b2g-debug(timed out) b2g-desktop(timed out)
+skip-if = buildapp == 'b2g' # timeouts
 [test_clone_media_element.html]
+[test_closing_connections.html]
+[test_constants.html]
 [test_contentDuration1.html]
 [test_contentDuration2.html]
 [test_contentDuration3.html]
 [test_contentDuration4.html]
 [test_contentDuration5.html]
 [test_contentDuration6.html]
 [test_contentDuration7.html]
-[test_can_play_type.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
-[test_can_play_type_mpeg.html]
-skip-if = buildapp == 'b2g' # b2g(7 failures out of 27) b2g-debug(7 failures out of 27) b2g-desktop(7 failures out of 27)
-[test_can_play_type_ogg.html]
-skip-if = buildapp == 'b2g' || e10s
-[test_can_play_type_no_ogg.html]
-[test_closing_connections.html]
-[test_constants.html]
 [test_controls.html]
 [test_currentTime.html]
 [test_decode_error.html]
+[test_decoder_disable.html]
 [test_defaultMuted.html]
 [test_delay_load.html]
-skip-if = buildapp == 'b2g' # b2g(6 failures) b2g-debug(6 failures) b2g-desktop(6 failures)
+skip-if = buildapp == 'b2g' # b2g(6 failures)
+[test_error_in_video_document.html]
+skip-if = true # bug 608634
 [test_error_on_404.html]
-skip-if = buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
 [test_fastSeek.html]
 [test_info_leak.html]
-skip-if = buildapp == 'b2g' # b2g(2 failures) b2g-debug(2 failures) b2g-desktop(2 failures)
+skip-if = buildapp == 'b2g' # b2g(2 failures)
 [test_invalid_reject.html]
 [test_load.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Timed out after gizmo.mp4) b2g-desktop(Timed out after gizmo.mp4)
 [test_load_candidates.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
 [test_load_same_resource.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_load_source.html]
 [test_loop.html]
+[test_media_selection.html]
+skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 897843, b2g(timed out)
+[test_media_sniffer.html]
+[test_mediarecorder_avoid_recursion.html]
+[test_mediarecorder_creation.html]
+[test_mediarecorder_creation_fail.html]
+[test_mediarecorder_getencodeddata.html]
+[test_mediarecorder_record_4ch_audiocontext.html]
+skip-if = (toolkit == 'gonk' && !debug)
+[test_mediarecorder_record_audiocontext.html]
+[test_mediarecorder_record_audiocontext_mlk.html]
+[test_mediarecorder_record_gum_video_timeslice.html]
+skip-if = buildapp == 'b2g' || (toolkit == 'android') # mimetype check, bug 969289
+[test_mediarecorder_record_immediate_stop.html]
+[test_mediarecorder_record_no_timeslice.html]
+[test_mediarecorder_record_nosrc.html]
+[test_mediarecorder_record_session.html]
+[test_mediarecorder_record_startstopstart.html]
+[test_mediarecorder_record_stopms.html]
+[test_mediarecorder_record_timeslice.html]
+[test_mediarecorder_reload_crash.html]
+[test_mediarecorder_unsupported_src.html]
 [test_metadata.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
-[test_no_load_event.html]
+[test_mixed_principals.html]
+skip-if = true # bug 567954 and 574586
+[test_mozHasAudio.html]
 [test_networkState.html]
 [test_new_audio.html]
+[test_no_load_event.html]
 [test_paused.html]
 [test_paused_after_ended.html]
 [test_play_events.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Last event should be canplaythrough for gizmo.mp4 - got playing, expected canplaythrough) b2g-desktop(Last event should be canplaythrough for gizmo.mp4 - got playing, expected canplaythrough)
 [test_play_events_2.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Last event should be canplaythrough for gizmo.mp4 - got playing, expected canplaythrough) b2g-desktop(Last event should be canplaythrough for gizmo.mp4 - got playing, expected canplaythrough)
-[test_playback_errors.html]
-[test_seekable1.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
-[test_preload_actions.html]
-[test_preload_attribute.html]
-[test_progress.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(bug 901716 - timeouts) b2g-desktop(bug 901716 - timeouts)
-[test_reactivate.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out in small-shot.mp3) b2g-desktop(timed out in small-shot.mp3)
-[test_readyState.html]
-[test_referer.html]
-[test_reset_events_async.html]
-[test_replay_metadata.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
-[test_seek2.html]
-[test_seek_out_of_range.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
-[test_seekable2.html]
-[test_seekable3.html]
-skip-if = buildapp == 'b2g' # b2g(timed out) b2g-debug(timed out) b2g-desktop(timed out)
-[test_source.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
-[test_source_write.html]
-[test_source_null.html]
-[test_standalone.html]
-[test_volume.html]
-[test_video_to_canvas.html]
-[test_mediarecorder_creation.html]
-[test_mediarecorder_creation_fail.html]
-[test_mediarecorder_avoid_recursion.html]
-[test_mediarecorder_record_timeslice.html]
-[test_mediarecorder_record_audiocontext.html]
-[test_mediarecorder_record_audiocontext_mlk.html]
-[test_mediarecorder_record_4ch_audiocontext.html]
-skip-if = (toolkit == 'gonk' && !debug)
-[test_mediarecorder_record_stopms.html]
-[test_mediarecorder_record_nosrc.html]
-[test_mozHasAudio.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
-[test_source_media.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
-[test_autoplay_contentEditable.html]
-skip-if = buildapp == 'b2g' # b2g(bug 899074 - timeouts) b2g-debug(bug 899074 - timeouts) b2g-desktop(bug 899074 - timeouts)
-[test_decoder_disable.html]
-[test_mediarecorder_record_no_timeslice.html]
-[test_mediarecorder_reload_crash.html]
-[test_mediarecorder_record_immediate_stop.html]
-[test_mediarecorder_record_session.html]
-[test_mediarecorder_record_startstopstart.html]
-[test_mediarecorder_getencodeddata.html]
-[test_mediarecorder_unsupported_src.html]
-[test_mediarecorder_record_gum_video_timeslice.html]
-skip-if = buildapp == 'b2g' || (toolkit == 'android') # mimetype check, bug 969289
-[test_playback.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' # Disabled on Android & B2G due to bug 668973
-[test_seekLies.html]
-[test_media_sniffer.html]
-[test_streams_srcObject.html]
-[test_reset_src.html]
-[test_streams_autoplay.html]
-[test_streams_element_capture.html]
-[test_streams_element_capture_reset.html]
-skip-if = buildapp == 'b2g' # b2g(bug 901102) b2g-debug(bug 901102) b2g-desktop(bug 901102)
-[test_streams_element_capture_createObjectURL.html]
-[test_streams_element_capture_playback.html]
-[test_streams_gc.html]
-skip-if = buildapp == 'b2g' # b2g(Value being assigned to HTMLMediaElement.currentTime is not a finite floating-point value) b2g-debug(Value being assigned to HTMLMediaElement.currentTime is not a finite floating-point value) b2g-desktop(Value being assigned to HTMLMediaElement.currentTime is not a finite floating-point value)
-[test_streams_tracks.html]
-[test_trackelementevent.html]
-[test_texttrack.html]
-[test_texttrackcue.html]
-[test_trackevent.html]
-[test_texttrackregion.html]
-[test_texttracklist.html]
-[test_timeupdate_small_files.html]
-[test_unseekable.html]
-skip-if = buildapp == 'b2g'
-[test_VideoPlaybackQuality.html]
-[test_VideoPlaybackQuality_disabled.html]
-[test_webvtt_disabled.html]
-
-# [test_audioDocumentTitle.html] # disabled - See bug 475110
-# [test_error_in_video_document.html] # disabled - See bug 608634
-# [test_mixed_principals.html] # disabled - See bug 567954 and 574586
-# [test_playback_rate_playpause.html] # disabled - See bug 897108
-# [test_played.html] # disabled - See bug 751539
-# [test_preload_suspend.html] # disabled - See bug 493692
-# [test_resume.html] # disabled - No bug :-(
-# [test_videoDocumentTitle.html] # disabled - See bug 492821
-
-# [test_playback_rate.html] # disabled - See bug 921622
-# Disabled since it causes random memory corruption, bug 921622, so
-# the best-case scenario is that it results in random crashes while it
-# runs, like bug 918417, bug 920827, bug 923996, bug 928225, bug 929521
-# bug 930982, bug 932193. Worst-case but quite likely, it causes random
-# crashes and failures in other tests which run after it. Don't even think
-# about reenabling it on any platform unless you *know* that you have fixed
-# that. Then don't think about reenabling it on Windows until you know that
-# you have fixed the timeouts of bug 832768, bug 814533, bug 840742
-
 [test_play_twice.html]
 # Seamonkey: Bug 598252, B2G: Bug 982100, Android: Bug 758476, bug 981086
 skip-if = appname == "seamonkey" || toolkit == 'gonk' || toolkit == 'android'
-
-[test_buffered.html]
-skip-if = toolkit == 'android' || os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682, b2g(assertion failures)
-[test_bug465498.html]
-skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682
-[test_bug493187.html]
-skip-if = os == "win" || (buildapp=='b2g'&&debug) || (toolkit == 'gonk' && !debug) # See bug 707777, #b2g-emulator-debug - process crash
-[test_media_selection.html]
-skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 897843, b2g(timed out)
+[test_playback.html]
+skip-if = buildapp == 'b2g' || toolkit == 'android' # Disabled on Android & B2G due to bug 668973
+[test_playback_errors.html]
+[test_playback_rate.html]
+# Win: Bug 814533, B2G & Android Debug: Bug 1020538
+skip-if = os == 'win' || buildapp == 'b2g' || (toolkit == 'android' && debug)
+[test_playback_rate_playpause.html]
+skip-if = true # bug 897108
+[test_played.html]
+skip-if = true # bug 751539
+[test_preload_actions.html]
+[test_preload_attribute.html]
+[test_preload_suspend.html]
+skip-if = true # bug 493692
+[test_progress.html]
+[test_reactivate.html]
+[test_readyState.html]
+[test_referer.html]
+[test_replay_metadata.html]
+[test_reset_events_async.html]
+[test_reset_src.html]
+[test_resume.html]
+skip-if = true # disabled - No bug :-(
+[test_seek_out_of_range.html]
 [test_seek.html]
 skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) # See bug 832678, 795271, and 857424 # android(bug 845162) androidx86(bug 845162)
+[test_seek2.html]
+[test_seekable1.html]
+[test_seekable2.html]
+[test_seekable3.html]
+skip-if = buildapp == 'b2g' # timeouts
+[test_seekLies.html]
+[test_source.html]
+[test_source_media.html]
+[test_source_null.html]
+[test_source_write.html]
+[test_standalone.html]
+[test_streams_autoplay.html]
+[test_streams_element_capture.html]
+[test_streams_element_capture_createObjectURL.html]
+[test_streams_element_capture_playback.html]
+[test_streams_element_capture_reset.html]
+skip-if = buildapp == 'b2g' # bug 901102
+[test_streams_gc.html]
+skip-if = buildapp == 'b2g' # Value being assigned to HTMLMediaElement.currentTime is not a finite floating-point value
+[test_streams_srcObject.html]
+[test_streams_tracks.html]
+[test_texttrack.html]
+[test_texttrackcue.html]
+[test_texttracklist.html]
+[test_texttrackregion.html]
+[test_timeupdate_small_files.html]
+[test_trackelementevent.html]
+[test_trackevent.html]
+[test_unseekable.html]
+skip-if = buildapp == 'b2g'
+[test_video_to_canvas.html]
+[test_videoDocumentTitle.html]
+skip-if = true # bug 492821
+[test_VideoPlaybackQuality.html]
+[test_VideoPlaybackQuality_disabled.html]
+[test_volume.html]
+[test_webvtt_disabled.html]
+
 
 # The tests below contain backend-specific tests. Write backend independent
 # tests rather than adding to this list.
-
 [test_can_play_type_webm.html]
 run-if = webm
 [test_can_play_type_no_webm.html]
 skip-if = webm
-
 [test_can_play_type_wave.html]
 run-if = wave
 [test_can_play_type_no_wave.html]
 skip-if = wave
 [test_fragment_noplay.html]
 run-if = wave
 [test_fragment_play.html]
 run-if = wave
--- a/content/media/test/test_playback_rate.html
+++ b/content/media/test/test_playback_rate.html
@@ -5,22 +5,29 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type='application/javascript;version=1.8'>
 
-SimpleTest.expectAssertions(0, 2);
-
+// In varying quantities:
+// ASSERTION: Should be on state machine or decode thread.:
+//            'OnStateMachineThread() || OnDecodeThread()',
+//            file MediaDecoderStateMachine.cpp, line 559
+// ASSERTION: Clock should go forwards if the playback rate is > 0.:
+//            'mCurrentFrameTime <= clock_time || mPlaybackRate <= 0',
+//            file MediaDecoderStateMachine.cpp, line 2379
+// This test is currently disabled on Android debug for wildly-varying numbers of the above.
+SimpleTest.expectAssertions(5, 9);
 if (navigator.platform.startsWith("Win")) {
-  SimpleTest.expectAssertions(0, 1);
+  SimpleTest.expectAssertions(4, 5);
 } else if (navigator.platform.startsWith("Mac")) {
-  SimpleTest.expectAssertions(0, 2);
+  SimpleTest.expectAssertions(5, 7);
 }
 
 let manager = new MediaTestManager;
 
 function rangeCheck(lhs, rhs, threshold) {
   var diff = Math.abs(lhs - rhs);
   if (diff < threshold) {
     return true;
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -222,17 +222,16 @@ static bool UseAudioChannelService()
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationNode, AudioNode,
                                    mAudioChannelAgent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
   NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(AudioDestinationNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(AudioDestinationNode, AudioNode)
 
 AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
                                            bool aIsOffline,
                                            AudioChannel aChannel,
--- a/content/media/webaudio/AudioDestinationNode.h
+++ b/content/media/webaudio/AudioDestinationNode.h
@@ -7,27 +7,25 @@
 #ifndef AudioDestinationNode_h_
 #define AudioDestinationNode_h_
 
 #include "mozilla/dom/AudioChannelBinding.h"
 #include "AudioNode.h"
 #include "nsIDOMEventListener.h"
 #include "nsIAudioChannelAgent.h"
 #include "AudioChannelCommon.h"
-#include "nsWeakReference.h"
 
 namespace mozilla {
 namespace dom {
 
 class AudioContext;
 
 class AudioDestinationNode : public AudioNode
                            , public nsIDOMEventListener
                            , public nsIAudioChannelAgentCallback
-                           , public nsSupportsWeakReference
                            , public MainThreadMediaStreamListener
 {
 public:
   // This node type knows what MediaStreamGraph to use based on
   // whether it's in offline mode.
   AudioDestinationNode(AudioContext* aContext,
                        bool aIsOffline,
                        AudioChannel aChannel = AudioChannel::Normal,
--- a/content/media/webaudio/AudioNode.cpp
+++ b/content/media/webaudio/AudioNode.cpp
@@ -4,21 +4,24 @@
  * 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 "AudioNode.h"
 #include "mozilla/ErrorResult.h"
 #include "AudioNodeStream.h"
 #include "AudioNodeEngine.h"
 #include "mozilla/dom/AudioParam.h"
+#include "mozilla/Services.h"
+#include "nsIObserverService.h"
 
 namespace mozilla {
 namespace dom {
 
 static const uint32_t INVALID_PORT = 0xffffffff;
+static uint32_t gId = 0;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(AudioNode)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioNode, DOMEventTargetHelper)
   tmp->DisconnectFromGraph();
   if (tmp->mContext) {
     tmp->mContext->UpdateNodeCount(-1);
   }
@@ -44,39 +47,48 @@ AudioNode::Release()
     DisconnectFromGraph();
   }
   nsrefcnt r = DOMEventTargetHelper::Release();
   NS_LOG_RELEASE(this, r, "AudioNode");
   return r;
 }
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioNode)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 AudioNode::AudioNode(AudioContext* aContext,
                      uint32_t aChannelCount,
                      ChannelCountMode aChannelCountMode,
                      ChannelInterpretation aChannelInterpretation)
   : DOMEventTargetHelper(aContext->GetParentObject())
   , mContext(aContext)
   , mChannelCount(aChannelCount)
   , mChannelCountMode(aChannelCountMode)
   , mChannelInterpretation(aChannelInterpretation)
+  , mId(gId++)
+#ifdef DEBUG
+  , mDemiseNotified(false)
+#endif
 {
   MOZ_ASSERT(aContext);
   DOMEventTargetHelper::BindToOwner(aContext->GetParentObject());
   SetIsDOMBinding();
   aContext->UpdateNodeCount(1);
 }
 
 AudioNode::~AudioNode()
 {
   MOZ_ASSERT(mInputNodes.IsEmpty());
   MOZ_ASSERT(mOutputNodes.IsEmpty());
   MOZ_ASSERT(mOutputParams.IsEmpty());
+#ifdef DEBUG
+  MOZ_ASSERT(mDemiseNotified,
+             "The webaudio-node-demise notification must have been sent");
+#endif
   if (mContext) {
     mContext->UpdateNodeCount(-1);
   }
 }
 
 size_t
 AudioNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
@@ -380,16 +392,26 @@ AudioNode::DestroyMediaStream()
       MutexAutoLock lock(ns->Engine()->NodeMutex());
       MOZ_ASSERT(ns, "How come we don't have a stream here?");
       MOZ_ASSERT(ns->Engine()->Node() == this, "Invalid node reference");
       ns->Engine()->ClearNode();
     }
 
     mStream->Destroy();
     mStream = nullptr;
+
+    nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+    if (obs) {
+      nsAutoString id;
+      id.AppendPrintf("%u", mId);
+      obs->NotifyObservers(nullptr, "webaudio-node-demise", id.get());
+    }
+#ifdef DEBUG
+    mDemiseNotified = true;
+#endif
   }
 }
 
 void
 AudioNode::RemoveOutputParam(AudioParam* aParam)
 {
   mOutputParams.RemoveElement(aParam);
 }
--- a/content/media/webaudio/AudioNode.h
+++ b/content/media/webaudio/AudioNode.h
@@ -11,16 +11,17 @@
 #include "mozilla/dom/AudioNodeBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "AudioContext.h"
 #include "MediaStreamGraph.h"
 #include "WebAudioUtils.h"
 #include "mozilla/MemoryReporting.h"
+#include "nsWeakReference.h"
 
 namespace mozilla {
 
 namespace dom {
 
 class AudioContext;
 class AudioBufferSourceNode;
 class AudioParam;
@@ -77,17 +78,18 @@ private:
  * finished do so strictly *after* producing and returning their last block.
  * In this way, an engine that receives non-null input knows that the input
  * comes from nodes that are still alive and will keep their output nodes
  * alive for at least as long as it takes to process messages from the graph
  * thread.  i.e. the engine receiving non-null input knows that its node is
  * still alive, and will still be alive when it receives a message from the
  * engine.
  */
-class AudioNode : public DOMEventTargetHelper
+class AudioNode : public DOMEventTargetHelper,
+                  public nsSupportsWeakReference
 {
 protected:
   // You can only use refcounting to delete this object
   virtual ~AudioNode();
 
 public:
   AudioNode(AudioContext* aContext,
             uint32_t aChannelCount,
@@ -128,16 +130,18 @@ public:
   virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv);
 
   // The following two virtual methods must be implemented by each node type
   // to provide their number of input and output ports. These numbers are
   // constant for the lifetime of the node. Both default to 1.
   virtual uint16_t NumberOfInputs() const { return 1; }
   virtual uint16_t NumberOfOutputs() const { return 1; }
 
+  uint32_t Id() const { return mId; }
+
   uint32_t ChannelCount() const { return mChannelCount; }
   virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv)
   {
     if (aChannelCount == 0 ||
         aChannelCount > WebAudioUtils::MaxChannelCount) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return;
     }
@@ -261,14 +265,20 @@ private:
   // AudioParam::mInputNodes of the mOutputParams entry. We won't necessarily be
   // able to identify the exact matching entry, since mOutputParams doesn't
   // include the port identifiers and the same node could be connected on
   // multiple ports.
   nsTArray<nsRefPtr<AudioParam> > mOutputParams;
   uint32_t mChannelCount;
   ChannelCountMode mChannelCountMode;
   ChannelInterpretation mChannelInterpretation;
+  const uint32_t mId;
+#ifdef DEBUG
+  // In debug builds, check to make sure that the node demise notification has
+  // been properly sent before the node is destroyed.
+  bool mDemiseNotified;
+#endif
 };
 
 }
 }
 
 #endif
--- a/content/media/webaudio/MediaStreamAudioSourceNode.cpp
+++ b/content/media/webaudio/MediaStreamAudioSourceNode.cpp
@@ -37,17 +37,17 @@ MediaStreamAudioSourceNode::MediaStreamA
               ChannelInterpretation::Speakers),
     mInputStream(aMediaStream)
 {
   AudioNodeEngine* engine = new MediaStreamAudioSourceNodeEngine(this);
   mStream = aContext->Graph()->CreateAudioNodeExternalInputStream(engine);
   ProcessedMediaStream* outputStream = static_cast<ProcessedMediaStream*>(mStream.get());
   mInputPort = outputStream->AllocateInputPort(aMediaStream->GetStream(),
                                                MediaInputPort::FLAG_BLOCK_INPUT);
-  mInputStream->AddConsumerToKeepAlive(this);
+  mInputStream->AddConsumerToKeepAlive(static_cast<nsIDOMEventTarget*>(this));
 
   PrincipalChanged(mInputStream); // trigger enabling/disabling of the connector
   mInputStream->AddPrincipalChangeObserver(this);
 }
 
 MediaStreamAudioSourceNode::~MediaStreamAudioSourceNode()
 {
   if (mInputStream) {
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/chrome.ini
@@ -0,0 +1,3 @@
+[DEFAULT]
+
+[test_AudioNodeDevtoolsAPI.html]
--- a/content/media/webaudio/test/mochitest.ini
+++ b/content/media/webaudio/test/mochitest.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) #b2g-debug(bug 916135) b2g-desktop(bug 916135)
+skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) #b2g-debug,b2g-desktop(bug 916135)
 support-files =
   audio-expected.wav
   audio-mono-expected-2.wav
   audio-mono-expected.wav
   audio-quad.wav
   audio.ogv
   audioBufferSourceNodeNeutered_worker.js
   invalid.txt
@@ -18,40 +18,40 @@ support-files =
   ting-48k-1ch.ogg
   ting-48k-2ch.ogg
   ting-44.1k-1ch.wav
   ting-44.1k-2ch.wav
   ting-48k-1ch.wav
   ting-48k-2ch.wav
   webaudio.js
 
+[test_analyserNode.html]
 [test_AudioBuffer.html]
-[test_AudioContext.html]
-[test_AudioListener.html]
-[test_OfflineAudioContext.html]
-[test_analyserNode.html]
 [test_audioBufferSourceNode.html]
 [test_audioBufferSourceNodeEnded.html]
 [test_audioBufferSourceNodeLazyLoopParam.html]
 [test_audioBufferSourceNodeLoop.html]
 [test_audioBufferSourceNodeLoopStartEnd.html]
 [test_audioBufferSourceNodeLoopStartEndSame.html]
 [test_audioBufferSourceNodeNeutered.html]
 [test_audioBufferSourceNodeNoStart.html]
 [test_audioBufferSourceNodeNullBuffer.html]
 [test_audioBufferSourceNodeOffset.html]
 skip-if = (toolkit == 'gonk' && !debug) #bug 906752
+[test_AudioContext.html]
+[test_audioDestinationNode.html]
+[test_AudioListener.html]
 [test_audioParamExponentialRamp.html]
+[test_audioParamGain.html]
 [test_audioParamLinearRamp.html]
 [test_audioParamSetCurveAtTime.html]
 [test_audioParamSetCurveAtTimeZeroDuration.html]
 [test_audioParamSetTargetAtTime.html]
 [test_audioParamSetValueAtTime.html]
 [test_audioParamTimelineDestinationOffset.html]
-[test_audioParamGain.html]
 [test_badConnect.html]
 [test_biquadFilterNode.html]
 [test_biquadFilterNodeWithGain.html]
 [test_bug808374.html]
 [test_bug827541.html]
 [test_bug839753.html]
 [test_bug845960.html]
 [test_bug856771.html]
@@ -67,19 +67,19 @@ skip-if = (toolkit == 'gonk' && !debug) 
 [test_bug956489.html]
 [test_bug964376.html]
 [test_bug972678.html]
 [test_channelMergerNode.html]
 [test_channelMergerNodeWithVolume.html]
 [test_channelSplitterNode.html]
 [test_channelSplitterNodeWithVolume.html]
 [test_convolverNode.html]
+[test_convolverNode_mono_mono.html]
 [test_convolverNodeChannelCount.html]
 [test_convolverNodeWithGain.html]
-[test_convolverNode_mono_mono.html]
 [test_currentTime.html]
 [test_decodeMultichannel.html]
 [test_delayNode.html]
 [test_delayNodeAtMax.html]
 [test_delayNodeChannelChanges.html]
 [test_delayNodeCycles.html]
 [test_delayNodeSmallMaxDelay.html]
 [test_delayNodeTailIncrease.html]
@@ -93,35 +93,35 @@ skip-if = (toolkit == 'gonk' && !debug) 
 [test_maxChannelCount.html]
 [test_mediaDecoding.html]
 [test_mediaElementAudioSourceNode.html]
 [test_mediaStreamAudioDestinationNode.html]
 [test_mediaStreamAudioSourceNode.html]
 [test_mediaStreamAudioSourceNodeCrossOrigin.html]
 [test_mediaStreamAudioSourceNodeResampling.html]
 [test_mixingRules.html]
+[test_mozaudiochannel.html]
+skip-if = (toolkit == 'gonk' && !debug)
 [test_nodeToParamConnection.html]
+[test_OfflineAudioContext.html]
 [test_offlineDestinationChannelCountLess.html]
 [test_offlineDestinationChannelCountMore.html]
 [test_oscillatorNode.html]
 [test_oscillatorNode2.html]
 [test_oscillatorNodeStart.html]
 [test_oscillatorTypeChange.html]
 [test_pannerNode.html]
+[test_pannerNode_equalPower.html]
 [test_pannerNodeAbove.html]
 [test_pannerNodeChannelCount.html]
 [test_pannerNodeHRTFSymmetry.html]
 [test_pannerNodeTail.html]
-[test_pannerNode_equalPower.html]
 [test_periodicWave.html]
 [test_scriptProcessorNode.html]
 [test_scriptProcessorNodeChannelCount.html]
 [test_scriptProcessorNodeZeroInputOutput.html]
 [test_scriptProcessorNodeNotConnected.html]
+[test_singleSourceDest.html]
 [test_stereoPanningWithGain.html]
-[test_singleSourceDest.html]
+[test_waveDecoder.html]
 [test_waveShaper.html]
 [test_waveShaperNoCurve.html]
 [test_waveShaperZeroLengthCurve.html]
-[test_audioDestinationNode.html]
-[test_mozaudiochannel.html]
-skip-if = (toolkit == 'gonk' && !debug)
-[test_waveDecoder.html]
--- a/content/media/webaudio/test/moz.build
+++ b/content/media/webaudio/test/moz.build
@@ -3,8 +3,12 @@
 # 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/.
 
 MOCHITEST_MANIFESTS += [
     'blink/mochitest.ini',
     'mochitest.ini',
 ]
+
+MOCHITEST_CHROME_MANIFESTS += [
+    'chrome.ini'
+]
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_AudioNodeDevtoolsAPI.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test the devtool AudioNode API</title>
+  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+  Components.utils.import('resource://gre/modules/Services.jsm');
+
+  SimpleTest.waitForExplicitFinish();
+
+  var ac = new AudioContext();
+  var ids;
+  var weak;
+  (function() {
+    var src1 = ac.createBufferSource();
+    var src2 = ac.createBufferSource();
+    ok(src2.id > src1.id, "The ID should be monotonic");
+    ok(src1.id > ac.destination.id, "The ID of the destination node should be the lowest");
+    ids = [src1.id, src2.id];
+    weak = Components.utils.getWeakReference(src1);
+    is(weak.get(), src1, "The node should support a weak reference");
+  })();
+  function observer(subject, topic, data) {
+    var id = parseInt(data);
+    var index = ids.indexOf(id);
+    if (index != -1) {
+      info("Dropping id " + id + " at index " + index);
+      ids.splice(index, 1);
+      if (ids.length == 0) {
+        SimpleTest.executeSoon(function() {
+          is(weak.get(), null, "The weak reference must be dropped now");
+          Services.obs.removeObserver(observer, "webaudio-node-demise");
+          SimpleTest.finish();
+        });
+      }
+    }
+  }
+  Services.obs.addObserver(observer, "webaudio-node-demise", false);
+
+  forceCC();
+  forceCC();
+
+  function forceCC() {
+    SpecialPowers.DOMWindowUtils.cycleCollect();
+    SpecialPowers.DOMWindowUtils.garbageCollect();
+    SpecialPowers.DOMWindowUtils.garbageCollect();
+  }
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/media/webspeech/recognition/test/mochitest.ini
+++ b/content/media/webspeech/recognition/test/mochitest.ini
@@ -5,15 +5,15 @@ support-files =
   hello.ogg^headers^
   silence.ogg
   silence.ogg^headers^
 
 [test_abort.html]
 [test_audio_capture_error.html]
 [test_call_start_from_end_handler.html]
 [test_nested_eventloop.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(showmodaldialog)
 [test_preference_enable.html]
 [test_recognition_service_error.html]
-skip-if = buildapp == 'b2g' # b2g(timed out) b2g-debug(timed out) b2g-desktop(timed out)
+skip-if = buildapp == 'b2g' # b2g(timed out)
 [test_success_without_recognition_service.html]
 [test_timeout.html]
 skip-if = os == "win"
--- a/content/media/webspeech/synth/test/mochitest.ini
+++ b/content/media/webspeech/synth/test/mochitest.ini
@@ -3,11 +3,11 @@ skip-if = e10s
 support-files =
   common.js
   file_setup.html
   file_speech_queue.html
   file_speech_simple.html
 
 [test_setup.html]
 [test_speech_queue.html]
-skip-if = buildapp == 'b2g' # b2g(Test timed out) b2g-debug(Test timed out) b2g-desktop(Test timed out)
+skip-if = buildapp == 'b2g' # b2g(Test timed out)
 [test_speech_simple.html]
-skip-if = buildapp == 'b2g' # b2g(Test timed out) b2g-debug(Test timed out) b2g-desktop(Test timed out)
+skip-if = buildapp == 'b2g' # b2g(Test timed out)
--- a/content/svg/document/src/SVGDocument.cpp
+++ b/content/svg/document/src/SVGDocument.cpp
@@ -61,16 +61,31 @@ SVGDocument::GetRootElement(ErrorResult&
   if (!root->IsSVG()) {
     aRv.Throw(NS_NOINTERFACE);
     return nullptr;
   }
   return static_cast<nsSVGElement*>(root);
 }
 
 nsresult
+SVGDocument::InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify)
+{
+  nsresult rv = XMLDocument::InsertChildAt(aKid, aIndex, aNotify);
+
+  if (NS_SUCCEEDED(rv) && aKid->IsElement() && !aKid->IsSVG()) {
+    // We can get here when well formed XML with a non-SVG root element is
+    // served with the SVG MIME type, for example. In that case we need to load
+    // the non-SVG UA sheets or else we can get bugs like bug 1016145.
+    EnsureNonSVGUserAgentStyleSheetsLoaded();
+  }
+
+  return rv;
+}
+
+nsresult
 SVGDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
                "Can't import this document into another document!");
 
   nsRefPtr<SVGDocument> clone = new SVGDocument();
   nsresult rv = CloneDocHelper(clone.get());
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/svg/document/src/SVGDocument.h
+++ b/content/svg/document/src/SVGDocument.h
@@ -23,16 +23,18 @@ class SVGDocument MOZ_FINAL : public XML
 public:
   SVGDocument()
     : XMLDocument("image/svg+xml")
     , mHasLoadedNonSVGUserAgentStyleSheets(false)
   {
     mType = eSVG;
   }
 
+  virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
+                                 bool aNotify) MOZ_OVERRIDE;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   // WebIDL API
   void GetDomain(nsAString& aDomain, ErrorResult& aRv);
   nsSVGElement* GetRootElement(ErrorResult& aRv);
 
   virtual SVGDocument* AsSVGDocument() MOZ_OVERRIDE {
     return this;
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -55,16 +55,17 @@
 #include "nsIHTMLDocument.h"
 #include "mozAutoDocUpdate.h"
 #include "nsMimeTypes.h"
 #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::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).
@@ -843,17 +844,27 @@ nsXMLContentSink::GetCurrentStackNode()
 
 nsresult
 nsXMLContentSink::PushContent(nsIContent *aContent)
 {
   NS_PRECONDITION(aContent, "Null content being pushed!");
   StackNode *sn = mContentStack.AppendElement();
   NS_ENSURE_TRUE(sn, NS_ERROR_OUT_OF_MEMORY);
 
-  sn->mContent = aContent;
+  nsIContent* contentToPush = aContent;
+
+  // When an XML parser would append a node to a template element, it
+  // must instead append it to the template element's template contents.
+  if (contentToPush->IsHTML(nsGkAtoms::_template)) {
+    HTMLTemplateElement* templateElement =
+      static_cast<HTMLTemplateElement*>(contentToPush);
+    contentToPush = templateElement->Content();
+  }
+
+  sn->mContent = contentToPush;
   sn->mNumFlushed = 0;
   return NS_OK;
 }
 
 void
 nsXMLContentSink::PopContent()
 {
   int32_t count = mContentStack.Length();
@@ -1071,18 +1082,23 @@ nsXMLContentSink::HandleEndElement(const
   NS_ASSERTION(content, "failed to pop content");
 #ifdef DEBUG
   // Check that we're closing the right thing
   nsCOMPtr<nsIAtom> debugNameSpacePrefix, debugTagAtom;
   int32_t debugNameSpaceID;
   nsContentUtils::SplitExpatName(aName, getter_AddRefs(debugNameSpacePrefix),
                                  getter_AddRefs(debugTagAtom),
                                  &debugNameSpaceID);
-  NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID),
-               "Wrong element being closed");
+  // Check if we are closing a template element because template
+  // elements do not get pushed on the stack, the template
+  // element content is pushed instead.
+  bool isTemplateElement = debugTagAtom == nsGkAtoms::_template &&
+                           debugNameSpaceID == kNameSpaceID_XHTML;
+  NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID) ||
+               isTemplateElement, "Wrong element being closed");
 #endif  
 
   result = CloseElement(content);
 
   if (mCurrentHead == content) {
     mCurrentHead = nullptr;
   }
   
--- a/docshell/shistory/src/nsSHistory.cpp
+++ b/docshell/shistory/src/nsSHistory.cpp
@@ -14,17 +14,16 @@
 // Interfaces Needed
 #include "nsILayoutHistoryState.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsISHContainer.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIURI.h"
 #include "nsIContentViewer.h"
-#include "nsICacheService.h"
 #include "nsIObserverService.h"
 #include "prclist.h"
 #include "mozilla/Services.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
 #include "nsDocShell.h"
 #include "mozilla/Attributes.h"
 #include "nsISHEntry.h"
@@ -185,17 +184,17 @@ NS_IMPL_ISUPPORTS(nsSHistoryObserver, ns
 
 NS_IMETHODIMP
 nsSHistoryObserver::Observe(nsISupports *aSubject, const char *aTopic,
                             const char16_t *aData)
 {
   if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
     nsSHistory::UpdatePrefs();
     nsSHistory::GloballyEvictContentViewers();
-  } else if (!strcmp(aTopic, NS_CACHESERVICE_EMPTYCACHE_TOPIC_ID) ||
+  } else if (!strcmp(aTopic, "cacheservice:empty-cache") ||
              !strcmp(aTopic, "memory-pressure")) {
     nsSHistory::GloballyEvictAllContentViewers();
   }
 
   return NS_OK;
 }
 
 namespace {
@@ -365,17 +364,17 @@ nsSHistory::Startup()
     Preferences::AddStrongObservers(gObserver, kObservedPrefs);
 
     nsCOMPtr<nsIObserverService> obsSvc =
       mozilla::services::GetObserverService();
     if (obsSvc) {
       // Observe empty-cache notifications so tahat clearing the disk/memory
       // cache will also evict all content viewers.
       obsSvc->AddObserver(gObserver,
-                          NS_CACHESERVICE_EMPTYCACHE_TOPIC_ID, false);
+                          "cacheservice:empty-cache", false);
 
       // Same for memory-pressure notifications
       obsSvc->AddObserver(gObserver, "memory-pressure", false);
     }
   }
 
   // Initialize the global list of all SHistory objects
   PR_INIT_CLIST(&gSHistoryList);
@@ -386,17 +385,17 @@ nsSHistory::Startup()
 void
 nsSHistory::Shutdown()
 {
   if (gObserver) {
     Preferences::RemoveObservers(gObserver, kObservedPrefs);
     nsCOMPtr<nsIObserverService> obsSvc =
       mozilla::services::GetObserverService();
     if (obsSvc) {
-      obsSvc->RemoveObserver(gObserver, NS_CACHESERVICE_EMPTYCACHE_TOPIC_ID);
+      obsSvc->RemoveObserver(gObserver, "cacheservice:empty-cache");
       obsSvc->RemoveObserver(gObserver, "memory-pressure");
     }
     NS_RELEASE(gObserver);
   }
 }
 
 /* Add an entry to the History list at mIndex and 
  * increment the index to point to the new entry
--- a/dom/archivereader/ArchiveRequest.cpp
+++ b/dom/archivereader/ArchiveRequest.cpp
@@ -149,19 +149,23 @@ ArchiveRequest::ReaderReady(nsTArray<nsC
     case GetFilenames:
       rv = GetFilenamesResult(cx, result.address(), aFileList);
       break;
 
     case GetFile:
       rv = GetFileResult(cx, &result, aFileList);
       break;
 
-      case GetFiles:
-        rv = GetFilesResult(cx, &result, aFileList);
-        break;
+    case GetFiles:
+      rv = GetFilesResult(cx, &result, aFileList);
+      break;
+
+    default:
+      rv = NS_ERROR_UNEXPECTED;
+      break;
   }
 
   if (NS_FAILED(rv)) {
     NS_WARNING("Get*Result failed!");
   }
 
   if (NS_SUCCEEDED(rv)) {
     FireSuccess(result);
--- a/dom/base/MessageChannel.cpp
+++ b/dom/base/MessageChannel.cpp
@@ -1,14 +1,15 @@
 /* -*- 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 "MessageChannel.h"
+
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/MessageChannelBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
 
 namespace mozilla {
 namespace dom {
@@ -23,26 +24,48 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END
 
 namespace {
   bool gPrefInitialized = false;
   bool gPrefEnabled = false;
 
 }
 
-
 /* static */ bool
-MessageChannel::PrefEnabled()
+MessageChannel::Enabled(JSContext* aCx, JSObject* aObj)
 {
   if (!gPrefInitialized) {
     Preferences::AddBoolVarCache(&gPrefEnabled, "dom.messageChannel.enabled");
     gPrefInitialized = true;
   }
 
-  return gPrefEnabled;
+  // Enabled by pref
+  if (gPrefEnabled) {
+    return true;
+  }
+
+  // Chrome callers are allowed.
+  if (nsContentUtils::ThreadsafeIsCallerChrome()) {
+    return true;
+  }
+
+  nsCOMPtr<nsIPrincipal> principal = nsContentUtils::SubjectPrincipal();
+  MOZ_ASSERT(principal);
+
+  nsCOMPtr<nsIURI> uri;
+  if (NS_FAILED(principal->GetURI(getter_AddRefs(uri))) || !uri) {
+    return false;
+  }
+
+  bool isResource = false;
+  if (NS_FAILED(uri->SchemeIs("resource", &isResource))) {
+    return false;
+  }
+
+  return isResource;
 }
 
 MessageChannel::MessageChannel(nsPIDOMWindow* aWindow)
   : mWindow(aWindow)
 {
   MOZ_COUNT_CTOR(MessageChannel);
   SetIsDOMBinding();
 
--- a/dom/base/MessageChannel.h
+++ b/dom/base/MessageChannel.h
@@ -23,17 +23,17 @@ class MessagePort;
 
 class MessageChannel MOZ_FINAL : public nsISupports
                                , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel)
 
-  static bool PrefEnabled();
+  static bool Enabled(JSContext* aCx, JSObject* aGlobal);
 
 public:
   MessageChannel(nsPIDOMWindow* aWindow);
 
   ~MessageChannel();
 
   nsPIDOMWindow*
   GetParentObject() const
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1492,17 +1492,17 @@ Navigator::GetFeature(const nsAString& a
   nsRefPtr<Promise> p = new Promise(go);
 
 #if defined(XP_LINUX)
   if (aName.EqualsLiteral("hardware.memory")) {
     // with seccomp enabled, fopen() should be in a non-sandboxed process
     if (XRE_GetProcessType() == GeckoProcessType_Default) {
       uint32_t memLevel = mozilla::hal::GetTotalSystemMemoryLevel();
       if (memLevel == 0) {
-        p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
+        p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
         return p.forget();
       }
       p->MaybeResolve((int)memLevel);
     } else {
       mozilla::dom::ContentChild* cc =
         mozilla::dom::ContentChild::GetSingleton();
       nsRefPtr<Promise> ipcRef(p);
       cc->SendGetSystemMemory(reinterpret_cast<uint64_t>(ipcRef.forget().take()));
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -239,16 +239,17 @@ AutoJSAPIWithErrorsReportedToWindow::Aut
 
 AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
                                  bool aIsMainThread,
                                  JSContext* aCx)
   : AutoJSAPI(aCx ? aCx : FindJSContext(aGlobalObject), aIsMainThread, /* aSkipNullAc = */ true)
   , ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
   , mAc(cx(), aGlobalObject->GetGlobalJSObject())
   , mStack(ScriptSettingsStack::Ref())
+  , mWebIDLCallerPrincipal(nullptr)
 {
   MOZ_ASSERT(aGlobalObject);
   MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread.
   MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject));
   mStack.Push(this);
 }
 
 AutoEntryScript::~AutoEntryScript()
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -174,17 +174,24 @@ public:
 
   void SetWebIDLCallerPrincipal(nsIPrincipal *aPrincipal) {
     mWebIDLCallerPrincipal = aPrincipal;
   }
 
 private:
   JSAutoCompartment mAc;
   dom::ScriptSettingsStack& mStack;
-  nsCOMPtr<nsIPrincipal> mWebIDLCallerPrincipal;
+  // 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;
   friend nsIPrincipal* GetWebIDLCallerPrincipal();
 };
 
 /*
  * A class that can be used to force a particular incumbent script on the stack.
  */
 class AutoIncumbentScript : protected ScriptSettingsStackEntry {
 public:
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -2610,23 +2610,16 @@ OldBindingConstructorEnabled(const nsGlo
       expose = nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal());
     }
 
     if (!expose) {
       return false;
     }
   }
 
-  // Don't expose CSSSupportsRule unless @supports processing is enabled.
-  if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSSupportsRule_id) {
-    if (!CSSSupportsRule::PrefEnabled()) {
-      return false;
-    }
-  }
-
   // Don't expose CSSFontFeatureValuesRule unless the pref is enabled
   if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) {
     return nsCSSFontFeatureValuesRule::PrefEnabled();
   }
 
   return true;
 }
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3020,17 +3020,17 @@ NS_IMETHODIMP
 nsDOMWindowUtils::GetFileId(JS::Handle<JS::Value> aFile, JSContext* aCx,
                             int64_t* aResult)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   if (!aFile.isPrimitive()) {
     JSObject* obj = aFile.toObjectOrNull();
 
-    FileHandle* fileHandle;
+    FileHandle* fileHandle = nullptr;
     if (NS_SUCCEEDED(UNWRAP_OBJECT(FileHandle, obj, fileHandle))) {
       *aResult = fileHandle->GetFileId();
       return NS_OK;
     }
 
     nsISupports* nativeObj =
       nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7900,17 +7900,17 @@ PostMessageReadTransferStructuredClone(J
                                        uint32_t tag, void* aData,
                                        uint64_t aExtraData,
                                        void* aClosure,
                                        JS::MutableHandle<JSObject*> returnObject)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  if (MessageChannel::PrefEnabled() && tag == SCTAG_DOM_MAP_MESSAGEPORT) {
+  if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
     MessagePort* port = static_cast<MessagePort*>(aData);
     port->BindToOwner(scInfo->window);
     scInfo->ports.Put(port, nullptr);
 
     JS::Rooted<JSObject*> obj(aCx, port->WrapObject(aCx));
     if (JS_WrapObject(aCx, &obj)) {
       MOZ_ASSERT(port->GetOwner() == scInfo->window);
       returnObject.set(obj);
@@ -7929,49 +7929,47 @@ PostMessageTransferStructuredClone(JSCon
                                    uint32_t* aTag,
                                    JS::TransferableOwnership* aOwnership,
                                    void** aContent,
                                    uint64_t* aExtraData)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  if (MessageChannel::PrefEnabled()) {
-    MessagePortBase* port = nullptr;
-    nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
-    if (NS_SUCCEEDED(rv)) {
-      nsRefPtr<MessagePortBase> newPort;
-      if (scInfo->ports.Get(port, getter_AddRefs(newPort))) {
-        // No duplicate.
-        return false;
-      }
-
-      newPort = port->Clone();
-      scInfo->ports.Put(port, newPort);
-
-      *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
-      *aOwnership = JS::SCTAG_TMO_CUSTOM;
-      *aContent = newPort;
-      *aExtraData = 0;
-
-      return true;
-    }
+  MessagePortBase* port = nullptr;
+  nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
+  if (NS_SUCCEEDED(rv)) {
+    nsRefPtr<MessagePortBase> newPort;
+    if (scInfo->ports.Get(port, getter_AddRefs(newPort))) {
+      // No duplicate.
+      return false;
+    }
+
+    newPort = port->Clone();
+    scInfo->ports.Put(port, newPort);
+
+    *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
+    *aOwnership = JS::SCTAG_TMO_CUSTOM;
+    *aContent = newPort;
+    *aExtraData = 0;
+
+    return true;
   }
 
   return false;
 }
 
 void
 PostMessageFreeTransferStructuredClone(uint32_t aTag, JS::TransferableOwnership aOwnership,
                                        void *aContent, uint64_t aExtraData, void* aClosure)
 {
   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
   NS_ASSERTION(scInfo, "Must have scInfo!");
 
-  if (MessageChannel::PrefEnabled() && aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
+  if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
     nsRefPtr<MessagePortBase> port(static_cast<MessagePort*>(aContent));
     scInfo->ports.Remove(port);
   }
 }
 
 JSStructuredCloneCallbacks kPostMessageCallbacks = {
   PostMessageReadStructuredClone,
   PostMessageWriteStructuredClone,
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -962,16 +962,17 @@ public:
                                       mozilla::ErrorResult& aError)
   {
     return CancelAnimationFrame(aHandle, aError);
   }
   int64_t GetMozAnimationStartTime(mozilla::ErrorResult& aError);
   void SizeToContent(mozilla::ErrorResult& aError);
   nsIDOMCrypto* GetCrypto(mozilla::ErrorResult& aError);
   nsIControllers* GetControllers(mozilla::ErrorResult& aError);
+  mozilla::dom::Element* GetRealFrameElement(mozilla::ErrorResult& aError);
   float GetMozInnerScreenX(mozilla::ErrorResult& aError);
   float GetMozInnerScreenY(mozilla::ErrorResult& aError);
   float GetDevicePixelRatio(mozilla::ErrorResult& aError);
   int32_t GetScrollMaxX(mozilla::ErrorResult& aError);
   int32_t GetScrollMaxY(mozilla::ErrorResult& aError);
   bool GetFullScreen(mozilla::ErrorResult& aError);
   void SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError);
   void Back(mozilla::ErrorResult& aError);
@@ -1369,18 +1370,16 @@ protected:
   // Returns device pixels.  Outer windows only.
   nsIntPoint GetScreenXY(mozilla::ErrorResult& aError);
 
   int32_t RequestAnimationFrame(const nsIDocument::FrameRequestCallbackHolder& aCallback,
                                 mozilla::ErrorResult& aError);
 
   nsGlobalWindow* InnerForSetTimeoutOrInterval(mozilla::ErrorResult& aError);
 
-  mozilla::dom::Element* GetRealFrameElement(mozilla::ErrorResult& aError);
-
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const nsAString& aTargetOrigin,
                       JS::Handle<JS::Value> aTransfer,
                       mozilla::ErrorResult& aError);
 
   already_AddRefed<nsIVariant>
     ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
                     const nsAString& aOptions, mozilla::ErrorResult& aError);
--- a/dom/base/test/chrome.ini
+++ b/dom/base/test/chrome.ini
@@ -3,11 +3,12 @@ support-files =
   file_url.jsm
   file_empty.html
 
 [test_bug715041.xul]
 [test_bug715041_removal.xul]
 [test_domrequesthelper.xul]
 [test_url.xul]
 [test_console.xul]
+[test_messageChannel.xul]
 [test_navigator_resolve_identity_xrays.xul]
 [test_sendQueryContentAndSelectionSetEvent.html]
 [test_bug1016960.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/iframe_messageChannel_chrome.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+  <script type="application/javascript">
+
+window.addEventListener('message', receiveMessage, false);
+function receiveMessage(evt) {
+  evt.data.postMessage("Hello world");
+}
+  </script>
+</body>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -1,12 +1,13 @@
 [DEFAULT]
 support-files =
   audio.ogg
   iframe_messageChannel_cloning.html
+  iframe_messageChannel_chrome.html
   iframe_messageChannel_pingpong.html
   iframe_messageChannel_post.html
   file_empty.html
   iframe_postMessage_solidus.html
 
 [test_Image_constructor.html]
 [test_appname_override.html]
 [test_audioWindowUtils.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_messageChannel.xul
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<window title="Test for MessageChannel API"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml" id="body">
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+
+  ok("MessageChannel" in window, "Should MessageChannel exist?");
+
+  var channel = new MessageChannel();
+  ok(channel, "MessageChannel is created");
+
+  channel.port1.onmessage = function(evt) {
+    ok(true, "message received!");
+    SimpleTest.finish();
+  }
+
+  var ifr = document.createElement('browser');
+  ifr.setAttribute("src", "http://mochi.test:8888/tests/dom/base/test/iframe_messageChannel_chrome.html");
+  ifr.setAttribute("flex", "1");
+  ifr.addEventListener('load', function() {
+    ifr.contentWindow.postMessage(channel.port2, '*', [channel.port2]);
+  });
+
+  var body = document.getElementById("body");
+  body.appendChild(ifr);
+
+  SimpleTest.waitForExplicitFinish();
+
+  ]]></script>
+</window>
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1557,17 +1557,17 @@ class CGClassConstructor(CGAbstractStati
               // Adding more relocations
               return ThrowConstructorWithoutNew(cx, "${ctorName}");
             }
             """,
             chromeOnlyCheck=chromeOnlyCheck,
             ctorName=ctorName)
 
         name = self._ctor.identifier.name
-        nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
+        nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
         callGenerator = CGMethodCall(nativeName, True, self.descriptor,
                                      self._ctor, isConstructor=True,
                                      constructorName=ctorName)
         return preamble + callGenerator.define()
 
 
 # Encapsulate the constructor in a helper method to share genConstructorBody with CGJSImplMethod.
 class CGConstructNavigatorObjectHelper(CGAbstractStaticMethod):
@@ -6942,17 +6942,17 @@ class CGSpecializedMethod(CGAbstractStat
         nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
                                                         self.method)
         return CGMethodCall(nativeName, self.method.isStatic(), self.descriptor,
                             self.method).define()
 
     @staticmethod
     def makeNativeName(descriptor, method):
         name = method.identifier.name
-        return MakeNativeName(descriptor.binaryNames.get(name, name))
+        return MakeNativeName(descriptor.binaryNameFor(name))
 
 
 class CGMethodPromiseWrapper(CGAbstractStaticMethod):
     """
     A class for generating a wrapper around another method that will
     convert exceptions to promises.
     """
     def __init__(self, descriptor, methodToWrap):
@@ -7031,17 +7031,17 @@ class CGLegacyCallHook(CGAbstractBinding
 
     def define(self):
         if not self._legacycaller:
             return ""
         return CGAbstractBindingMethod.define(self)
 
     def generate_code(self):
         name = self._legacycaller.identifier.name
-        nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
+        nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
         return CGMethodCall(nativeName, False, self.descriptor,
                             self._legacycaller)
 
 
 class CGNewResolveHook(CGAbstractBindingMethod):
     """
     NewResolve hook for objects with custom hooks.
     """
@@ -7282,17 +7282,17 @@ class CGSpecializedGetter(CGAbstractStat
 
         return (prefix +
                 CGGetterCall(self.attr.type, nativeName,
                              self.descriptor, self.attr).define())
 
     @staticmethod
     def makeNativeName(descriptor, attr):
         name = attr.identifier.name
-        nativeName = MakeNativeName(descriptor.binaryNames.get(name, name))
+        nativeName = MakeNativeName(descriptor.binaryNameFor(name))
         # resultOutParam does not depend on whether resultAlreadyAddRefed is set
         _, resultOutParam, _, _ = getRetvalDeclarationForType(attr.type,
                                                               descriptor,
                                                               False)
         infallible = ('infallible' in
                       descriptor.getExtendedAttributes(attr, getter=True))
         if resultOutParam or attr.type.nullable() or not infallible:
             nativeName = "Get" + nativeName
@@ -7385,17 +7385,17 @@ class CGSpecializedSetter(CGAbstractStat
         nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
                                                         self.attr)
         return CGSetterCall(self.attr.type, nativeName, self.descriptor,
                             self.attr).define()
 
     @staticmethod
     def makeNativeName(descriptor, attr):
         name = attr.identifier.name
-        return "Set" + MakeNativeName(descriptor.binaryNames.get(name, name))
+        return "Set" + MakeNativeName(descriptor.binaryNameFor(name))
 
 
 class CGStaticSetter(CGAbstractStaticBindingMethod):
     """
     A class for generating the C++ code for an IDL static attribute setter.
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
@@ -9090,17 +9090,17 @@ class CGProxySpecialOperation(CGPerSigna
     (don't use this directly, use the derived classes below).
 
     If checkFound is False, will just assert that the prop is found instead of
     checking that it is before wrapping the value.
     """
     def __init__(self, descriptor, operation, checkFound=True, argumentMutableValue=None):
         self.checkFound = checkFound
 
-        nativeName = MakeNativeName(descriptor.binaryNames.get(operation, operation))
+        nativeName = MakeNativeName(descriptor.binaryNameFor(operation))
         operation = descriptor.operations[operation]
         assert len(operation.signatures()) == 1
         signature = operation.signatures()[0]
 
         returnType, arguments = signature
 
         # We pass len(arguments) as the final argument so that the
         # CGPerSignatureCall won't do any argument conversion of its own.
@@ -12303,22 +12303,22 @@ def genConstructorBody(descriptor, initC
         contractId=descriptor.interface.getJSImplementation(),
         implClass=descriptor.name,
         initCall=initCall)
 
 
 # We're always fallible
 def callbackGetterName(attr, descriptor):
     return "Get" + MakeNativeName(
-        descriptor.binaryNames.get(attr.identifier.name, attr.identifier.name))
+        descriptor.binaryNameFor(attr.identifier.name))
 
 
 def callbackSetterName(attr, descriptor):
     return "Set" + MakeNativeName(
-        descriptor.binaryNames.get(attr.identifier.name, attr.identifier.name))
+        descriptor.binaryNameFor(attr.identifier.name))
 
 
 class CGJSImplGetter(CGJSImplMember):
     """
     Class for generating code for the getters of attributes for a JS-implemented
     WebIDL interface.
     """
     def __init__(self, descriptor, attr):
@@ -13047,17 +13047,17 @@ class CallCallback(CallbackMethod):
 
 
 class CallbackOperationBase(CallbackMethod):
     """
     Common class for implementing various callback operations.
     """
     def __init__(self, signature, jsName, nativeName, descriptor, singleOperation, rethrowContentException=False):
         self.singleOperation = singleOperation
-        self.methodName = descriptor.binaryNames.get(jsName, jsName)
+        self.methodName = descriptor.binaryNameFor(jsName)
         CallbackMethod.__init__(self, signature, nativeName, descriptor, singleOperation, rethrowContentException)
 
     def getThisDecl(self):
         if not self.singleOperation:
             return "JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));\n"
         # This relies on getCallableDecl declaring a boolean
         # isCallable in the case when we're a single-operation
         # interface.
@@ -13102,17 +13102,17 @@ class CallbackOperation(CallbackOperatio
     Codegen actual WebIDL operations on callback interfaces.
     """
     def __init__(self, method, signature, descriptor):
         self.ensureASCIIName(method)
         self.method = method
         jsName = method.identifier.name
         CallbackOperationBase.__init__(self, signature,
                                        jsName,
-                                       MakeNativeName(descriptor.binaryNames.get(jsName, jsName)),
+                                       MakeNativeName(descriptor.binaryNameFor(jsName)),
                                        descriptor, descriptor.interface.isSingleOperationInterface(),
                                        rethrowContentException=descriptor.interface.isJSImplemented())
 
     def getPrettyName(self):
         return "%s.%s" % (self.descriptorProvider.interface.identifier.name,
                           self.method.identifier.name)
 
 
@@ -13146,18 +13146,17 @@ class CallbackGetter(CallbackAccessor):
         return fill(
             """
             JS::Rooted<JSObject *> callback(cx, mCallback);
             if (!JS_GetProperty(cx, callback, "${attrName}", &rval)) {
               aRv.Throw(NS_ERROR_UNEXPECTED);
               return${errorReturn};
             }
             """,
-            attrName=self.descriptorProvider.binaryNames.get(self.attrName,
-                                                             self.attrName),
+            attrName=self.descriptorProvider.binaryNameFor(self.attrName),
             errorReturn=self.getDefaultRetval())
 
 
 class CallbackSetter(CallbackAccessor):
     def __init__(self, attr, descriptor):
         CallbackAccessor.__init__(self, attr,
                                   (BuiltinTypes[IDLBuiltinType.Types.void],
                                    [FakeArgument(attr.type, attr)]),
@@ -13172,18 +13171,17 @@ class CallbackSetter(CallbackAccessor):
         return fill(
             """
             MOZ_ASSERT(argv.length() == 1);
             if (!JS_SetProperty(cx, CallbackPreserveColor(), "${attrName}", argv[0])) {
               aRv.Throw(NS_ERROR_UNEXPECTED);
               return${errorReturn};
             }
             """,
-            attrName=self.descriptorProvider.binaryNames.get(self.attrName,
-                                                             self.attrName),
+            attrName=self.descriptorProvider.binaryNameFor(self.attrName),
             errorReturn=self.getDefaultRetval())
 
     def getArgcDecl(self):
         return None
 
 
 class CGJSImplInitOperation(CallbackOperationBase):
     """
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -409,22 +409,19 @@ class Descriptor(DescriptorProvider):
                     add('all', [config], attribute)
 
         if self.interface.isJSImplemented():
             addExtendedAttribute('implicitJSContext', ['constructor'])
         else:
             for attribute in ['implicitJSContext', 'resultNotAddRefed']:
                 addExtendedAttribute(attribute, desc.get(attribute, {}))
 
-        self.binaryNames = desc.get('binaryNames', {})
-        if '__legacycaller' not in self.binaryNames:
-            self.binaryNames["__legacycaller"] = "LegacyCall"
-        if '__stringifier' not in self.binaryNames:
-            self.binaryNames["__stringifier"] = "Stringify"
-
+        self._binaryNames = desc.get('binaryNames', {})
+        self._binaryNames.setdefault('__legacycaller', 'LegacyCall')
+        self._binaryNames.setdefault('__stringifier', 'Stringify')
 
         if not self.interface.isExternal():
             self.permissions = dict()
 
             # Adds a permission list to this descriptor and returns the index to use.
             def addPermissions(ifaceOrMember):
                 checkPermissions = ifaceOrMember.getExtendedAttribute("CheckPermissions")
                 if checkPermissions is None:
@@ -452,16 +449,19 @@ class Descriptor(DescriptorProvider):
         self.prototypeChain = []
         parent = interface
         while parent:
             self.prototypeChain.insert(0, parent.identifier.name)
             parent = parent.parent
         config.maxProtoChainLength = max(config.maxProtoChainLength,
                                          len(self.prototypeChain))
 
+    def binaryNameFor(self, name):
+        return self._binaryNames.get(name, name)
+
     def hasInterfaceOrInterfacePrototypeObject(self):
 
         # Forward-declared interfaces don't need either interface object or
         # interface prototype object as they're going to use QI (on main thread)
         # or be passed as a JSObject (on worker threads).
         if self.interface.isExternal():
             return False
 
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -21,17 +21,17 @@ namespace dom {
 
 /*
  * Class that just handles the JSObject storage and tracing for typed arrays
  */
 struct TypedArrayObjectStorage : AllTypedArraysBase {
 protected:
   JSObject* mObj;
 
-  TypedArrayObjectStorage(JSObject *obj) : mObj(obj)
+  TypedArrayObjectStorage() : mObj(nullptr)
   {
   }
 
   explicit TypedArrayObjectStorage(TypedArrayObjectStorage&& aOther)
     : mObj(aOther.mObj)
   {
     aOther.mObj = nullptr;
   }
@@ -55,28 +55,18 @@ private:
  * or array buffer object.
  */
 template<typename T,
          JSObject* UnwrapArray(JSObject*),
          void GetLengthAndData(JSObject*, uint32_t*, T**)>
 struct TypedArray_base : public TypedArrayObjectStorage {
   typedef T element_type;
 
-  TypedArray_base(JSObject* obj)
-    : TypedArrayObjectStorage(obj),
-      mData(nullptr),
-      mLength(0),
-      mComputed(false)
-  {
-    MOZ_ASSERT(obj != nullptr);
-  }
-
   TypedArray_base()
-    : TypedArrayObjectStorage(nullptr),
-      mData(nullptr),
+    : mData(nullptr),
       mLength(0),
       mComputed(false)
   {
   }
 
   explicit TypedArray_base(TypedArray_base&& aOther)
     : TypedArrayObjectStorage(Move(aOther)),
       mData(aOther.mData),
@@ -92,17 +82,17 @@ private:
   mutable T* mData;
   mutable uint32_t mLength;
   mutable bool mComputed;
 
 public:
   inline bool Init(JSObject* obj)
   {
     MOZ_ASSERT(!inited());
-    DoInit(obj);
+    mObj = UnwrapArray(obj);
     return inited();
   }
 
   inline bool inited() const {
     return !!mObj;
   }
 
   inline T *Data() const {
@@ -130,21 +120,16 @@ public:
   {
     MOZ_ASSERT(inited());
     MOZ_ASSERT(!mComputed);
     GetLengthAndData(mObj, &mLength, &mData);
     mComputed = true;
   }
 
 protected:
-  inline void DoInit(JSObject* obj)
-  {
-    mObj = UnwrapArray(obj);
-  }
-
   inline void ComputeData() const {
     MOZ_ASSERT(inited());
     if (!mComputed) {
       GetLengthAndData(mObj, &mLength, &mData);
       mComputed = true;
     }
   }
 
@@ -158,20 +143,16 @@ template<typename T,
          T* GetData(JSObject*),
          void GetLengthAndData(JSObject*, uint32_t*, T**),
          JSObject* CreateNew(JSContext*, uint32_t)>
 struct TypedArray : public TypedArray_base<T, UnwrapArray, GetLengthAndData> {
 private:
   typedef TypedArray_base<T, UnwrapArray, GetLengthAndData> Base;
 
 public:
-  TypedArray(JSObject* obj)
-    : Base(obj)
-  {}
-
   TypedArray()
     : Base()
   {}
 
   explicit TypedArray(TypedArray&& aOther)
     : Base(Move(aOther))
   {
   }
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -312,17 +312,18 @@ public:
     if (mEncrypt) {
       if (!mPubKey) {
         mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
         return;
       }
       mStrength = SECKEY_PublicKeyStrength(mPubKey);
 
       // Verify that the data input is not too big
-      // (as required by PKCS#1 / RFC 3447)
+      // (as required by PKCS#1 / RFC 3447, Section 7.2)
+      // http://tools.ietf.org/html/rfc3447#section-7.2
       if (mData.Length() > mStrength - 11) {
         mEarlyRv = NS_ERROR_DOM_DATA_ERR;
         return;
       }
     } else {
       if (!mPrivKey) {
         mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
         return;
@@ -443,20 +444,22 @@ private:
     if (mSign) {
       // Return the computed MAC
       TypedArrayCreator<Uint8Array> ret(mResult);
       mResultPromise->MaybeResolve(ret);
     } else {
       // Compare the MAC to the provided signature
       // No truncation allowed
       bool equal = (mResult.Length() == mSignature.Length());
-      int cmp = NSS_SecureMemcmp(mSignature.Elements(),
-                                 mResult.Elements(),
-                                 mSignature.Length());
-      equal = equal && (cmp == 0);
+      if (equal) {
+        int cmp = NSS_SecureMemcmp(mSignature.Elements(),
+                                   mResult.Elements(),
+                                   mSignature.Length());
+        equal = (cmp == 0);
+      }
       mResultPromise->MaybeResolve(equal);
     }
   }
 };
 
 class RsassaPkcs1Task : public WebCryptoTask
 {
 public:
@@ -530,19 +533,23 @@ private:
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
 
       rv = MapSECStatus(SGN_Update(ctx, mData.Elements(), mData.Length()));
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
 
       rv = MapSECStatus(SGN_End(ctx, signature));
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
 
-      mSignature.Assign(signature);
+      ATTEMPT_BUFFER_ASSIGN(mSignature, signature);
     } else {
       ScopedSECItem signature(mSignature.ToSECItem());
+      if (!signature) {
+        return NS_ERROR_DOM_UNKNOWN_ERR;
+      }
+
       ScopedVFYContext ctx(VFY_CreateContext(mPubKey, signature,
                                              mOidTag, nullptr));
       if (!ctx) {
         int err = PORT_GetError();
         if (err == SEC_ERROR_BAD_SIGNATURE) {
           mVerified = false;
           return NS_OK;
         }
@@ -580,16 +587,17 @@ public:
                    const ObjectOrString& aAlgorithm,
                    const CryptoOperationData& aData)
   {
     ATTEMPT_BUFFER_INIT(mData, aData);
 
     nsString algName;
     mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
     if (NS_FAILED(mEarlyRv)) {
+      mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
       return;
     }
 
     if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA1))   {
       mOidTag = SEC_OID_SHA1;
     } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA224)) {
       mOidTag = SEC_OID_SHA224;
     } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
@@ -932,42 +940,41 @@ private:
   {
     nsNSSShutDownPreventionLock locker;
 
     if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
       mResult = mSymKey;
       if (mResult.Length() == 0) {
         return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       }
+
+      return NS_OK;
     } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_PKCS8)) {
       if (!mPrivateKey) {
-        mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       }
 
       switch (mPrivateKey->keyType) {
         case rsaKey:
           Key::PrivateKeyToPkcs8(mPrivateKey.get(), mResult, locker);
-          mEarlyRv = NS_OK;
-          break;
+          return NS_OK;
         default:
-          mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+          return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       }
     } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) {
       if (!mPublicKey) {
         return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
       }
 
-      mEarlyRv = Key::PublicKeyToSpki(mPublicKey.get(), mResult, locker);
+      return Key::PublicKeyToSpki(mPublicKey.get(), mResult, locker);
     } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
-      mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-    } else {
-      mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
+      return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     }
 
-    return NS_OK;
+    return NS_ERROR_DOM_SYNTAX_ERR;
   }
 };
 
 class GenerateSymmetricKeyTask : public WebCryptoTask
 {
 public:
   GenerateSymmetricKeyTask(JSContext* aCx,
       const ObjectOrString& aAlgorithm, bool aExtractable,
@@ -983,29 +990,31 @@ public:
     mKey = new Key(global);
     mKey->SetExtractable(aExtractable);
     mKey->SetType(Key::SECRET);
 
     // Extract algorithm name
     nsString algName;
     mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
     if (NS_FAILED(mEarlyRv)) {
+      mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
       return;
     }
 
     // Construct an appropriate KeyAlorithm
     nsRefPtr<KeyAlgorithm> algorithm;
     uint32_t allowedUsages = 0;
     if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
         algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
         algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
       RootedDictionary<AesKeyGenParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv) || !params.mLength.WasPassed()) {
         mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
+        return;
       }
 
       mLength = params.mLength.Value();
       if (mLength != 128 && mLength != 192 && mLength != 256) {
         mEarlyRv = NS_ERROR_DOM_DATA_ERR;
         return;
       }
       algorithm = new AesKeyAlgorithm(global, algName, mLength);
@@ -1021,16 +1030,17 @@ public:
 
       nsString hashName;
       if (params.mHash.Value().IsString()) {
         hashName.Assign(params.mHash.Value().GetAsString());
       } else {
         Algorithm hashAlg;
         mEarlyRv = Coerce(aCx, hashAlg, params.mHash.Value());
         if (NS_FAILED(mEarlyRv) || !hashAlg.mName.WasPassed()) {
+          mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
           return;
         }
         hashName.Assign(hashAlg.mName.Value());
       }
 
       mLength = params.mLength.Value();
       algorithm = new HmacKeyAlgorithm(global, algName, mLength, hashName);
       allowedUsages = Key::SIGN | Key::VERIFY;
@@ -1047,18 +1057,16 @@ public:
         return;
       }
     }
 
     mLength = mLength >> 3; // bits to bytes
     mMechanism = algorithm->Mechanism();
     mKey->SetAlgorithm(algorithm);
     // SetSymKey done in Resolve, after we've done the keygen
-
-    return;
   }
 
 private:
   nsRefPtr<Key> mKey;
   size_t mLength;
   CK_MECHANISM_TYPE mMechanism;
   CryptoBuffer mKeyData;
 
@@ -1110,39 +1118,41 @@ public:
 
     // Create an empty key and set easy attributes
     mKeyPair = new KeyPair(global);
 
     // Extract algorithm name
     nsString algName;
     mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
     if (NS_FAILED(mEarlyRv)) {
+      mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
       return;
     }
 
     // Construct an appropriate KeyAlorithm
     KeyAlgorithm* algorithm;
     uint32_t privateAllowedUsages = 0, publicAllowedUsages = 0;
     if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
       RootedDictionary<RsaHashedKeyGenParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv) || !params.mModulusLength.WasPassed() ||
           !params.mPublicExponent.WasPassed() ||
           !params.mHash.WasPassed()) {
-        // TODO fix error and handle default values
         mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
+        return;
       }
 
       // Pull relevant info
       uint32_t modulusLength = params.mModulusLength.Value();
       CryptoBuffer publicExponent;
       ATTEMPT_BUFFER_INIT(publicExponent, params.mPublicExponent.Value());
       nsString hashName;
       mEarlyRv = GetAlgorithmName(aCx, params.mHash.Value(), hashName);
       if (NS_FAILED(mEarlyRv)) {
+        mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
         return;
       }
 
       // Create algorithm
       algorithm = new RsaHashedKeyAlgorithm(global, algName, modulusLength,
                                             publicExponent, hashName);
       mKeyPair->PublicKey()->SetAlgorithm(algorithm);
       mKeyPair->PrivateKey()->SetAlgorithm(algorithm);
@@ -1158,18 +1168,18 @@ public:
 
       privateAllowedUsages = Key::SIGN;
       publicAllowedUsages = Key::VERIFY;
     } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSAES_PKCS1)) {
       RootedDictionary<RsaKeyGenParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv) || !params.mModulusLength.WasPassed() ||
           !params.mPublicExponent.WasPassed()) {
-        // TODO fix error and handle default values
         mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
+        return;
       }
 
       // Pull relevant info
       uint32_t modulusLength = params.mModulusLength.Value();
       CryptoBuffer publicExponent;
       ATTEMPT_BUFFER_INIT(publicExponent, params.mPublicExponent.Value());
 
       // Create algorithm and note the mechanism
@@ -1210,18 +1220,16 @@ public:
       }
 
       mEarlyRv = mKeyPair->PublicKey()->AddUsageIntersecting(aKeyUsages[i],
                                                              publicAllowedUsages);
       if (NS_FAILED(mEarlyRv)) {
         return;
       }
     }
-
-    return;
   }
 
 private:
   nsRefPtr<KeyPair> mKeyPair;
   CK_MECHANISM_TYPE mMechanism;
   PK11RSAGenParams mRsaParams;
   ScopedSECKEYPublicKey mPublicKey;
   ScopedSECKEYPrivateKey mPrivateKey;
--- a/dom/datastore/DataStoreService.cpp
+++ b/dom/datastore/DataStoreService.cpp
@@ -145,17 +145,17 @@ RejectPromise(nsPIDOMWindow* aWindow, Pr
   if (aRv == NS_ERROR_DOM_SECURITY_ERR) {
     error = new DOMError(aWindow, NS_LITERAL_STRING("SecurityError"),
                          NS_LITERAL_STRING("Access denied"));
   } else {
     error = new DOMError(aWindow, NS_LITERAL_STRING("InternalError"),
                          NS_LITERAL_STRING("An error occurred"));
   }
 
-  aPromise->MaybeReject(error);
+  aPromise->MaybeRejectBrokenly(error);
 }
 
 void
 DeleteDatabase(const nsAString& aName,
                const nsAString& aManifestURL)
 {
   AssertIsInMainProcess();
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.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/. */
 
 // Microsoft's API Name hackery sucks
 #undef CreateEvent
 
 #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"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/JSEventHandler.h"
@@ -1324,16 +1325,37 @@ EventListenerManager::MarkForCC()
       listener.mListener.GetWebIDLCallback()->Callback();
     }
   }
   if (mRefCnt.IsPurple()) {
     mRefCnt.RemovePurple();
   }
 }
 
+void
+EventListenerManager::TraceListeners(JSTracer* aTrc)
+{
+  uint32_t count = mListeners.Length();
+  for (uint32_t i = 0; i < count; ++i) {
+    const Listener& listener = mListeners.ElementAt(i);
+    JSEventHandler* jsEventHandler = listener.GetJSEventHandler();
+    if (jsEventHandler) {
+      const TypedEventHandler& typedHandler =
+        jsEventHandler->GetTypedEventHandler();
+      if (typedHandler.HasEventHandler()) {
+        mozilla::TraceScriptHolder(typedHandler.Ptr(), aTrc);
+      }
+    } else if (listener.mListenerType == Listener::eWebIDLListener) {
+      mozilla::TraceScriptHolder(listener.mListener.GetWebIDLCallback(), aTrc);
+    }
+    // We might have eWrappedJSListener, but that is the legacy type for
+    // JS implemented event listeners, and trickier to handle here.
+  }
+}
+
 already_AddRefed<nsIScriptGlobalObject>
 EventListenerManager::GetScriptGlobalAndDocument(nsIDocument** aDoc)
 {
   nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
   nsCOMPtr<nsIDocument> doc;
   nsCOMPtr<nsIScriptGlobalObject> global;
   if (node) {
     // Try to get context from doc
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -15,16 +15,17 @@
 #include "nsGkAtoms.h"
 #include "nsIDOMEventListener.h"
 #include "nsTObserverArray.h"
 
 class nsIDOMEvent;
 class nsIEventListenerInfo;
 class nsIScriptContext;
 class nsPIDOMWindow;
+class JSTracer;
 
 struct EventTypeData;
 
 template<class T> class nsCOMArray;
 
 namespace mozilla {
 
 class ELMCreationDetector;
@@ -399,16 +400,18 @@ public:
 
   uint32_t ListenerCount() const
   {
     return mListeners.Length();
   }
 
   void MarkForCC();
 
+  void TraceListeners(JSTracer* aTrc);
+
   dom::EventTarget* GetTarget() { return mTarget; }
 
 protected:
   void HandleEventInternal(nsPresContext* aPresContext,
                            WidgetEvent* aEvent,
                            nsIDOMEvent** aDOMEvent,
                            dom::EventTarget* aCurrentTarget,
                            nsEventStatus* aEventStatus);
--- a/dom/events/KeyNameList.h
+++ b/dom/events/KeyNameList.h
@@ -15,23 +15,159 @@
  */
 
 #define DEFINE_KEYNAME_INTERNAL(aCPPName, aDOMKeyName) \
   NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName)
 
 #define DEFINE_KEYNAME_WITH_SAME_NAME(aName) \
   DEFINE_KEYNAME_INTERNAL(aName, #aName)
 
+/******************************************************************************
+ * Special Key Values
+ *****************************************************************************/
 DEFINE_KEYNAME_WITH_SAME_NAME(Unidentified)
+
+/******************************************************************************
+ * Our Internal Key Values (must have "Moz" prefix)
+ *****************************************************************************/
 DEFINE_KEYNAME_INTERNAL(PrintableKey, "MozPrintableKey")
 
+/******************************************************************************
+ * Modifier Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(Alt)
+DEFINE_KEYNAME_WITH_SAME_NAME(AltGraph)
+DEFINE_KEYNAME_WITH_SAME_NAME(CapsLock)
+DEFINE_KEYNAME_WITH_SAME_NAME(Control)
+DEFINE_KEYNAME_WITH_SAME_NAME(Fn)
+// DEFINE_KEYNAME_WITH_SAME_NAME(FnLock)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Hyper)
+DEFINE_KEYNAME_WITH_SAME_NAME(Meta)
+DEFINE_KEYNAME_WITH_SAME_NAME(NumLock)
+DEFINE_KEYNAME_WITH_SAME_NAME(OS)
+DEFINE_KEYNAME_WITH_SAME_NAME(ScrollLock)
+DEFINE_KEYNAME_WITH_SAME_NAME(Shift)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Super)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Symbol)
+// DEFINE_KEYNAME_WITH_SAME_NAME(SymbolLock)
+
+/******************************************************************************
+ * Whitespace Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(Enter)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Separator)
+DEFINE_KEYNAME_WITH_SAME_NAME(Tab)
+
+/******************************************************************************
+ * Navigation Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(Down) // Rename to ArrowDown
+DEFINE_KEYNAME_WITH_SAME_NAME(Left) // Rename to ArrowLeft
+DEFINE_KEYNAME_WITH_SAME_NAME(Right) // Rename to ArrowRight
+DEFINE_KEYNAME_WITH_SAME_NAME(Up) // Rename to ArrowUp
+DEFINE_KEYNAME_WITH_SAME_NAME(End)
+DEFINE_KEYNAME_WITH_SAME_NAME(Home)
+DEFINE_KEYNAME_WITH_SAME_NAME(PageDown)
+DEFINE_KEYNAME_WITH_SAME_NAME(PageUp)
+
+/******************************************************************************
+ * Editing Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(Backspace)
+DEFINE_KEYNAME_WITH_SAME_NAME(Clear)
+DEFINE_KEYNAME_WITH_SAME_NAME(Copy)
+DEFINE_KEYNAME_WITH_SAME_NAME(Crsel) // Rename to CrSel
+DEFINE_KEYNAME_WITH_SAME_NAME(Cut)
+DEFINE_KEYNAME_WITH_SAME_NAME(Del) // Rename to Delete
+DEFINE_KEYNAME_WITH_SAME_NAME(EraseEof)
+DEFINE_KEYNAME_WITH_SAME_NAME(Exsel) // Rename to ExSel
+DEFINE_KEYNAME_WITH_SAME_NAME(Insert)
+DEFINE_KEYNAME_WITH_SAME_NAME(Paste)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Redo)
+DEFINE_KEYNAME_WITH_SAME_NAME(Undo)
+
+/******************************************************************************
+ * UI Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(Accept)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Again)
 DEFINE_KEYNAME_WITH_SAME_NAME(Attn)
-DEFINE_KEYNAME_WITH_SAME_NAME(Apps)
-DEFINE_KEYNAME_WITH_SAME_NAME(Crsel)
-DEFINE_KEYNAME_WITH_SAME_NAME(Exsel)
+DEFINE_KEYNAME_WITH_SAME_NAME(Cancel)
+DEFINE_KEYNAME_WITH_SAME_NAME(Menu) // Rename to ContextMenu
+DEFINE_KEYNAME_WITH_SAME_NAME(Esc) // Rename to Escape
+DEFINE_KEYNAME_WITH_SAME_NAME(Execute)
+DEFINE_KEYNAME_WITH_SAME_NAME(Find)
+DEFINE_KEYNAME_WITH_SAME_NAME(Help)
+DEFINE_KEYNAME_WITH_SAME_NAME(Pause)
+DEFINE_KEYNAME_WITH_SAME_NAME(Play)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Props)
+DEFINE_KEYNAME_WITH_SAME_NAME(Select)
+// DEFINE_KEYNAME_WITH_SAME_NAME(ZoomIn)
+// DEFINE_KEYNAME_WITH_SAME_NAME(ZoomOut)
+
+/******************************************************************************
+ * Device Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessDown)
+DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessUp)
+DEFINE_KEYNAME_WITH_SAME_NAME(Camera)
+DEFINE_KEYNAME_WITH_SAME_NAME(Eject)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LogOff)
+DEFINE_KEYNAME_WITH_SAME_NAME(Power)
+// DEFINE_KEYNAME_WITH_SAME_NAME(PowerOff)
+DEFINE_KEYNAME_WITH_SAME_NAME(PrintScreen)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Hibernate)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Standby)
+// DEFINE_KEYNAME_WITH_SAME_NAME(WakeUp)
+
+/******************************************************************************
+ * IME and Composition Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(AllCandidates)
+DEFINE_KEYNAME_WITH_SAME_NAME(Alphanumeric)
+DEFINE_KEYNAME_WITH_SAME_NAME(CodeInput)
+DEFINE_KEYNAME_WITH_SAME_NAME(Compose)
+DEFINE_KEYNAME_WITH_SAME_NAME(Convert)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Dead)
+DEFINE_KEYNAME_WITH_SAME_NAME(FinalMode)
+// DEFINE_KEYNAME_WITH_SAME_NAME(GroupFirst)
+// DEFINE_KEYNAME_WITH_SAME_NAME(GroupLast)
+// DEFINE_KEYNAME_WITH_SAME_NAME(GroupNext)
+// DEFINE_KEYNAME_WITH_SAME_NAME(GroupPrevious)
+DEFINE_KEYNAME_WITH_SAME_NAME(ModeChange)
+// DEFINE_KEYNAME_WITH_SAME_NAME(NextCandidate)
+DEFINE_KEYNAME_WITH_SAME_NAME(Nonconvert) // Rename to NonConvert
+DEFINE_KEYNAME_WITH_SAME_NAME(PreviousCandidate)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Process)
+// DEFINE_KEYNAME_WITH_SAME_NAME(SingleCandidate)
+
+/******************************************************************************
+ * Keys specific to Korean keyboards
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(HangulMode)
+DEFINE_KEYNAME_WITH_SAME_NAME(HanjaMode)
+DEFINE_KEYNAME_WITH_SAME_NAME(JunjaMode)
+
+/******************************************************************************
+ * Keys specific to Japanese keyboards
+ *****************************************************************************/
+// DEFINE_KEYNAME_WITH_SAME_NAME(Eisu)
+DEFINE_KEYNAME_WITH_SAME_NAME(HalfWidth) // Rename to Hankaku
+DEFINE_KEYNAME_WITH_SAME_NAME(Hiragana)
+// DEFINE_KEYNAME_WITH_SAME_NAME(HiraganaKatakana)
+DEFINE_KEYNAME_WITH_SAME_NAME(KanaMode)
+DEFINE_KEYNAME_WITH_SAME_NAME(KanjiMode)
+DEFINE_KEYNAME_WITH_SAME_NAME(Katakana)
+DEFINE_KEYNAME_WITH_SAME_NAME(RomanCharacters) // Rename to Romaji
+DEFINE_KEYNAME_WITH_SAME_NAME(FullWidth) // Rename to Zenkaku
+// DEFINE_KEYNAME_WITH_SAME_NAME(ZenkakuHankaku)
+
+/******************************************************************************
+ * General-Purpose Function Keys
+ *****************************************************************************/
 DEFINE_KEYNAME_WITH_SAME_NAME(F1)
 DEFINE_KEYNAME_WITH_SAME_NAME(F2)
 DEFINE_KEYNAME_WITH_SAME_NAME(F3)
 DEFINE_KEYNAME_WITH_SAME_NAME(F4)
 DEFINE_KEYNAME_WITH_SAME_NAME(F5)
 DEFINE_KEYNAME_WITH_SAME_NAME(F6)
 DEFINE_KEYNAME_WITH_SAME_NAME(F7)
 DEFINE_KEYNAME_WITH_SAME_NAME(F8)
@@ -57,16 +193,57 @@ DEFINE_KEYNAME_WITH_SAME_NAME(F27)
 DEFINE_KEYNAME_WITH_SAME_NAME(F28)
 DEFINE_KEYNAME_WITH_SAME_NAME(F29)
 DEFINE_KEYNAME_WITH_SAME_NAME(F30)
 DEFINE_KEYNAME_WITH_SAME_NAME(F31)
 DEFINE_KEYNAME_WITH_SAME_NAME(F32)
 DEFINE_KEYNAME_WITH_SAME_NAME(F33)
 DEFINE_KEYNAME_WITH_SAME_NAME(F34)
 DEFINE_KEYNAME_WITH_SAME_NAME(F35)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Soft1)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Soft2)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Soft3)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Soft4)
+
+/******************************************************************************
+ * Multimedia Keys
+ *****************************************************************************/
+// DEFINE_KEYNAME_WITH_SAME_NAME(Close)
+// DEFINE_KEYNAME_WITH_SAME_NAME(MailForward)
+// DEFINE_KEYNAME_WITH_SAME_NAME(MailReply)
+// DEFINE_KEYNAME_WITH_SAME_NAME(MailSend)
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlayPause)
+DEFINE_KEYNAME_WITH_SAME_NAME(SelectMedia) // Rename to MediaSelect
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaStop)
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaNextTrack) // Rename to MediaTrackNext
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaPreviousTrack) // Rename to MediaTrackPrevious
+// DEFINE_KEYNAME_WITH_SAME_NAME(New)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Open)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Print)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Save)
+// DEFINE_KEYNAME_WITH_SAME_NAME(SpellCheck)
+DEFINE_KEYNAME_WITH_SAME_NAME(VolumeDown)
+DEFINE_KEYNAME_WITH_SAME_NAME(VolumeUp)
+DEFINE_KEYNAME_WITH_SAME_NAME(VolumeMute)
+
+/******************************************************************************
+ * Application Keys
+ *****************************************************************************/
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchCalculator)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchCalendar)
+DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMail)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMediaPlayer)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMusicPlayer)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMyComputer)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchScreenSaver)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchSpreadsheet)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchWebBrowser)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchWebCam)
+// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchWordProcessor)
+
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication1)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication2)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication3)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication4)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication5)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication6)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication7)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication8)
@@ -75,191 +252,124 @@ DEFINE_KEYNAME_WITH_SAME_NAME(LaunchAppl
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication11)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication12)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication13)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication14)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication15)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication16)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication17)
 DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication18)
-DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMail)
-DEFINE_KEYNAME_WITH_SAME_NAME(List)
-DEFINE_KEYNAME_WITH_SAME_NAME(Props)
-DEFINE_KEYNAME_WITH_SAME_NAME(Soft1)
-DEFINE_KEYNAME_WITH_SAME_NAME(Soft2)
-DEFINE_KEYNAME_WITH_SAME_NAME(Soft3)
-DEFINE_KEYNAME_WITH_SAME_NAME(Soft4)
-DEFINE_KEYNAME_WITH_SAME_NAME(Accept)
-DEFINE_KEYNAME_WITH_SAME_NAME(Again)
-DEFINE_KEYNAME_WITH_SAME_NAME(Enter)
-DEFINE_KEYNAME_WITH_SAME_NAME(Find)
-DEFINE_KEYNAME_WITH_SAME_NAME(Help)
-DEFINE_KEYNAME_WITH_SAME_NAME(Info)
-DEFINE_KEYNAME_WITH_SAME_NAME(Menu)
-DEFINE_KEYNAME_WITH_SAME_NAME(Pause)
-DEFINE_KEYNAME_WITH_SAME_NAME(Play)
-DEFINE_KEYNAME_WITH_SAME_NAME(ScrollLock) // IE9 users "Scroll"
-DEFINE_KEYNAME_WITH_SAME_NAME(Execute)
-DEFINE_KEYNAME_WITH_SAME_NAME(Cancel)
-DEFINE_KEYNAME_WITH_SAME_NAME(Esc)
-DEFINE_KEYNAME_WITH_SAME_NAME(Exit)
-DEFINE_KEYNAME_WITH_SAME_NAME(Zoom)
-DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessDown)
-DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessUp)
-DEFINE_KEYNAME_WITH_SAME_NAME(Camera)
-DEFINE_KEYNAME_WITH_SAME_NAME(Eject)
-DEFINE_KEYNAME_WITH_SAME_NAME(Power)
-DEFINE_KEYNAME_WITH_SAME_NAME(PrintScreen)
+
+/******************************************************************************
+ * Browser Keys
+ *****************************************************************************/
+DEFINE_KEYNAME_WITH_SAME_NAME(BrowserBack)
 DEFINE_KEYNAME_WITH_SAME_NAME(BrowserFavorites)
+DEFINE_KEYNAME_WITH_SAME_NAME(BrowserForward)
 DEFINE_KEYNAME_WITH_SAME_NAME(BrowserHome)
 DEFINE_KEYNAME_WITH_SAME_NAME(BrowserRefresh)
 DEFINE_KEYNAME_WITH_SAME_NAME(BrowserSearch)
 DEFINE_KEYNAME_WITH_SAME_NAME(BrowserStop)
-DEFINE_KEYNAME_WITH_SAME_NAME(BrowserBack)
-DEFINE_KEYNAME_WITH_SAME_NAME(BrowserForward)
-DEFINE_KEYNAME_WITH_SAME_NAME(Left)
-DEFINE_KEYNAME_WITH_SAME_NAME(PageDown)
-DEFINE_KEYNAME_WITH_SAME_NAME(PageUp)
-DEFINE_KEYNAME_WITH_SAME_NAME(Right)
-DEFINE_KEYNAME_WITH_SAME_NAME(Up)
-DEFINE_KEYNAME_WITH_SAME_NAME(UpLeft)
-DEFINE_KEYNAME_WITH_SAME_NAME(UpRight)
-DEFINE_KEYNAME_WITH_SAME_NAME(Down)
-DEFINE_KEYNAME_WITH_SAME_NAME(DownLeft)
-DEFINE_KEYNAME_WITH_SAME_NAME(DownRight)
-DEFINE_KEYNAME_WITH_SAME_NAME(Home)
-DEFINE_KEYNAME_WITH_SAME_NAME(End)
-DEFINE_KEYNAME_WITH_SAME_NAME(Select)
-DEFINE_KEYNAME_WITH_SAME_NAME(Tab)
-DEFINE_KEYNAME_WITH_SAME_NAME(Backspace)
-DEFINE_KEYNAME_WITH_SAME_NAME(Clear)
-DEFINE_KEYNAME_WITH_SAME_NAME(Copy)
-DEFINE_KEYNAME_WITH_SAME_NAME(Cut)
-DEFINE_KEYNAME_WITH_SAME_NAME(Del)
-DEFINE_KEYNAME_WITH_SAME_NAME(EraseEof)
-DEFINE_KEYNAME_WITH_SAME_NAME(Insert)
-DEFINE_KEYNAME_WITH_SAME_NAME(Paste)
-DEFINE_KEYNAME_WITH_SAME_NAME(Undo)
+
+/******************************************************************************
+ * Media Controller Keys
+ *****************************************************************************/
+// DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceLeft)
+// DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceRight)
+DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostDown)
+DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostUp)
+// DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderFront)
+// DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderRear)
+// DEFINE_KEYNAME_WITH_SAME_NAME(AudioSurroundModeNext)
+// DEFINE_KEYNAME_WITH_SAME_NAME(AVRInput)
+// DEFINE_KEYNAME_WITH_SAME_NAME(AVRPower)
+DEFINE_KEYNAME_WITH_SAME_NAME(ChannelDown)
+DEFINE_KEYNAME_WITH_SAME_NAME(ChannelUp)
+DEFINE_KEYNAME_WITH_SAME_NAME(Red) // Rename to ColorF0Red
+DEFINE_KEYNAME_WITH_SAME_NAME(Green) // Rename to ColorF1Green
+DEFINE_KEYNAME_WITH_SAME_NAME(Yellow) // Rename to ColorF2Yellow
+DEFINE_KEYNAME_WITH_SAME_NAME(Blue) // Rename to ColorF3Blue
+// DEFINE_KEYNAME_WITH_SAME_NAME(Grey) // Rename to ColorF4Grey
+// DEFINE_KEYNAME_WITH_SAME_NAME(Brown) // Rename to ColorF5Brown
+// DEFINE_KEYNAME_WITH_SAME_NAME(ClosedCaptionToggle)
+DEFINE_KEYNAME_WITH_SAME_NAME(Dimmer)
+// DEFINE_KEYNAME_WITH_SAME_NAME(DisplaySwap)
+DEFINE_KEYNAME_WITH_SAME_NAME(Exit)
+// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite0) // Rename to FavoriteClear0
+// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite1) // Rename to FavoriteClear1
+// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite2) // Rename to FavoriteClear2
+// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite3) // Rename to FavoriteClear3
+// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite0) // Rename to FavoriteRecall0
+// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite1) // Rename to FavoriteRecall1
+// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite2) // Rename to FavoriteRecall2
+// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite3) // Rename to FavoriteRecall3
+// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite0) // Rename to FavoriteStore0
+// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite1) // Rename to FavoriteStore1
+// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite2) // Rename to FavoriteStore2
+// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite3) // Rename to FavoriteStore3
+DEFINE_KEYNAME_WITH_SAME_NAME(Guide)
+// DEFINE_KEYNAME_WITH_SAME_NAME(NextDay) // Rename to GuideNextDay
+// DEFINE_KEYNAME_WITH_SAME_NAME(PrevDay) // Rename to GuidePreviousDay
+DEFINE_KEYNAME_WITH_SAME_NAME(Info)
+// DEFINE_KEYNAME_WITH_SAME_NAME(InstantReplay)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Link)
+// DEFINE_KEYNAME_WITH_SAME_NAME(List) // Rename to ListProgram
+DEFINE_KEYNAME_WITH_SAME_NAME(Live) // Rename to LiveContent
+// DEFINE_KEYNAME_WITH_SAME_NAME(Lock)
+DEFINE_KEYNAME_WITH_SAME_NAME(Apps) // Rename to MediaApps
+DEFINE_KEYNAME_WITH_SAME_NAME(FastFwd) // Rename to MediaFastForward
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaLast)
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaPause)
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlay)
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaRecord)
+DEFINE_KEYNAME_WITH_SAME_NAME(MediaRewind)
+// DEFINE_KEYNAME_WITH_SAME_NAME(MediaSkip)
+// DEFINE_KEYNAME_WITH_SAME_NAME(NextFavoriteChannel)
+// DEFINE_KEYNAME_WITH_SAME_NAME(NextUserProfile)
+// DEFINE_KEYNAME_WITH_SAME_NAME(OnDemand)
+// DEFINE_KEYNAME_WITH_SAME_NAME(PinPDown)
+// DEFINE_KEYNAME_WITH_SAME_NAME(PinPMove)
+DEFINE_KEYNAME_WITH_SAME_NAME(PinPToggle)
+// DEFINE_KEYNAME_WITH_SAME_NAME(PinPUp)
+// DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedDown)
+// DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedReset)
+// DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedUp)
+DEFINE_KEYNAME_WITH_SAME_NAME(RandomToggle)
+// DEFINE_KEYNAME_WITH_SAME_NAME(RcLowBattery)
+// DEFINE_KEYNAME_WITH_SAME_NAME(RecordSpeedNext)
+// DEFINE_KEYNAME_WITH_SAME_NAME(RfBypass)
+// DEFINE_KEYNAME_WITH_SAME_NAME(ScanChannelsToggle)
+// DEFINE_KEYNAME_WITH_SAME_NAME(ScreenModeNext)
+DEFINE_KEYNAME_WITH_SAME_NAME(Settings)
+// DEFINE_KEYNAME_WITH_SAME_NAME(SplitScreenToggle)
+// DEFINE_KEYNAME_WITH_SAME_NAME(STBInput)
+// DEFINE_KEYNAME_WITH_SAME_NAME(STBPower)
+DEFINE_KEYNAME_WITH_SAME_NAME(Subtitle)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Teletext)
+// DEFINE_KEYNAME_WITH_SAME_NAME(TV)
+// DEFINE_KEYNAME_WITH_SAME_NAME(TVInput)
+// DEFINE_KEYNAME_WITH_SAME_NAME(TVPower)
+// DEFINE_KEYNAME_WITH_SAME_NAME(VideoModeNext)
+// DEFINE_KEYNAME_WITH_SAME_NAME(Wink)
+DEFINE_KEYNAME_WITH_SAME_NAME(Zoom) // Rename to ZoomToggle
+
+/******************************************************************************
+ * Deprecated
+ ******************************************************************************/
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadGrave)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadAcute)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadCircumflex)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadTilde)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadMacron)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadBreve)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadAboveDot)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadUmlaut)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadAboveRing)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadDoubleacute)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadCaron)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadCedilla)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadOgonek)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadIota)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadVoicedSound)
 DEFINE_KEYNAME_WITH_SAME_NAME(DeadSemivoicedSound)
-DEFINE_KEYNAME_WITH_SAME_NAME(Alphanumeric)
-DEFINE_KEYNAME_WITH_SAME_NAME(Alt)
-DEFINE_KEYNAME_WITH_SAME_NAME(AltGraph)
-DEFINE_KEYNAME_WITH_SAME_NAME(CapsLock)
-DEFINE_KEYNAME_WITH_SAME_NAME(Control)
-DEFINE_KEYNAME_WITH_SAME_NAME(Fn)
-DEFINE_KEYNAME_WITH_SAME_NAME(FnLock)
-DEFINE_KEYNAME_WITH_SAME_NAME(Meta)
-DEFINE_KEYNAME_WITH_SAME_NAME(Process)
-DEFINE_KEYNAME_WITH_SAME_NAME(NumLock)
-DEFINE_KEYNAME_WITH_SAME_NAME(Shift)
-DEFINE_KEYNAME_WITH_SAME_NAME(SymbolLock)
-DEFINE_KEYNAME_WITH_SAME_NAME(OS) // IE9 uses "Win"
-DEFINE_KEYNAME_WITH_SAME_NAME(Compose)
-DEFINE_KEYNAME_WITH_SAME_NAME(AllCandidates)
-DEFINE_KEYNAME_WITH_SAME_NAME(NextCandidate)
-DEFINE_KEYNAME_WITH_SAME_NAME(PreviousCandidate)
-DEFINE_KEYNAME_WITH_SAME_NAME(CodeInput)
-DEFINE_KEYNAME_WITH_SAME_NAME(Convert)
-DEFINE_KEYNAME_WITH_SAME_NAME(Nonconvert)
-DEFINE_KEYNAME_WITH_SAME_NAME(FinalMode)
-DEFINE_KEYNAME_WITH_SAME_NAME(FullWidth)
-DEFINE_KEYNAME_WITH_SAME_NAME(HalfWidth)
-DEFINE_KEYNAME_WITH_SAME_NAME(ModeChange)
-DEFINE_KEYNAME_WITH_SAME_NAME(RomanCharacters)
-DEFINE_KEYNAME_WITH_SAME_NAME(HangulMode)
-DEFINE_KEYNAME_WITH_SAME_NAME(HanjaMode)
-DEFINE_KEYNAME_WITH_SAME_NAME(JunjaMode)
-DEFINE_KEYNAME_WITH_SAME_NAME(Hiragana)
-DEFINE_KEYNAME_WITH_SAME_NAME(KanaMode)
-DEFINE_KEYNAME_WITH_SAME_NAME(KanjiMode)
-DEFINE_KEYNAME_WITH_SAME_NAME(Katakana)
-DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderFront)
-DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderRear)
-DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceLeft)
-DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceRight)
-DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostDown)
-DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostUp)
-DEFINE_KEYNAME_WITH_SAME_NAME(VolumeMute)
-DEFINE_KEYNAME_WITH_SAME_NAME(VolumeDown)
-DEFINE_KEYNAME_WITH_SAME_NAME(VolumeUp)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaPause)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlay)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaStop)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaNextTrack)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaPreviousTrack)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlayPause)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaTrackSkip)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaTrackStart)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaTrackEnd)
-DEFINE_KEYNAME_WITH_SAME_NAME(SelectMedia)
-DEFINE_KEYNAME_WITH_SAME_NAME(Blue)
-DEFINE_KEYNAME_WITH_SAME_NAME(Brown)
-DEFINE_KEYNAME_WITH_SAME_NAME(ChannelDown)
-DEFINE_KEYNAME_WITH_SAME_NAME(ChannelUp)
-DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite0)
-DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite1)
-DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite2)
-DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite3)
-DEFINE_KEYNAME_WITH_SAME_NAME(Dimmer)
-DEFINE_KEYNAME_WITH_SAME_NAME(DisplaySwap)
-DEFINE_KEYNAME_WITH_SAME_NAME(FastFwd)
-DEFINE_KEYNAME_WITH_SAME_NAME(Green)
-DEFINE_KEYNAME_WITH_SAME_NAME(Grey)
-DEFINE_KEYNAME_WITH_SAME_NAME(Guide)
-DEFINE_KEYNAME_WITH_SAME_NAME(InstantReplay)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaLast)
-DEFINE_KEYNAME_WITH_SAME_NAME(Link)
-DEFINE_KEYNAME_WITH_SAME_NAME(Live)
-DEFINE_KEYNAME_WITH_SAME_NAME(Lock)
-DEFINE_KEYNAME_WITH_SAME_NAME(NextDay)
-DEFINE_KEYNAME_WITH_SAME_NAME(NextFavoriteChannel)
-DEFINE_KEYNAME_WITH_SAME_NAME(OnDemand)
-DEFINE_KEYNAME_WITH_SAME_NAME(PinPDown)
-DEFINE_KEYNAME_WITH_SAME_NAME(PinPMove)
-DEFINE_KEYNAME_WITH_SAME_NAME(PinPToggle)
-DEFINE_KEYNAME_WITH_SAME_NAME(PinPUp)
-DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedDown)
-DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedReset)
-DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedUp)
-DEFINE_KEYNAME_WITH_SAME_NAME(PrevDay)
-DEFINE_KEYNAME_WITH_SAME_NAME(RandomToggle)
-DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite0)
-DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite1)
-DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite2)
-DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite3)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaRecord)
-DEFINE_KEYNAME_WITH_SAME_NAME(RecordSpeedNext)
-DEFINE_KEYNAME_WITH_SAME_NAME(Red)
-DEFINE_KEYNAME_WITH_SAME_NAME(MediaRewind)
-DEFINE_KEYNAME_WITH_SAME_NAME(RfBypass)
-DEFINE_KEYNAME_WITH_SAME_NAME(ScanChannelsToggle)
-DEFINE_KEYNAME_WITH_SAME_NAME(ScreenModeNext)
-DEFINE_KEYNAME_WITH_SAME_NAME(Settings)
-DEFINE_KEYNAME_WITH_SAME_NAME(SplitScreenToggle)
-DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite0)
-DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite1)
-DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite2)
-DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite3)
-DEFINE_KEYNAME_WITH_SAME_NAME(Subtitle)
-DEFINE_KEYNAME_WITH_SAME_NAME(AudioSurroundModeNext)
-DEFINE_KEYNAME_WITH_SAME_NAME(Teletext)
-DEFINE_KEYNAME_WITH_SAME_NAME(VideoModeNext)
-DEFINE_KEYNAME_WITH_SAME_NAME(DisplayWide)
-DEFINE_KEYNAME_WITH_SAME_NAME(Wink)
-DEFINE_KEYNAME_WITH_SAME_NAME(Yellow)
 
 #undef DEFINE_KEYNAME_WITH_SAME_NAME
 #undef DEFINE_KEYNAME_INTERNAL
--- a/dom/events/PhysicalKeyCodeNameList.h
+++ b/dom/events/PhysicalKeyCodeNameList.h
@@ -37,17 +37,17 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit4)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit5)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit6)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit7)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit8)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit9)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Equal)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlBackslash)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlHash)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlHash)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlRo)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlYen)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyA)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyB)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyC)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyD)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyE)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyF)
@@ -92,19 +92,19 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Space)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Tab)
 
 // IME keys
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Convert)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KanaMode)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang1)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang2)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang3)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang4)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang5)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang3)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang4)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang5)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NonConvert)
 
 // Control pad section
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Delete)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(End)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Help)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Home)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Insert)
@@ -126,31 +126,31 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad4)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad5)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad6)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad7)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad8)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad9)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadAdd)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadBackspace)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClear)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClearEntry)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClear)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClearEntry)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadComma)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadDecimal)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadDivide)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadEnter)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadEqual)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryAdd)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryClear)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryRecall)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryStore)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryAdd)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryClear)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryRecall)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryStore)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemorySubtract)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMultiply)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenLeft)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenRight)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenLeft)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenRight)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadSubtract)
 
 // Function section
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Escape)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F1)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F2)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F3)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F4)
@@ -170,17 +170,17 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F18)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F19)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F20)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F21)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F22)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F23)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F24)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Fn)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(FLock)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(FLock)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(PrintScreen)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ScrollLock)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Pause)
 
 // Media keys
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserBack)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserFavorites)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(BrowserForward)
@@ -200,18 +200,17 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Power)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Sleep)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(VolumeDown)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(VolumeMute)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(VolumeUp)
 DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(WakeUp)
 
 // Legacy keys
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Abort)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Hyper)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Meta)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Resume)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Super)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Suspend)
-DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Turbo)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Abort)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Hyper)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Resume)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Super)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Suspend)
+// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Turbo)
 
 #undef DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME
 #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME_INTERNAL
--- a/dom/filesystem/CreateDirectoryTask.cpp
+++ b/dom/filesystem/CreateDirectoryTask.cpp
@@ -117,17 +117,17 @@ CreateDirectoryTask::HandlerCallback()
   if (mFileSystem->IsShutdown()) {
     mPromise = nullptr;
     return;
   }
 
   if (HasError()) {
     nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
       mErrorValue);
-    mPromise->MaybeReject(domError);
+    mPromise->MaybeRejectBrokenly(domError);
     mPromise = nullptr;
     return;
   }
   nsRefPtr<Directory> dir = new Directory(mFileSystem, mTargetRealPath);
   mPromise->MaybeResolve(dir);
   mPromise = nullptr;
 }
 
--- a/dom/filesystem/CreateFileTask.cpp
+++ b/dom/filesystem/CreateFileTask.cpp
@@ -282,17 +282,17 @@ CreateFileTask::HandlerCallback()
   if (mFileSystem->IsShutdown()) {
     mPromise = nullptr;
     return;
   }
 
   if (HasError()) {
     nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
       mErrorValue);
-    mPromise->MaybeReject(domError);
+    mPromise->MaybeRejectBrokenly(domError);
     mPromise = nullptr;
     return;
   }
 
   mPromise->MaybeResolve(mTargetFile);
   mPromise = nullptr;
 }
 
--- a/dom/filesystem/GetFileOrDirectoryTask.cpp
+++ b/dom/filesystem/GetFileOrDirectoryTask.cpp
@@ -192,17 +192,17 @@ GetFileOrDirectoryTask::HandlerCallback(
   if (mFileSystem->IsShutdown()) {
     mPromise = nullptr;
     return;
   }
 
   if (HasError()) {
     nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
       mErrorValue);
-    mPromise->MaybeReject(domError);
+    mPromise->MaybeRejectBrokenly(domError);
     mPromise = nullptr;
     return;
   }
 
   if (mIsDirectory) {
     nsRefPtr<Directory> dir = new Directory(mFileSystem, mTargetRealPath);
     mPromise->MaybeResolve(dir);
     mPromise = nullptr;
--- a/dom/filesystem/RemoveTask.cpp
+++ b/dom/filesystem/RemoveTask.cpp
@@ -180,17 +180,17 @@ RemoveTask::HandlerCallback()
   if (mFileSystem->IsShutdown()) {
     mPromise = nullptr;
     return;
   }
 
   if (HasError()) {
     nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
       mErrorValue);
-    mPromise->MaybeReject(domError);
+    mPromise->MaybeRejectBrokenly(domError);
     mPromise = nullptr;
     return;
   }
 
   mPromise->MaybeResolve(mReturnValue);
   mPromise = nullptr;
 }
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1468,17 +1468,17 @@ ContentChild::AddRemoteAlertObserver(con
 
 bool
 ContentChild::RecvSystemMemoryAvailable(const uint64_t& aGetterId,
                                         const uint32_t& aMemoryAvailable)
 {
     nsRefPtr<Promise> p = dont_AddRef(reinterpret_cast<Promise*>(aGetterId));
 
     if (!aMemoryAvailable) {
-        p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
+        p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
         return true;
     }
 
     p->MaybeResolve((int)aMemoryAvailable);
     return true;
 }
 
 bool
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -474,17 +474,17 @@ TabChildBase::ProcessUpdateFrame(const F
 }
 
 nsEventStatus
 TabChildBase::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
                                             const LayoutDevicePoint& aRefPoint,
                                             nsIWidget* aWidget)
 {
   MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
-             aMsg == NS_MOUSE_BUTTON_UP);
+             aMsg == NS_MOUSE_BUTTON_UP || aMsg == NS_MOUSE_MOZLONGTAP);
 
   WidgetMouseEvent event(true, aMsg, nullptr,
                          WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
   event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
   event.time = aTime;
   event.button = WidgetMouseEvent::eLeftButton;
   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
   if (aMsg != NS_MOUSE_MOVE) {
@@ -686,16 +686,17 @@ TabChild::TabChild(ContentChild* aManage
   , mAppPackageFileDescriptorRecved(false)
   , mLastBackgroundColor(NS_RGB(255, 255, 255))
   , mDidFakeShow(false)
   , mNotified(false)
   , mTriedBrowserInit(false)
   , mOrientation(eScreenOrientation_PortraitPrimary)
   , mUpdateHitRegion(false)
   , mContextMenuHandled(false)
+  , mLongTapEventHandled(false)
   , mWaitingTouchListeners(false)
   , mIgnoreKeyPressEvent(false)
   , mActiveElementManager(new ActiveElementManager())
   , mHasValidInnerSize(false)
 {
   if (!sActiveDurationMsSet) {
     Preferences::AddIntVarCache(&sActiveDurationMs,
                                 "ui.touch_activation.duration_ms",
@@ -1734,29 +1735,44 @@ TabChild::RecvHandleLongTap(const CSSPoi
   }
 
   mContextMenuHandled =
       DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
                          APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid),
                          2, 1, 0, false,
                          nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
 
-  SendContentReceivedTouch(aGuid, mContextMenuHandled);
+  // If no one handle context menu, fire MOZLONGTAP event
+  if (!mContextMenuHandled) {
+    LayoutDevicePoint currentPoint =
+      APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();
+    int time = 0;
+    nsEventStatus status =
+      DispatchSynthesizedMouseEvent(NS_MOUSE_MOZLONGTAP, time, currentPoint, mWidget);
+    mLongTapEventHandled = (status == nsEventStatus_eConsumeNoDefault);
+  }
+
+  SendContentReceivedTouch(aGuid, mContextMenuHandled || mLongTapEventHandled);
 
   return true;
 }
 
 bool
 TabChild::RecvHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
 {
   if (mContextMenuHandled) {
     mContextMenuHandled = false;
     return true;
   }
 
+  if (mLongTapEventHandled) {
+    mLongTapEventHandled = false;
+    return true;
+  }
+
   RecvHandleSingleTap(aPoint, aGuid);
   return true;
 }
 
 bool
 TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
                                    const APZStateChange& aChange,
                                    const int& aArg)
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -556,16 +556,17 @@ private:
         mCachedFileDescriptorInfos;
     nscolor mLastBackgroundColor;
     bool mDidFakeShow;
     bool mNotified;
     bool mTriedBrowserInit;
     ScreenOrientation mOrientation;
     bool mUpdateHitRegion;
     bool mContextMenuHandled;
+    bool mLongTapEventHandled;
     bool mWaitingTouchListeners;
     void FireSingleTapEvent(LayoutDevicePoint aPoint);
 
     bool mIgnoreKeyPressEvent;
     nsRefPtr<ActiveElementManager> mActiveElementManager;
     bool mHasValidInnerSize;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -56,16 +56,17 @@
 #include "PermissionMessageUtils.h"
 #include "StructuredCloneUtils.h"
 #include "ColorPickerParent.h"
 #include "JavaScriptParent.h"
 #include "FilePickerParent.h"
 #include "TabChild.h"
 #include "LoadContext.h"
 #include "nsNetCID.h"
+#include "gfxPrefs.h"
 #include <algorithm>
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::services;
 using namespace mozilla::widget;
@@ -1883,19 +1884,17 @@ TabParent::GetWidget() const
   nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
   return widget.forget();
 }
 
 bool
 TabParent::UseAsyncPanZoom()
 {
   bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
-  bool asyncPanZoomEnabled =
-    Preferences::GetBool("layers.async-pan-zoom.enabled", false);
-  return (usingOffMainThreadCompositing && asyncPanZoomEnabled &&
+  return (usingOffMainThreadCompositing && gfxPrefs::AsyncPanZoomEnabled() &&
           GetScrollingBehavior() == ASYNC_PAN_ZOOM);
 }
 
 nsEventStatus
 TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent,
                                           ScrollableLayerGuid* aOutTargetGuid)
 {
   if (RenderFrameParent* rfp = GetRenderFrame()) {
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -7,16 +7,21 @@
 if CONFIG['MOZ_WEBRTC']:
     DIRS += ['bridge']
 
     LOCAL_INCLUDES += [
         '/media/webrtc/signaling/src/common',
         '/media/webrtc/trunk',
     ]
 
+    if CONFIG['GNU_CXX']:
+        CXXFLAGS += [
+            '-Wno-unused-local-typedefs', # Workaround until we fix bug 1020661
+        ]
+
 TEST_DIRS += ['tests/mochitest', 'tests/ipc', 'tests/identity']
 
 XPIDL_SOURCES += [
     'nsIDOMMediaStream.idl',
     'nsIDOMNavigatorUserMedia.idl',
     'nsIMediaManager.idl',
 ]
 
--- a/dom/media/tests/identity/mochitest.ini
+++ b/dom/media/tests/identity/mochitest.ini
@@ -1,23 +1,19 @@
 [DEFAULT]
-skip-if = e10s
+# All tests are disabled on android&b2g due to lack of https support in
+# mochitests (Bug 907770)
+# Tests are also disabled on b2g due to lack of e10s support in WebRTC identity
+# (Bug 975144)
+skip-if = e10s || os == "android" || appname == "b2g"
 support-files =
   /.well-known/idp-proxy/idp.html
   /.well-known/idp-proxy/idp-proxy.js
   identityevent.js
 
-# All tests are disabled on android&b2g due to lack of https support in
-# mochitests (Bug 907770)
-# All tests are disabled on b2g due to lack of e10s support in WebRTC identity
-# (Bug 975144)
 [test_idpproxy.html]
-skip-if = os == "android" || appname == "b2g"
 [test_getIdentityAssertion.html]
-skip-if = os == "android" || appname == "b2g"
 [test_setIdentityProvider.html]
-skip-if = os == "android" || appname == "b2g"
 [test_setIdentityProviderWithErrors.html]
-skip-if = os == "android" || appname == "b2g"
 [test_peerConnection_peerIdentity.html]
-skip-if = os == "android" || appname == "b2g"
+
+# Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases
 [../mochitest/test_zmedia_cleanup.html]
-skip-if = os == "android" || appname == "b2g"
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -8,25 +8,25 @@ support-files =
   NetworkPreparationChromeScript.js
   blacksilence.js
   turnConfig.js
 
 [test_dataChannel_basicAudio.html]
 skip-if = toolkit == 'gonk' #Bug 962984 for debug, bug 963244 for opt
 [test_dataChannel_basicAudioVideo.html]
 # Disabled on OS X for bug 930481 timeouts
-skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_dataChannel_basicAudioVideoCombined.html]
 # Disabled on OS X for bug 930481 timeouts
-skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_dataChannel_basicDataOnly.html]
 [test_dataChannel_basicVideo.html]
 skip-if = toolkit=='gonk' # b2g emulator seems to bee too slow (Bug 1016498 and 1008080)
 [test_dataChannel_bug1013809.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_dataChannel_noOffer.html]
 [test_getUserMedia_basicAudio.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
 [test_getUserMedia_basicVideo.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
 [test_getUserMedia_basicVideoAudio.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure, turned an intermittent (bug 962579) into a permanant orange
 [test_getUserMedia_constraints.html]
@@ -46,40 +46,41 @@ skip-if = (toolkit == 'gonk' && debug) #
 [test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html]
 [test_getUserMedia_stopVideoStream.html]
 [test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
 [test_getUserMedia_peerIdentity.html]
 [test_peerConnection_addCandidateInHaveLocalOffer.html]
 [test_peerConnection_basicAudio.html]
 skip-if = (toolkit == 'gonk' && debug) #Bug 962984, test fail on b2g debug build
 [test_peerConnection_basicAudioVideo.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_basicAudioVideoCombined.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_basicVideo.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_bug822674.html]
 [test_peerConnection_bug825703.html]
 [test_peerConnection_bug827843.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_bug834153.html]
 [test_peerConnection_bug835370.html]
 skip-if = toolkit=='gonk' # b2g emulator seems to bee too slow (Bug 1016498 and 1008080)
 [test_peerConnection_bug1013809.html]
 [test_peerConnection_close.html]
 [test_peerConnection_errorCallbacks.html]
 [test_peerConnection_offerRequiresReceiveAudio.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_offerRequiresReceiveVideo.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_offerRequiresReceiveVideoAudio.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_setLocalAnswerInHaveLocalOffer.html]
 [test_peerConnection_setLocalAnswerInStable.html]
 [test_peerConnection_setLocalOfferInHaveRemoteOffer.html]
 [test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html]
 [test_peerConnection_setRemoteAnswerInStable.html]
 [test_peerConnection_setRemoteOfferInHaveLocalOffer.html]
 [test_peerConnection_throwInCallbacks.html]
-skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
+skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_toJSON.html]
-# Bug950317: Hack for making a cleanup hook after finishing all WebRTC cases
+
+# Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases
 [test_zmedia_cleanup.html]
--- a/dom/media/tests/mochitest/templates.js
+++ b/dom/media/tests/mochitest/templates.js
@@ -417,16 +417,72 @@ var commandsDataChannel = [
         function () {
         is(test.pcLocal.signalingState, STABLE,
            "signalingState after local setRemoteDescription is 'stable'");
         test.next();
       });
     }
   ],
   [
+    'PC_LOCAL_WAIT_FOR_ICE_CONNECTED',
+    function (test) {
+      var myTest = test;
+      var myPc = myTest.pcLocal;
+
+      function onIceConnectedSuccess () {
+        ok(true, "pc_local: ICE switched to 'connected' state");
+        myTest.next();
+      };
+      function onIceConnectedFailed () {
+        dumpSdp(myTest);
+        ok(false, "pc_local: ICE failed to switch to 'connected' state: " + myPc.iceConnectionState);
+        myTest.next();
+      };
+
+      if (myPc.isIceConnected()) {
+        ok(true, "pc_local: ICE is in connected state");
+        myTest.next();
+      } else if (myPc.isIceConnectionPending()) {
+        myPc.waitForIceConnected(onIceConnectedSuccess, onIceConnectedFailed);
+      } else {
+        dumpSdp(myTest);
+        ok(false, "pc_local: ICE is already in bad state: " + myPc.iceConnectionState);
+        myTest.next();
+      }
+    }
+  ],
+  [
+    'PC_REMOTE_WAIT_FOR_ICE_CONNECTED',
+    function (test) {
+      var myTest = test;
+      var myPc = myTest.pcRemote;
+
+      function onIceConnectedSuccess () {
+        ok(true, "pc_remote: ICE switched to 'connected' state");
+        myTest.next();
+      };
+      function onIceConnectedFailed () {
+        dumpSdp(myTest);
+        ok(false, "pc_remote: ICE failed to switch to 'connected' state: " + myPc.iceConnectionState);
+        myTest.next();
+      };
+
+      if (myPc.isIceConnected()) {
+        ok(true, "pc_remote: ICE is in connected state");
+        myTest.next();
+      } else if (myPc.isIceConnectionPending()) {
+        myPc.waitForIceConnected(onIceConnectedSuccess, onIceConnectedFailed);
+      } else {
+        dumpSdp(myTest);
+        ok(false, "pc_remote: ICE is already in bad state: " + myPc.iceConnectionState);
+        myTest.next();
+      }
+    }
+  ],
+  [
     'PC_LOCAL_VERIFY_DATA_CHANNEL_STATE',
     function (test) {
       test.waitForInitialDataChannel(test.pcLocal, function() {
         test.next();
       }, function() {
         ok(false, test.pcLocal + " initial dataChannels[0] failed to switch to 'open'");
         unexpectedEventAndFinish(this, 'timeout')
       });
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 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/dom/Promise.h"
 
 #include "jsfriendapi.h"
+#include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/OwningNonNull.h"
 #include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/Preferences.h"
 #include "PromiseCallback.h"
 #include "PromiseNativeHandler.h"
 #include "PromiseWorkerProxy.h"
 #include "nsContentUtils.h"
@@ -1202,19 +1203,21 @@ Promise::RunResolveTask(JS::Handle<JS::V
       !mHadRejectCallback &&
       !NS_IsMainThread()) {
     WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(worker);
     worker->AssertIsOnWorkerThread();
 
     mFeature = new PromiseReportRejectFeature(this);
     if (NS_WARN_IF(!worker->AddFeature(worker->GetJSContext(), mFeature))) {
+      // To avoid a false RemoveFeature().
+      mFeature = nullptr;
       // Worker is shutting down, report rejection immediately since it is
       // unlikely that reject callbacks will be added after this point.
-      MaybeReportRejected();
+      MaybeReportRejectedOnce();
     }
   }
 
   RunTask();
 }
 
 void
 Promise::RemoveFeature()
@@ -1426,10 +1429,20 @@ PromiseWorkerProxy::CleanUp(JSContext* a
   // Release the Promise and remove the PromiseWorkerProxy from the features of
   // the worker thread since the Promise has been resolved/rejected or the
   // worker thread has been cancelled.
   mWorkerPromise = nullptr;
   mWorkerPrivate->RemoveFeature(aCx, this);
   mCleanedUp = true;
 }
 
+// Specializations of MaybeRejectBrokenly we actually support.
+template<>
+void Promise::MaybeRejectBrokenly(const nsRefPtr<DOMError>& aArg) {
+  MaybeSomething(aArg, &Promise::MaybeReject);
+}
+template<>
+void Promise::MaybeRejectBrokenly(const nsAString& aArg) {
+  MaybeSomething(aArg, &Promise::MaybeReject);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -21,16 +21,17 @@
 #include "mozilla/dom/workers/bindings/WorkerFeature.h"
 
 class nsIGlobalObject;
 
 namespace mozilla {
 namespace dom {
 
 class AnyCallback;
+class DOMError;
 class PromiseCallback;
 class PromiseInit;
 class PromiseNativeHandler;
 
 class Promise;
 class PromiseReportRejectFeature : public workers::WorkerFeature
 {
   // The Promise that owns this feature.
@@ -84,21 +85,31 @@ public:
   // Most DOM objects are handled already.  To add a new type T, add a
   // ToJSValue overload in ToJSValue.h.
   // aArg is a const reference so we can pass rvalues like integer constants
   template <typename T>
   void MaybeResolve(const T& aArg) {
     MaybeSomething(aArg, &Promise::MaybeResolve);
   }
 
-  // aArg is a const reference so we can pass rvalues like NS_ERROR_*
-  template <typename T>
-  void MaybeReject(const T& aArg) {
+  inline void MaybeReject(nsresult aArg) {
+    MOZ_ASSERT(NS_FAILED(aArg));
     MaybeSomething(aArg, &Promise::MaybeReject);
   }
+  // DO NOT USE MaybeRejectBrokenly with in new code.  Promises should be
+  // rejected with Error instances.
+  // Note: MaybeRejectBrokenly is a template so we can use it with DOMError
+  // without instantiating the DOMError specialization of MaybeSomething in
+  // every translation unit that includes this header, because that would
+  // require use to include DOMError.h either here or in all those translation
+  // units.
+  template<typename T>
+  void MaybeRejectBrokenly(const T& aArg); // Not implemented by default; see
+                                           // specializations in the .cpp for
+                                           // the T values we support.
 
   // WebIDL
 
   nsIGlobalObject* GetParentObject() const
   {
     return mGlobal;
   }
 
--- a/dom/push/src/PushService.jsm
+++ b/dom/push/src/PushService.jsm
@@ -1489,20 +1489,23 @@ this.PushService = {
         // In Multi-sim, there is more than one client in iccProvider. Each
         // client represents a icc service. To maintain backward compatibility
         // with single sim, we always use client 0 for now. Adding support
         // for multiple sim will be addressed in bug 927721, if needed.
         let clientId = 0;
         let iccInfo = icc.getIccInfo(clientId);
         if (iccInfo) {
           debug("Running on mobile data");
+          let ips = {};
+          let prefixLengths = {};
+          nm.active.getAddresses(ips, prefixLengths);
           return {
             mcc: iccInfo.mcc,
             mnc: iccInfo.mnc,
-            ip:  nm.active.ip
+            ip:  ips.value[0]
           }
         }
       }
     } catch (e) {}
 
     debug("Running on wifi");
 
     return {
--- a/dom/src/offline/nsDOMOfflineResourceList.cpp
+++ b/dom/src/offline/nsDOMOfflineResourceList.cpp
@@ -8,17 +8,16 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsError.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "nsIPrefetchService.h"
 #include "nsCPrefetchService.h"
 #include "nsNetUtil.h"
 #include "nsNetCID.h"
 #include "nsICacheSession.h"
-#include "nsICacheService.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsAutoPtr.h"
 #include "nsContentUtils.h"
 #include "nsIObserverService.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIWebNavigation.h"
 #include "mozilla/dom/OfflineResourceListBinding.h"
 #include "mozilla/EventDispatcher.h"
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -71,17 +71,17 @@ public:
     MOZ_ASSERT(mTelephony);
   }
 
   virtual ~Callback() {}
 
   NS_IMETHODIMP
   NotifyDialError(const nsAString& aError)
   {
-    mPromise->MaybeReject(aError);
+    mPromise->MaybeRejectBrokenly(aError);
     return NS_OK;
   }
 
   NS_IMETHODIMP
   NotifyDialSuccess(uint32_t aCallIndex)
   {
     nsRefPtr<TelephonyCall> call =
       mTelephony->CreateNewDialingCall(mServiceId, mNumber, aCallIndex);
@@ -250,31 +250,31 @@ Telephony::DialInternal(uint32_t aServic
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   if (!global) {
     return nullptr;
   }
 
   nsRefPtr<Promise> promise = new Promise(global);
 
   if (!IsValidNumber(aNumber) || !IsValidServiceId(aServiceId)) {
-    promise->MaybeReject(NS_LITERAL_STRING("InvalidAccessError"));
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return promise.forget();
   }
 
   // We only support one outgoing call at a time.
   if (HasDialingCall()) {
-    promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback =
     new Callback(this, promise, aServiceId, aNumber);
   nsresult rv = mService->Dial(aServiceId, aNumber, aIsEmergency, callback);
   if (NS_FAILED(rv)) {
-    promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   return promise.forget();
 }
 
 already_AddRefed<TelephonyCall>
 Telephony::CreateNewDialingCall(uint32_t aServiceId, const nsAString& aNumber,
--- a/dom/tests/mochitest/ajax/offline/offlineTests.js
+++ b/dom/tests/mochitest/ajax/offline/offlineTests.js
@@ -1,13 +1,14 @@
 // Utility functions for offline tests.
 var Cc = SpecialPowers.Cc;
 var Ci = SpecialPowers.Ci;
 var Cu = SpecialPowers.Cu;
 var LoadContextInfo = Cu.import("resource://gre/modules/LoadContextInfo.jsm", {}).LoadContextInfo;
+var CommonUtils = Cu.import("resource://services-common/utils.js", {}).CommonUtils;
 
 const kNetBase = 2152398848; // 0x804B0000
 var NS_ERROR_CACHE_KEY_NOT_FOUND = kNetBase + 61;
 var NS_ERROR_CACHE_KEY_WAIT_FOR_VALIDATION = kNetBase + 64;
 
 // Reading the contents of multiple cache entries asynchronously
 function OfflineCacheContents(urls) {
   this.urls = urls;
@@ -17,23 +18,24 @@ function OfflineCacheContents(urls) {
 OfflineCacheContents.prototype = {
 QueryInterface: function(iid) {
     if (!iid.equals(Ci.nsISupports) &&
         !iid.equals(Ci.nsICacheListener)) {
       throw Cr.NS_ERROR_NO_INTERFACE;
     }
     return this;
   },
-onCacheEntryAvailable: function(desc, accessGranted, status) {
+onCacheEntryCheck: function() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; },
+onCacheEntryAvailable: function(desc, isnew, applicationCache, status) {
     if (!desc) {
       this.fetch(this.callback);
       return;
     }
 
-    var stream = desc.QueryInterface(Ci.nsICacheEntryDescriptor).openInputStream(0);
+    var stream = desc.openInputStream(0);
     var sstream = Cc["@mozilla.org/scriptableinputstream;1"]
                  .createInstance(SpecialPowers.Ci.nsIScriptableInputStream);
     sstream.init(stream);
     this.contents[desc.key] = sstream.read(sstream.available());
     sstream.close();
     desc.close();
     this.fetch(this.callback);
   },
@@ -44,18 +46,18 @@ fetch: function(callback)
   if (this.urls.length == 0) {
     callback(this.contents);
     return;
   }
 
   var url = this.urls.shift();
   var self = this;
 
-  var cacheSession = OfflineTest.getActiveSession();
-  cacheSession.asyncOpenCacheEntry(url, Ci.nsICache.ACCESS_READ, this);
+  var cacheStorage = OfflineTest.getActiveStorage();
+  cacheStorage.asyncOpenURI(CommonUtils.makeURI(url), "", Ci.nsICacheStorage.OPEN_READONLY, this);
 }
 };
 
 var OfflineTest = {
 
 _allowedByDefault: false,
 
 _hasSlave: false,
@@ -250,37 +252,36 @@ failEvent: function(e)
 
 // The offline API as specified has no way to watch the load of a resource
 // added with applicationCache.mozAdd().
 waitForAdd: function(url, onFinished) {
   // Check every half second for ten seconds.
   var numChecks = 20;
 
   var waitForAddListener = {
-    onCacheEntryAvailable: function(entry, access, status) {
+    onCacheEntryCheck: function() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; },
+    onCacheEntryAvailable: function(entry, isnew, applicationCache, status) {
       if (entry) {
         entry.close();
         onFinished();
         return;
       }
 
       if (--numChecks == 0) {
         onFinished();
         return;
       }
 
       setTimeout(OfflineTest.priv(waitFunc), 500);
     }
   };
 
   var waitFunc = function() {
-    var cacheSession = OfflineTest.getActiveSession();
-    cacheSession.asyncOpenCacheEntry(url,
-                                     Ci.nsICache.ACCESS_READ,
-                                     waitForAddListener);
+    var cacheStorage = OfflineTest.getActiveStorage();
+    cacheStorage.asyncOpenURI(CommonUtils.makeURI(url), "", Ci.nsICacheStorage.OPEN_READONLY, waitForAddListener);
   }
 
   setTimeout(this.priv(waitFunc), 500);
 },
 
 manifestURL: function(overload)
 {
   var manifestURLspec;
@@ -322,28 +323,26 @@ getActiveCache: function(overload)
   // Note that this is the current active cache in the cache stack, not the
   // one associated with this window.
   var serv = Cc["@mozilla.org/network/application-cache-service;1"]
              .getService(Ci.nsIApplicationCacheService);
   var groupID = serv.buildGroupID(this.manifestURL(overload), this.loadContextInfo());
   return serv.getActiveCache(groupID);
 },
 
-getActiveSession: function()
+getActiveStorage: function()
 {
   var cache = this.getActiveCache();
   if (!cache) {
     return null;
   }
 
-  var cacheService = Cc["@mozilla.org/network/cache-service;1"]
-                     .getService(Ci.nsICacheService);
-  return cacheService.createSession(cache.clientID,
-                                    Ci.nsICache.STORE_OFFLINE,
-                                    true);
+  var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+                     .getService(Ci.nsICacheStorageService);
+  return cacheService.appCacheStorage(LoadContextInfo.default, cache);
 },
 
 priv: function(func)
 {
   var self = this;
   return function() {
     func(arguments);
   }
@@ -360,34 +359,35 @@ checkCacheEntries: function(entries, cal
     }
   }
 
   checkNextEntry();
 },
 
 checkCache: function(url, expectEntry, callback)
 {
-  var cacheSession = this.getActiveSession();
-  this._checkCache(cacheSession, url, expectEntry, callback);
+  var cacheStorage = this.getActiveStorage();
+  this._checkCache(cacheStorage, url, expectEntry, callback);
 },
 
-_checkCache: function(cacheSession, url, expectEntry, callback)
+_checkCache: function(cacheStorage, url, expectEntry, callback)
 {
-  if (!cacheSession) {
+  if (!cacheStorage) {
     if (expectEntry) {
       this.ok(false, url + " should exist in the offline cache (no session)");
     } else {
       this.ok(true, url + " should not exist in the offline cache (no session)");
     }
     if (callback) setTimeout(this.priv(callback), 0);
     return;
   }
 
   var _checkCacheListener = {
-    onCacheEntryAvailable: function(entry, access, status) {
+    onCacheEntryCheck: function() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; },
+    onCacheEntryAvailable: function(entry, isnew, applicationCache, status) {
       if (entry) {
         if (expectEntry) {
           OfflineTest.ok(true, url + " should exist in the offline cache");
         } else {
           OfflineTest.ok(false, url + " should not exist in the offline cache");
         }
         entry.close();
       } else {
@@ -407,20 +407,17 @@ checkCache: function(url, expectEntry, c
         } else {
           OfflineTest.ok(false, "got invalid error for " + url);
         }
       }
       if (callback) setTimeout(OfflineTest.priv(callback), 0);
     }
   };
 
-  cacheSession.asyncOpenCacheEntry(url,
-                                   Ci.nsICache.ACCESS_READ,
-                                   _checkCacheListener,
-                                   false);
+  cacheStorage.asyncOpenURI(CommonUtils.makeURI(url), "", Ci.nsICacheStorage.OPEN_READONLY, _checkCacheListener);
 },
 
 setSJSState: function(sjsPath, stateQuery)
 {
   var client = new XMLHttpRequest();
   client.open("GET", sjsPath + "?state=" + stateQuery, false);
 
   var appcachechannel = SpecialPowers.wrap(client).channel.QueryInterface(Ci.nsIApplicationCacheChannel);
--- a/dom/tests/mochitest/notification/test_notification_resend.html
+++ b/dom/tests/mochitest/notification/test_notification_resend.html
@@ -150,17 +150,17 @@
         is(notif.text, "Body", "Notification body is valid: " + notif.text);
         is(notif.manifestURL, manifestURL, "Notification manifest URL is valid: " + notif.manifestURL);
         is(notif.imageURL, "icon.jpg", "Notification icon URL is valid: " + notif.imageURL);
         is(notif.lang, "en-US", "Notification lang is valid: " + notif.lang);
         is(notif.id, notif.manifestURL + "#tag:" + notif.tag, "Notification id is valid: " + notif.id);
         ok(notif.dbId.match(uuidRegEx), "Notification dbId is valid: " + notif.dbId);
         is(notif.dir, "ltr", "Notification dir is valid: " + notif.dir);
         is(notif.tag, "fakeTag", "Notification tag is valid: " + notif.tag);
-        ok((notif.timestamp > now), "Notification timestamp is valid: " + notif.timestamp);
+        ok((notif.timestamp >= now), "Notification timestamp is valid: (" + notif.timestamp + " >= " + now + ")");
         notif2.close();
       });
     }
   ];
 
   MockServices.register();
   NotificationTest.run(steps, function () {
     MockServices.unregister();
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -1,24 +1,26 @@
 [DEFAULT]
 support-files =
   inert_style.css
 
 [test_bug900724.html]
+[test_bug1017896.html]
 [test_content_element.html]
 [test_nested_content_element.html]
 [test_dest_insertion_points.html]
 [test_dest_insertion_points_shadow.html]
 [test_fallback_dest_insertion_points.html]
 [test_dynamic_content_element_matching.html]
 [test_document_register.html]
 [test_document_register_base_queue.html]
 [test_document_register_lifecycle.html]
 [test_document_register_parser.html]
 [test_document_register_stack.html]
 [test_document_shared_registry.html]
 [test_template.html]
+[test_template_xhtml.html]
 [test_shadowroot.html]
 [test_shadowroot_inert_element.html]
 [test_shadowroot_style.html]
 [test_shadowroot_style_multiple_shadow.html]
 [test_shadowroot_style_order.html]
 [test_style_fallback_content.html]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_bug1017896.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1017896
+-->
+<head>
+  <title>Test template element in stale document.</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017896">Bug 1017896</a>
+<div id="container"></div>
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+var frame = document.createElement("iframe");
+document.getElementById("container").appendChild(frame);
+
+var staleFrameDoc = frame.contentDocument;
+
+setTimeout(function() {
+  var v = staleFrameDoc.createElement("div");
+  v.innerHTML = "<template>Content</template>";
+  is(v.firstChild.content.childNodes.length, 1, "Template should have one child in template content.");
+  SimpleTest.finish();
+}, 0);
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_template_xhtml.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1011831
+-->
+<head>
+  <title>Test for template element</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1011831">Bug 1011831</a>
+<script>
+var docSrc =
+  '<!DOCTYPE html>' +
+  '<html xmlns="http://www.w3.org/1999/xhtml">' +
+    '<body>' +
+      '<template id="t">Content<span>Content</span></template>' +
+      '<div id="container"><template>One</template><div>Two</div></div>' +
+      '<template id="t2"></template>' +
+    '</body>' +
+  '</html>';
+
+var doc = (new DOMParser()).parseFromString(docSrc, 'application/xhtml+xml');
+
+var t = doc.getElementById("t");
+is(t.childNodes.length, 0, "Template should have no children.");
+is(t.content.childNodes.length, 2, "Template content should have two children, text node and a span.");
+
+// Test serialization of template element.
+is(t.innerHTML, 'Content<span xmlns="http://www.w3.org/1999/xhtml">Content</span>', "Template contents should be serialized.");
+is(t.outerHTML, '<template xmlns="http://www.w3.org/1999/xhtml" id="t">Content<span>Content</span></template>', "Template contents should be serialized.");
+
+var c = doc.getElementById("container");
+is(c.innerHTML, '<template xmlns="http://www.w3.org/1999/xhtml">One</template><div xmlns="http://www.w3.org/1999/xhtml">Two</div>', "Template contents should be serialized.");
+is(c.outerHTML, '<div xmlns="http://www.w3.org/1999/xhtml" id="container"><template>One</template><div>Two</div></div>', "Template contents should be serialized.");
+
+// Test setting innerHTML on template element.
+var t2 = doc.getElementById("t2");
+t2.innerHTML = 'Three<span>Four</span>';
+is(t2.childNodes.length, 0, "Setting innerHTML should append children into template content.");
+is(t2.content.childNodes.length, 2, "Setting innerHTML should append children into template content.");
+
+</script>
+</body>
+</html>
--- a/dom/webidl/AudioNode.webidl
+++ b/dom/webidl/AudioNode.webidl
@@ -38,8 +38,14 @@ interface AudioNode : EventTarget {
     [SetterThrows]
     attribute unsigned long channelCount;
     [SetterThrows]
     attribute ChannelCountMode channelCountMode;
     attribute ChannelInterpretation channelInterpretation;
 
 };
 
+// Mozilla extension
+partial interface AudioNode {
+  [ChromeOnly]
+  readonly attribute unsigned long id;
+};
+
--- a/dom/webidl/CSS.webidl
+++ b/dom/webidl/CSS.webidl
@@ -5,22 +5,21 @@
  *
  * The origin of this IDL file is
  * http://dev.w3.org/csswg/css3-conditional/
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-[Pref="layout.css.supports-rule.enabled"]
 interface CSS {
-  [Throws, Pref="layout.css.supports-rule.enabled"]
+  [Throws]
   static boolean supports(DOMString property, DOMString value);
 
-  [Throws, Pref="layout.css.supports-rule.enabled"]
+  [Throws]
   static boolean supports(DOMString conditionText);
 };
 
 // http://dev.w3.org/csswg/cssom/#the-css.escape%28%29-method
 partial interface CSS {
   [Throws]
   static DOMString escape(DOMString ident);
 };
--- a/dom/webidl/HTMLLinkElement.webidl
+++ b/dom/webidl/HTMLLinkElement.webidl
@@ -39,11 +39,12 @@ partial interface HTMLLinkElement {
   [SetterThrows, Pure]
            attribute DOMString rev;
   [SetterThrows, Pure]
            attribute DOMString target;
 };
 
 // http://w3c.github.io/webcomponents/spec/imports/#interface-import
 partial interface HTMLLinkElement {
+    [Pref="dom.webcomponents.enabled"]
     readonly attribute Document? import;
 };
 
--- a/dom/webidl/MessageChannel.webidl
+++ b/dom/webidl/MessageChannel.webidl
@@ -2,13 +2,13 @@
 /* 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/.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
  */
 
-[Constructor, Pref="dom.messageChannel.enabled"]
+[Constructor, Func="MessageChannel::Enabled"]
 interface MessageChannel {
   readonly attribute MessagePort port1;
   readonly attribute MessagePort port2;
 };
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -280,16 +280,18 @@ partial interface Window {
   /**
    * Method for sizing this window to the content in the window.
    */
   [Throws] void             sizeToContent();
 
   // XXX Shouldn't this be in nsIDOMChromeWindow?
   [ChromeOnly, Replaceable, Throws] readonly attribute MozControllers controllers;
 
+  [ChromeOnly, Throws] readonly attribute Element? realFrameElement;
+
   [Throws] readonly attribute float               mozInnerScreenX;
   [Throws] readonly attribute float               mozInnerScreenY;
   [Throws] readonly attribute float               devicePixelRatio;
 
   /* The maximum offset that the window can be scrolled to
      (i.e., the document width/height minus the scrollport width/height) */
   [Replaceable, Throws] readonly attribute long   scrollMaxX;
   [Replaceable, Throws] readonly attribute long   scrollMaxY;
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/bug1020226_frame.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1020226
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1020226</title>
+</head>
+<body>
+
+<script type="application/javascript">
+  var worker = new Worker("bug1020226_worker.js");
+  worker.onmessage = function(e) {
+    window.parent.postMessage("loaded", "*");
+  }
+</script>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/bug1020226_worker.js
@@ -0,0 +1,11 @@
+var p = new Promise(function(resolve, reject) {
+  // This causes a runnable to be queued.
+  reject(new Error());
+  postMessage("loaded");
+
+  // This prevents that runnable from running until the window calls terminate(),
+  // at which point the worker goes into the Canceling state and then an
+  // AddFeature() is attempted, which fails, which used to result in multiple
+  // calls to the error reporter, one after the worker's context had been GCed.
+  while (true);
+});
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -1,12 +1,14 @@
 [DEFAULT]
 support-files =
   WorkerTest_badworker.js
   atob_worker.js
+  bug1020226_worker.js
+  bug1020226_frame.html
   clearTimeouts_worker.js
   closeOnGC_server.sjs
   closeOnGC_worker.js
   close_worker.js
   content_worker.js
   console_worker.js
   consoleReplaceable_worker.js
   csp_worker.js
@@ -73,16 +75,17 @@ support-files =
   subdir/relativeLoad_sub_import.js
 
 [test_404.html]
 [test_atob.html]
 [test_blobConstructor.html]
 [test_blobWorkers.html]
 [test_bug949946.html]
 [test_bug1010784.html]
+[test_bug1020226.html]
 [test_chromeWorker.html]
 [test_clearTimeouts.html]
 [test_close.html]
 [test_closeOnGC.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #bug 881404 # b2g-debug(times out) b2g-desktop(times out)
 [test_console.html]
 [test_consoleReplaceable.html]
 [test_contentWorker.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_bug1020226.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1020226
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1020226</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020226">Mozilla Bug 1020226</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<iframe id="iframe" src="bug1020226_frame.html" onload="finishTest();">
+</iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+function finishTest() {
+  document.getElementById("iframe").onload = null;
+  window.onmessage = function(e) {
+    info("Got message");
+    document.getElementById("iframe").src = "about:blank";
+    // We aren't really interested in the test, it shouldn't crash when the
+    // worker is GCed later.
+    ok(true, "Should not crash");
+    SimpleTest.finish();
+  };
+}
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
--- a/editor/composer/src/moz.build
+++ b/editor/composer/src/moz.build
@@ -34,12 +34,24 @@ RESOURCE_FILES += [
     'res/table-add-row-before-hover.gif',
     'res/table-add-row-before.gif',
     'res/table-remove-column-active.gif',
     'res/table-remove-column-hover.gif',
     'res/table-remove-column.gif',
     'res/table-remove-row-active.gif',
     'res/table-remove-row-hover.gif',
     'res/table-remove-row.gif',
+    'res/text_caret.png',
+    'res/text_caret@1.5x.png',
+    'res/text_caret@2.25x.png',
+    'res/text_caret@2x.png',
+    'res/text_caret_tilt_left.png',
+    'res/text_caret_tilt_left@1.5x.png',
+    'res/text_caret_tilt_left@2.25x.png',
+    'res/text_caret_tilt_left@2x.png',
+    'res/text_caret_tilt_right.png',
+    'res/text_caret_tilt_right@1.5x.png',
+    'res/text_caret_tilt_right@2.25x.png',
+    'res/text_caret_tilt_right@2x.png',
     'res/text_selection_handle.png',
     'res/text_selection_handle@1.5.png',
     'res/text_selection_handle@2.png',
 ]
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..167cb6526ce7b354b9a395df1c8b2d9e99918f30
GIT binary patch
literal 1652
zc%17D@N?(olHy`uVBq!ia0vp^qChOg!3HEF9L1f1lw^r(L`iUdT1k0gQ7VIDN`6wR
zf@f}GdTLN=VoGJ<$y6H#24<Dakcg59UmvUF{9L_6kQ%*;+yVv=u(7WwNKDR7Em25H
zP0!4;ReHaBzmh^`img((sjq==fpcm`rbks#YH*cbNODznvSo^ry`6$hg%!|%+|-gp
zg^Jvqyke^gTP3i$RzNmLSYJs2tfVB{Rte&$2;Tq&=lr5n1yem^-DCqpLj^N4Jwp>y
zGc!XS1tSAPBYguPGSf9Qu`)HYGBQ_y0wthrMJZ`kK`w4kyMR1frHqo20xNy}^73-M
za$~*xqI7*jOG`_T8Ae9BKoz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^Yauy{KTaE(h^%G
zC72g-3*g4)6+?pw7-0Gpi3R$GdItJP3VnU?E6vS?t1d1HN=?JBx;Uh=AXPsowK%`D
zC>a=WY04nY1y;^Qsfi`|MIrh5Ij~R+$jC3rFV4s>P;d@5Q_%2DOwP;$321_K`1)FT
z<`tJD<|U_ky4WfKMf5T=Q><K!Ok9jD-JD%449pD;U5zcBO$=R44S_r(Q&S^HSD0Rx
z{N&Qy)Vvay-V}sh7o2)Qi2<TJwJ5VJHN~wcKUV?lX{$`!ZgIrz7Kq*y+-`BgsaGH9
z7=5&;h6w@F4~Pj*xIhj(>8Iua(|ZvxVNdLmN?~ANdgkfk7*cU7=}PR+8I1xvWb{ri
z+52MIyUCeH!=G?1|L;2aaKL$&p2n=&-?1}q?9}r(c2$+>=b4r-0wy9H77;&MPCN3X
z<?X9cIO;iZp+dNp>6*gCXQCwx+Rq+b3w(QXvd@XFJ{3GEQ@nDfJqWorpW}(qp(8h!
zPLY1noxZy9N#V;>F@D`cS|9&k=Z_OSf27n$Cg#_PM?F41GHVtY<;h&q%Fdg<vsU%g
zQU&oEtF6vHIu`Zp!s`99VZJ#stNw`HV{dR=-1LTfO<U8UfUV{0IoD789GUPV@*%gm
zTUeQ?Ug>1vSCjj8ES`P1C1-)xZL#Ds&!uyFbk-QTEa6HBFyP+Ud2$`Qnk9eA<_A2E
z?E!Xtmc6MxXLOo)mN2-f@tJY9x*EN_yJ^FMgr;4STy-?;*<YxNvKcX4P&{Pw>zk>A
zn)W8|oe?ZYCP`{A=rApMxTnp}DZyFs<wno$&bh&jLe7oro{E0+VOlDdHo<%5O%;)?
zk}DV*Zc3!^X`cuXO9&EQ(6*50|G$roXP6~V{rLTL^7bnRpU*!pe}C{LW6Hnh-tF%j
zi`163{i`XGPB~{kVPU=9+*|+NeE&UtyXL2#-}Uq3*UqgFJn@IOOjDr#XHD7nC@-GB
zMQ?vRtGC}@%V0T)Gh%MTp1(g|zByHDKmY!Im#~PsioZWzewoDT@XUS2cgF|p0`|36
zrr-PW{O{`JOC)}Lf4%&>f7+BQ%*vc1^X@;e<a!YmkoxW2@x`yj-<h$9|E(x_tYpac
zuj=QEcg=k}CY^u&U6#4%euGSJkjMV0%luro^XvE5{P>gi{ZVmGkI(x^mZPl^6+c)d
zB_st?pZ)*;zkYw^uNQ|OZhb9Rrsl)2={&RRe1}@@ld&g4O}2C~h;l8k(P2HbM(NU|
zJ#2hjXKa}6?7wgG`^VpVOP|}%zgx>Ug*h=Gpz+cV|0gOZJJ#N756h8pIKzB&fz%Yq
zSGE(n9j=}bSNO-r71mSK5Mas3Tb`!zmp|)-ea%c(g#!!+KmK{XUNcS}R1bK%`njxg
HN@xNA6J~-V
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8b2ec905aae4474fb2507831b0774ba1d6900bca
GIT binary patch
literal 1930
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dae08f27565737d34420b9962cc1031e1e5e6936
GIT binary patch
literal 2468
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
G6Z1DA8zXN3
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f3151a37a7910a5a2c630ac447c1ce7df03f5d50
GIT binary patch
literal 2524
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9250b816288d13725a21da76d8c99f72d6f0c47a
GIT binary patch
literal 1567
zc%17D@N?(olHy`uVBq!ia0vp^Vn8g#!3HEZm#uLCQj#UE5hcO-X(i=}MX3yqDfvmM
z3ZA)%>8U}fi7AzZCsS=07?@QuLn2Bde0{8v^K<nQL2C3Watjzhz{b9!ATc>RwL~E)
zH9a%WR_Xoj{Yna%DYi=CroINg1<t7%nI2U|slio#A<0$Q$(AWf_I3(36;?n4a#KqZ
z6)JLb@`|l0Y?Z*~S^?Q0VSOb9u#%E&TP292B76fBob!uP6-@Pvb(0MY4HeAH^bAc*
z&CCpS6pRcEjr0wG$V}JJ#LCpn%E(*+3Y37h6{VzE1-ZCE?E>;_l`=|73as??%gf94
z%8m8%i_-NCEiElUW*8ai0#)c1SLT%@R_NvxE5l51Ni9w;$}A|!%+FH*@e`BsOG|8(
zlwe-SEr1)FR}2j%V1VgYBo^o!>KW)GDfIQluQWFouDZA+C^Zeg>f(^ff>iyW)Z+Zo
zqGVvir743n7g#wLr6!i-7lq{K=fFZSAS1sdzc?emK*2fKOhLmpF*!32B%le_;p=PV
znO9trn3tUD>0+w{6w%AfOtEsaFf}x@urPJ8FfcbXbTzhgHZgQHH3agEOihg(U154%
z@{>z*Q}aq-dQ%X3&2Z`kB?gG@)S}F?)D*X({9FaFr>!z^yTur{TOfK<aJ$6>r(S)a
zWAxFY8YToxKOiPN;Q~4Eq@S7xOz%a&gq^bQxc~zL(?m}f$B>F!NmpWj&S(@Wu#6Eq
zmU3lIap0r>>*veorOf=BpyZ_d`2F_tOaIr@rT_W<x%#Yp|GMJlBMwFDuYEDj^s!#L
z%JR3<rf-X)XGd1B$Qu?Glrt`kh$xU;c5S!+w9tr6G3hsJ<=xW6EN93VuUBY(*X4d+
z;@|(@x?(X0P98XMqHWFh(@&kJH;PDei#bPbc^0FU^h_{=CF{|FSG;a+dJ2t-f8Iae
z-tWImbS|S|<OQD8tFy{WrHswvxhx<4{e5<`_W!!NdiIomNls-ek8PPO`b3J0sorki
zKISF+7(d3VMa=M0H9NVPqbodMl2gOFTFxTf4&Guz?fDzC?UaR$#a%P|Cvv8|h)-#@
zY@GP?tb=00vqw)GH_mi8cp&?M#-Sr87kg|xXv1V=aJ-4bO)u2hlP%|E`;`d^sp3pC
z`OSa4K6^P{Vg<v$|3CkV-#q$%e~i_ipa0*-i%9=_{`Yjd!siEU&67^7pU!_iFzdr~
z?{>cCPn<Ur5?-<y{rJ7y*xEek$*ul;xqVUgl23NbKXLNy>+Yv>tLyFdm(RQNpmuxt
zPaTE7eD9K0u$-7C-v7%e>VMteA8jGQ_VE@QUOqjw?ybW!_W-sQX&xRvf#=K{*6jUJ
z;Z<jPA^Lo0@$>)x=bw9b@5ch$ZTu&guS(p1D9Pd}sbOvRyC(1b!P}{MKjr;%?*4dx
zy+41)85Xy1bJIU(N6VL~er4LZ-GQ%pr`Vij6IZKcoMq5zKH3n`H*<Ep-wD-QGrZ46
z$j(^J((v-j_xI-h@ii8^KI#~-#<cJH#A(9uZ$XOK7c2fO3ytp$pY}3{d}cDVzT$d+
z0oz{oNB$0fm~Sq%;C0)~lESEcB_J(h)_-2!ZTA-}=?a<I$0VaFYoK}QNJ0YxGsFK>
VUd7;d6Ieh+wx_F~%Q~loCIGsqS%Lrn
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9837cbd0feb5350f07f24bc902ef24c879058555
GIT binary patch
literal 2004
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
a0K?kn&*!Yl%3c7fXFXm0T-G@yGywq9?kt%A
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a76c610008827d78cd01f125f2e8438309f366d7
GIT binary patch
literal 2322
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
Uaf0mC>W_aZ94|js88bZXKa%&mG5`Po
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5ca79fc8738617127e44d306b42dfb692d19a8b2
GIT binary patch
literal 2411
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
K)ap$;)Bgh#FXoW|
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..965c749d2c36377e448a7729862ea1037228038c
GIT binary patch
literal 1565
zc%17D@N?(olHy`uVBq!ia0vp^Vn8g#!3HEZm#uLCQj#UE5hcO-X(i=}MX3yqDfvmM
z3ZA)%>8U}fi7AzZCsS=07?@QuLn2Bde0{8v^K<nQL2C3Watjzhz{b9!ATc>RwL~E)
zH9a%WR_Xoj{Yna%DYi=CroINg1<t7%nI2U|slio#A<0$Q$(AWf_I3(36;?n4a#KqZ
z6)JLb@`|l0Y?Z*~S^?Q0VSOb9u#%E&TP292B76fBob!uP6-@Pvb(0MY4HeAH^bAc*
z&CCpS6pRcEjr0wG$V}JJ#LCpn%E(*+3Y37h6{VzE1-ZCE?E>;_l`=|73as??%gf94
z%8m8%i_-NCEiElUW*8ai0#)c1SLT%@R_NvxE5l51Ni9w;$}A|!%+FH*@e`BsOG|8(
zlwe-SEr1)FR}2j%V1VgYBo^o!>KW)GDfIQluQWFouDZA+C^Zeg>f(^ff>iyW)Z+Zo
zqGVvir743n7g#wLr6!i-7lq{K=fFZSAS1sdzc?emK*2fKOhLmpF*!32B%le_;p=PV
znO9trn3tUD>0+w{6w%AfOtG>waxyS5a5HzYFt9K*bTzhgHZgQHHMB4=H!?Lfa&(31
zb;(aI%}vcKf$2>_=(WJ97nB$vx>JiX%TiO^it=+6z@E0s#NrlHa~DekOD7ZDZh`1c
z!R;0^oO<<vj?qVpYM2l({eYP8gbU=rlYVL*FufN66L$agy*C*cnEE|k978H@C8Z=J
zBwU$M*3~?*H}*kQ*FWyNQ~UoLPhik%Kb<6+&Xgpk#`jK7Ozxojt?s<sf1h9GetN(C
zd}#dIm+4JeDStk`u=;-g{Cm^?HFfDsQzo-@3T_fu(h$9_z>Q~r>vtZJng9RSGj_gr
zP}Sk->A9m3RR7=R*Z<eYr`>-aS8`XYsD?%8P?~|dvT=9YwLhzW&$zLZ#e<V=!BhKx
zbw2~@bzRr<pZMJ@Ct}~ISMmS%+0CnYmN2=w@ukHb^jljQzO3-Xij4~;czV{<JN&vm
zzkhwc@dVBpJAVd?W=#uic*K44sKSTW_t(qoOKLFa{84%ubaE}%g$J$Df5cDx_w78`
z<8vlv4_jZWgPQiHgFFt2a%^0T-0K&xPk7{HHluT<yF*)0^Gu6Mk;;<X)&p`4mNO<!
zjqPYGI&flbqE>5;!R7z<`~L?WOlZ@;?pNbx_T&Hj@A~pVSug(I-@mVBZ`B*_4o>4A
z-=}-G^95&pSU;Wre4|E6bN#+3`=58__vdRAeO+#BZO*jvy@np!qw@FP^yas&bx>sc
zQ&ac;PxsTg)s1J?e|W-n_L_YBx;MA}{d{!r>=LP8-(Md$@Bd{K)p$l+!8*W*;|h1b
z{Fb9%>TEWq@@{zY%e`mefd|$9DuVJ%H=NnW@uZF+X@i~Hg6xUe%mIo@JV#a?$}7xM
zvdf&9^XQY-4IY+hy7%qo-`@TE=AT<j>+SaJV<{5RsWIenGnymcv9vLw&;7h#@PS+R
zXN0;$HBD@tDjM;x?nl|{H)qSMr_Ez!V_Y$T{b9JnA7;xs1D-Z1J}xCbg=fr3jw@Va
zHhhxquy@|ednjI^RU&IivZ=&LCbx{tqijnh7q&I<{O7&$TRc3~ic28z4={bqlHd_Y
ZVA!6|`A(sA(|k~Y?dj_0vd$@?2>=2lR|)_C
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9018291b5c543ac9adc1655227d0e5ee7d4e6f67
GIT binary patch
literal 2031
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..83f4b931d7ecf1e8a7b8456f1b1031531b668354
GIT binary patch
literal 2345
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ecb4c54e9c69d1abadbfddeb2195cf9837ef803b
GIT binary patch
literal 2443
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
--- a/editor/libeditor/base/ChangeAttributeTxn.cpp
+++ b/editor/libeditor/base/ChangeAttributeTxn.cpp
@@ -2,105 +2,99 @@
 /* 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 "ChangeAttributeTxn.h"
 #include "nsAString.h"
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsError.h"                    // for NS_ERROR_NOT_INITIALIZED, etc
-#include "nsEditor.h"                   // for nsEditor
+#include "nsIDOMElement.h"              // for nsIDOMElement
+#include "nsIEditor.h"                  // for nsIEditor
 #include "nsString.h"                   // for nsString
-#include "mozilla/dom/Element.h"
-
-using namespace mozilla;
 
 ChangeAttributeTxn::ChangeAttributeTxn()
   : EditTxn()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeAttributeTxn, EditTxn,
                                    mElement)
 
 NS_IMPL_ADDREF_INHERITED(ChangeAttributeTxn, EditTxn)
 NS_IMPL_RELEASE_INHERITED(ChangeAttributeTxn, EditTxn)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeAttributeTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
-NS_IMETHODIMP ChangeAttributeTxn::Init(nsEditor      *aEditor,
-                                       dom::Element *aElement,
+NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor      *aEditor,
+