Merge mozilla-central to b2g-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 26 May 2015 13:37:22 +0200
changeset 245625 833be9ccdb9d3f1172d05db222725ef4bc134464
parent 245624 6296370a3b754ec909f520fc9403cc548d611e80 (current diff)
parent 245587 e537a1ba501ba047d21587a8fc9f83d92b518f1f (diff)
child 245626 00549ec1b984e1352f3c5cf81d18dab0a2036b0c
push id13177
push userkwierso@gmail.com
push dateTue, 26 May 2015 23:26:28 +0000
treeherderfx-team@b991cd5a0ad1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone41.0a1
Merge mozilla-central to b2g-inbound
--- a/browser/base/content/newtab/newTab.css
+++ b/browser/base/content/newtab/newTab.css
@@ -45,60 +45,16 @@ input[type=button] {
   z-index: 101;
 }
 
 #newtab-customize-button:-moz-locale-dir(rtl) {
   left: 20px;
   right: auto;
 }
 
-#newtab-intro-what {
-  cursor: pointer;
-  position: absolute;
-  right: 70px;
-  top: 20px;
-  display: none;
-}
-
-#newtab-intro-what:-moz-locale-dir(rtl) {
-  left: 70px;
-  right: auto;
-}
-
-#newtab-scrollbox[page-disabled] #newtab-intro-what {
-  display: none;
-}
-
-#newtab-intro-panel {
-  color: #6a7b86;
-  font-size: 15px;
-  line-height: 19px;
-  width: 520px;
-}
-
-#newtab-intro-panel h1 {
-  color: #343f48;
-  font-family: Open Sans, sans-serif;
-  font-size: 30px;
-  margin: 20px;
-}
-
-#newtab-intro-panel p {
-  margin: 10px 20px;
-}
-
-#newtab-intro-panel p:last-child {
-  margin-bottom: 30px;
-}
-
-#newtab-intro-what:hover,
-#newtab-intro-panel a {
-  color: #4a90e2;
-}
-
 /* MARGINS */
 #newtab-vertical-margin {
   display: -moz-box;
   position: relative;
   -moz-box-flex: 1;
   -moz-box-orient: vertical;
 }
 
@@ -294,17 +250,16 @@ input[type=button] {
   background-color: rgba(51, 51, 51, 0.95);
   bottom: 30px;
   line-height: 20px;
   padding: 15px 10px;
   position: absolute;
   text-align: start;
 }
 
-#newtab-intro-panel input,
 .sponsored-explain input,
 .suggested-explain input {
   background-size: 18px;
   height: 18px;
   opacity: 1;
   pointer-events: none;
   position: static;
   width: 18px;
--- a/browser/base/content/newtab/newTab.xul
+++ b/browser/base/content/newtab/newTab.xul
@@ -19,21 +19,16 @@
 ]>
 
 <xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml"
             xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
             title="&newtab.pageTitle;">
 
   <div id="newtab-customize-overlay"></div>
 
-  <xul:panel id="newtab-intro-panel" orient="vertical" type="arrow"
-             noautohide="true" hidden="true">
-    <h1>&newtab.intro.header;</h1>
-  </xul:panel>
-
   <xul:panel id="newtab-search-panel" orient="vertical" type="arrow"
              noautohide="true" hidden="true">
     <xul:hbox id="newtab-search-manage">
       <xul:label>&changeSearchSettings.button;</xul:label>
     </xul:hbox>
   </xul:panel>
 
   <xul:panel id="newtab-customize-panel" orient="vertical" type="arrow"
@@ -127,18 +122,16 @@
 
         <div class="newtab-side-margin"/>
       </div>
 
       <div id="newtab-margin-bottom"/>
 
     </div>
 
-    <div id="newtab-intro-what">&newtab.customize.what;</div>
-
     <input id="newtab-customize-button" type="button" title="&newtab.customize.title;"/>
   </div>
 
   <xul:script type="text/javascript;version=1.8"
               src="chrome://browser/content/searchSuggestionUI.js"/>
   <xul:script type="text/javascript;version=1.8"
               src="chrome://browser/content/newtab/newTab.js"/>
 </xul:window>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1565,17 +1565,22 @@
             let browser = this._preloadedBrowser;
 
             // Consume the browser.
             this._preloadedBrowser = null;
 
             // Attach the nsIFormFillController now that we know the browser
             // will be used. If we do that before and the preloaded browser
             // won't be consumed until shutdown then we leak a docShell.
-            if (browser && this.hasAttribute("autocompletepopup")) {
+            // Also, we do not need to take care of attaching nsIFormFillControllers
+            // in the case that the browser is remote, as remote browsers take
+            // care of that themselves.
+            if (browser &&
+                this.hasAttribute("autocompletepopup") &&
+                !browser.isRemoteBrowser) {
               browser.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
               browser.attachFormFill();
             }
 
             return browser;
           ]]>
         </body>
       </method>
@@ -1596,17 +1601,19 @@
         <body>
           <![CDATA[
             // Do nothing if we have a preloaded browser already
             // or preloading of newtab pages is disabled.
             if (this._preloadedBrowser || !this._isPreloadingEnabled()) {
               return;
             }
 
-            let browser = this._createBrowser({isPreloadBrowser: true});
+            let remote = gMultiProcessBrowser &&
+                         E10SUtils.canLoadURIInProcess(BROWSER_NEW_TAB_URL, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
+            let browser = this._createBrowser({isPreloadBrowser: true, remote: remote});
             this._preloadedBrowser = browser;
 
             let notificationbox = this.getNotificationBox(browser);
             this.mPanelContainer.appendChild(notificationbox);
 
             browser.loadURI(BROWSER_NEW_TAB_URL);
             browser.docShellIsActive = false;
           ]]>
--- a/browser/base/content/test/general/browser_bug839103.js
+++ b/browser/base/content/test/general/browser_bug839103.js
@@ -1,9 +1,9 @@
-const gTestRoot = getRootDirectory(gTestPath);
+const gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
 const gStyleSheet = "bug839103.css";
 
 var gTab = null;
 var needsInitialApplicableStateEvent = false;
 var needsInitialApplicableStateEventFor = null;
 
 function test() {
   waitForExplicitFinish();
--- a/browser/base/content/test/newtab/browser_newtab_enhanced.js
+++ b/browser/base/content/test/newtab/browser_newtab_enhanced.js
@@ -104,19 +104,16 @@ function runTests() {
   ({type, enhanced, title, suggested} = getData(0));
   isnot(type, "enhanced", "history link is not enhanced");
   is(enhanced, "", "history link has no enhanced image");
   is(title, "example.com");
   is(suggested, "", "There is no suggested explanation");
 
   is(getData(1), null, "directory link still pushed out by pinned history link");
 
-  ok(getContentDocument().getElementById("newtab-intro-what"),
-     "'What is this page?' link exists");
-
   yield unpinCell(0);
 
 
 
   // Test that a suggested tile is not enhanced by a directory tile
   let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
   NewTabUtils.isTopPlacesSite = () => true;
   yield setLinks("-1,2,3,4,5,6,7,8");
--- a/browser/components/sessionstore/SessionFile.jsm
+++ b/browser/components/sessionstore/SessionFile.jsm
@@ -168,16 +168,20 @@ let SessionFileInternal = {
       if (SessionFileInternal.latestUpgradeBackupID) {
         // We have an upgradeBackup
         order.push("upgradeBackup");
       }
       return order;
     },
   }),
 
+  // `true` once `write` has succeeded at last once.
+  // Used for error-reporting.
+  _hasWriteEverSucceeded: false,
+
   // The ID of the latest version of Gecko for which we have an upgrade backup
   // or |undefined| if no upgrade backup was ever written.
   get latestUpgradeBackupID() {
     try {
       return Services.prefs.getCharPref(PREF_UPGRADE_BACKUP);
     } catch (ex) {
       return undefined;
     }
@@ -270,17 +274,17 @@ let SessionFileInternal = {
 
     let options = {isFinalWrite, performShutdownCleanup};
     let promise = SessionWorker.post("write", [aData, options]);
 
     // Wait until the write is done.
     promise = promise.then(msg => {
       // Record how long the write took.
       this._recordTelemetry(msg.telemetry);
-
+      this._hasWriteEverSucceeded = true;
       if (msg.result.upgradeBackup) {
         // We have just completed a backup-on-upgrade, store the information
         // in preferences.
         Services.prefs.setCharPref(PREF_UPGRADE_BACKUP,
           Services.appinfo.platformBuildID);
       }
     }, err => {
       // Catch and report any errors.
@@ -288,17 +292,24 @@ let SessionFileInternal = {
       // By not doing anything special here we ensure that |promise| cannot
       // be rejected anymore. The shutdown/cleanup code at the end of the
       // function will thus always be executed.
     });
 
     // Ensure that we can write sessionstore.js cleanly before the profile
     // becomes unaccessible.
     AsyncShutdown.profileBeforeChange.addBlocker(
-      "SessionFile: Finish writing Session Restore data", promise);
+      "SessionFile: Finish writing Session Restore data",
+      promise,
+      {
+        fetchState: () => ({
+          options,
+          hasEverSucceeded: this._hasWriteEverSucceeded
+        })
+      });
 
     // This code will always be executed because |promise| can't fail anymore.
     // We ensured that by having a reject handler that reports the failure but
     // doesn't forward the rejection.
     return promise.then(() => {
       // Remove the blocker, no matter if writing failed or not.
       AsyncShutdown.profileBeforeChange.removeBlocker(promise);
 
--- a/browser/components/sessionstore/content/aboutSessionRestore.xhtml
+++ b/browser/components/sessionstore/content/aboutSessionRestore.xhtml
@@ -10,78 +10,77 @@
   <!ENTITY % netErrorDTD SYSTEM "chrome://global/locale/netError.dtd">
   %netErrorDTD;
   <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
   %globalDTD;
   <!ENTITY % restorepageDTD SYSTEM "chrome://browser/locale/aboutSessionRestore.dtd">
   %restorepageDTD;
 ]>
 
-<html xmlns="http://www.w3.org/1999/xhtml">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <head>
     <title>&restorepage.tabtitle;</title>
     <link rel="stylesheet" href="chrome://global/skin/in-content/info-pages.css" type="text/css" media="all"/>
     <link rel="stylesheet" href="chrome://browser/skin/aboutSessionRestore.css" type="text/css" media="all"/>
     <link rel="icon" type="image/png" href="chrome://global/skin/icons/warning-16.png"/>
 
     <script type="application/javascript;version=1.8" src="chrome://browser/content/aboutSessionRestore.js"/>
   </head>
 
   <body dir="&locale.dir;">
 
-    <div class="container">
+    <div class="container flex">
 
       <div class="title">
         <h1 class="title-text">&restorepage.errorTitle;</h1>
       </div>
       <div class="description">
         <p>&restorepage.problemDesc;</p>
 
         <div id="errorLongDesc">
           <p>&restorepage.tryThis;</p>
           <ul>
             <li>&restorepage.restoreSome;</li>
             <li>&restorepage.startNew;</li>
           </ul>
         </div>
-
-        <tree xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-              id="tabList" flex="1" seltype="single" hidecolumnpicker="true"
+      </div>
+      <div class="tree-container">
+        <xul:tree id="tabList" seltype="single" hidecolumnpicker="true"
               onclick="onListClick(event);" onkeydown="onListKeyDown(event);"
               available="true" _window_label="&restorepage.windowLabel;">
-          <treecols>
-            <treecol cycler="true" id="restore" type="checkbox" label="&restorepage.restoreHeader;"/>
-            <splitter class="tree-splitter"/>
-            <treecol primary="true" id="title" label="&restorepage.listHeader;" flex="1"/>
-          </treecols>
-          <treechildren flex="1"/>
-        </tree>
+          <xul:treecols>
+            <xul:treecol cycler="true" id="restore" type="checkbox" label="&restorepage.restoreHeader;"/>
+            <xul:splitter class="tree-splitter"/>
+            <xul:treecol primary="true" id="title" label="&restorepage.listHeader;" flex="1"/>
+          </xul:treecols>
+          <xul:treechildren flex="1"/>
+        </xul:tree>
       </div>
-
-      <hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" class="button-container">
+      <div class="button-container">
 #ifdef XP_UNIX
-        <button id="errorCancel"
+        <xul:button id="errorCancel"
                 label="&restorepage.closeButton;"
                 accesskey="&restorepage.close.access;"
                 oncommand="startNewSession();"/>
-        <button class="primary"
+        <xul:button class="primary"
                 id="errorTryAgain"
                 label="&restorepage.tryagainButton;"
                 accesskey="&restorepage.restore.access;"
                 oncommand="restoreSession();"/>
 #else
-        <button class="primary"
+        <xul:button class="primary"
                 id="errorTryAgain"
                 label="&restorepage.tryagainButton;"
                 accesskey="&restorepage.restore.access;"
                 oncommand="restoreSession();"/>
-        <button id="errorCancel"
+        <xul:button id="errorCancel"
                 label="&restorepage.closeButton;"
                 accesskey="&restorepage.close.access;"
                 oncommand="startNewSession();"/>
 #endif
-      </hbox>
+      </div>
       <!-- holds the session data for when the tab is closed -->
       <input type="text" id="sessionData" style="display: none;"/>
     </div>
 
   </body>
 </html>
--- a/browser/devtools/app-manager/content/projects.js
+++ b/browser/devtools/app-manager/content/projects.js
@@ -121,17 +121,17 @@ let UI = {
                         UI.validate(project);
                         UI.selectProject(project.location);
                       });
   },
 
   _getLocalIconURL: function(project, manifest) {
     let icon;
     if (manifest.icons) {
-      let size = Object.keys(manifest.icons).sort(function(a, b) b - a)[0];
+      let size = Object.keys(manifest.icons).sort((a, b) => b - a)[0];
       if (size) {
         icon = manifest.icons[size];
       }
     }
     if (!icon)
       return "chrome://browser/skin/devtools/app-manager/default-app-icon.png";
     if (project.type == "hosted") {
       let manifestURL = Services.io.newURI(project.location, null, null);
--- a/browser/devtools/app-manager/test/browser_manifest_editor.js
+++ b/browser/devtools/app-manager/test/browser_manifest_editor.js
@@ -6,17 +6,17 @@ const {Services} = Cu.import("resource:/
 
 const MANIFEST_EDITOR_ENABLED = "devtools.appmanager.manifestEditor.enabled";
 
 let gManifestWindow, gManifestEditor;
 
 function test() {
   waitForExplicitFinish();
 
-  Task.spawn(function() {
+  Task.spawn(function*() {
     Services.prefs.setBoolPref(MANIFEST_EDITOR_ENABLED, true);
     let tab = yield openAppManager();
     yield selectProjectsPanel();
     yield addSamplePackagedApp();
     yield showSampleProjectDetails();
 
     gManifestWindow = getManifestWindow();
     gManifestEditor = getProjectsWindow().UI.manifestEditor;
--- a/browser/devtools/debugger/debugger-commands.js
+++ b/browser/devtools/debugger/debugger-commands.js
@@ -511,19 +511,22 @@ exports.items.push({
       // Filter the sources down to those that we will need to black box.
 
       function shouldBlackBox(source) {
         var value = globRegExp && globRegExp.test(source.url)
           || args.source && source.actor == args.source;
         return args.invert ? !value : value;
       }
 
-      const toBlackBox = [s.attachment.source
-                          for (s of dbg._view.Sources.items)
-                          if (shouldBlackBox(s.attachment.source))];
+      const toBlackBox = [];
+      for (let {attachment: {source}} of dbg._view.Sources.items) {
+        if (shouldBlackBox(source)) {
+          toBlackBox.push(source);
+        }
+      }
 
       // If we aren't black boxing any sources, bail out now.
 
       if (toBlackBox.length === 0) {
         const empty = createXHTMLElement(doc, "div");
         empty.textContent = lookup("EmptyDesc");
         return void resolve(empty);
       }
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -451,17 +451,19 @@ let DebuggerController = {
  * thread (paused/attached/etc.).
  */
 function ThreadState() {
   this._update = this._update.bind(this);
   this.interruptedByResumeButton = false;
 }
 
 ThreadState.prototype = {
-  get activeThread() DebuggerController.activeThread,
+  get activeThread() {
+    return DebuggerController.activeThread;
+  },
 
   /**
    * Connect to the current thread client.
    */
   connect: function() {
     dumpn("ThreadState is connecting...");
     this.activeThread.addListener("paused", this._update);
     this.activeThread.addListener("resumed", this._update);
@@ -537,17 +539,20 @@ function StackFrames() {
   this._onFramesCleared = this._onFramesCleared.bind(this);
   this._onBlackBoxChange = this._onBlackBoxChange.bind(this);
   this._onPrettyPrintChange = this._onPrettyPrintChange.bind(this);
   this._afterFramesCleared = this._afterFramesCleared.bind(this);
   this.evaluate = this.evaluate.bind(this);
 }
 
 StackFrames.prototype = {
-  get activeThread() DebuggerController.activeThread,
+  get activeThread() {
+    return DebuggerController.activeThread;
+  },
+
   currentFrameDepth: -1,
   _currentFrameDescription: FRAME_TYPE.NORMAL,
   _syncedWatchExpressions: null,
   _currentWatchExpressions: null,
   _currentBreakpointLocation: null,
   _currentEvaluation: null,
   _currentException: null,
   _currentReturnedValue: null,
@@ -1109,18 +1114,24 @@ function SourceScripts() {
   this._onNewGlobal = this._onNewGlobal.bind(this);
   this._onNewSource = this._onNewSource.bind(this);
   this._onSourcesAdded = this._onSourcesAdded.bind(this);
   this._onBlackBoxChange = this._onBlackBoxChange.bind(this);
   this._onPrettyPrintChange = this._onPrettyPrintChange.bind(this);
 }
 
 SourceScripts.prototype = {
-  get activeThread() DebuggerController.activeThread,
-  get debuggerClient() DebuggerController.client,
+  get activeThread() {
+    return DebuggerController.activeThread;
+  },
+
+  get debuggerClient() {
+    return DebuggerController.client;
+  },
+
   _cache: new Map(),
 
   /**
    * Connect to the current thread client.
    */
   connect: function() {
     dumpn("SourceScripts is connecting...");
     this.debuggerClient.addListener("newGlobal", this._onNewGlobal);
@@ -2438,33 +2449,43 @@ DebuggerController.Breakpoints.DOM = new
 DebuggerController.Tracer = new Tracer();
 DebuggerController.HitCounts = new HitCounts();
 
 /**
  * Export some properties to the global scope for easier access.
  */
 Object.defineProperties(window, {
   "gTarget": {
-    get: function() DebuggerController._target,
+    get: function() {
+      return DebuggerController._target;
+    },
     configurable: true
   },
   "gHostType": {
-    get: function() DebuggerView._hostType,
+    get: function() {
+      return DebuggerView._hostType;
+    },
     configurable: true
   },
   "gClient": {
-    get: function() DebuggerController.client,
+    get: function() {
+      return DebuggerController.client;
+    },
     configurable: true
   },
   "gThreadClient": {
-    get: function() DebuggerController.activeThread,
+    get: function() {
+      return DebuggerController.activeThread;
+    },
     configurable: true
   },
   "gCallStackPageSize": {
-    get: function() CALL_STACK_PAGE_SIZE,
+    get: function() {
+      return CALL_STACK_PAGE_SIZE;
+    },
     configurable: true
   }
 });
 
 /**
  * Helper method for debugging.
  * @param string
  */
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -510,25 +510,27 @@ let DebuggerView = {
       window.emit(EVENTS.EDITOR_LOCATION_SET);
     }).then(null, console.error);
   },
 
   /**
    * Gets the visibility state of the instruments pane.
    * @return boolean
    */
-  get instrumentsPaneHidden()
-    this._instrumentsPane.hasAttribute("pane-collapsed"),
+  get instrumentsPaneHidden() {
+    return this._instrumentsPane.hasAttribute("pane-collapsed");
+  },
 
   /**
    * Gets the currently selected tab in the instruments pane.
    * @return string
    */
-  get instrumentsPaneTab()
-    this._instrumentsPane.selectedTab.id,
+  get instrumentsPaneTab() {
+    return this._instrumentsPane.selectedTab.id;
+  },
 
   /**
    * Sets the instruments pane hidden or visible.
    *
    * @param object aFlags
    *        An object containing some of the following properties:
    *        - visible: true if the pane should be shown, false to hide
    *        - animated: true to display an animation on toggle
@@ -749,19 +751,20 @@ ResultsPanelContainer.prototype = Herita
       this._panel.openPopup(this._anchor, this.position, this.left, this.top);
     }
   },
 
   /**
    * Gets this container's visibility state.
    * @return boolean
    */
-  get hidden()
-    this._panel.state == "closed" ||
-    this._panel.state == "hiding",
+  get hidden() {
+    return this._panel.state == "closed" ||
+           this._panel.state == "hiding";
+  },
 
   /**
    * Removes all items from this container and hides it.
    */
   clearView: function() {
     this.hidden = true;
     this.empty();
   },
--- a/browser/devtools/debugger/panel.js
+++ b/browser/devtools/debugger/panel.js
@@ -63,17 +63,19 @@ DebuggerPanel.prototype = {
       })
       .then(null, function onError(aReason) {
         DevToolsUtils.reportException("DebuggerPanel.prototype.open", aReason);
       });
   },
 
   // DevToolPanel API
 
-  get target() this._toolbox.target,
+  get target() {
+    return this._toolbox.target;
+  },
 
   destroy: function() {
     // Make sure this panel is not already destroyed.
     if (this._destroyer) {
       return this._destroyer;
     }
 
     this.target.off("thread-paused", this.highlightWhenPaused);
--- a/browser/devtools/debugger/test/browser_dbg_addon-console.js
+++ b/browser/devtools/debugger/test/browser_dbg_addon-console.js
@@ -13,17 +13,17 @@ function getCachedMessages(webConsole) {
       return;
     }
     deferred.resolve(aResponse.messages);
   });
   return deferred.promise;
 }
 
 function test() {
-  Task.spawn(function () {
+  Task.spawn(function*() {
     let addon = yield addAddon(ADDON_URL);
     let addonDebugger = yield initAddonDebugger(ADDON_URL);
 
     let webConsole = addonDebugger.webConsole;
     let messages = yield getCachedMessages(webConsole);
     is(messages.length, 1, "Should be one cached message");
     is(messages[0].arguments[0].type, "object", "Should have logged an object");
     is(messages[0].arguments[0].preview.ownProperties.msg.value, "Hello from the test add-on", "Should have got the right message");
--- a/browser/devtools/debugger/test/browser_dbg_addon-modules-unpacked.js
+++ b/browser/devtools/debugger/test/browser_dbg_addon-modules-unpacked.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Make sure the add-on actor can see loaded JS Modules from an add-on
 
 const ADDON_URL = EXAMPLE_URL + "addon5.xpi";
 
 function test() {
-  Task.spawn(function () {
+  Task.spawn(function*() {
     let addon = yield addAddon(ADDON_URL);
     let tab1 = yield addTab("chrome://browser_dbg_addon5/content/test.xul");
 
     let addonDebugger = yield initAddonDebugger(ADDON_URL);
 
     is(addonDebugger.title, "Debugger - Test unpacked add-on with JS Modules", "Saw the right toolbox title.");
 
     // Check the inital list of sources is correct
--- a/browser/devtools/debugger/test/browser_dbg_addon-modules.js
+++ b/browser/devtools/debugger/test/browser_dbg_addon-modules.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Make sure the add-on actor can see loaded JS Modules from an add-on
 
 const ADDON_URL = EXAMPLE_URL + "addon4.xpi";
 
 function test() {
-  Task.spawn(function () {
+  Task.spawn(function*() {
     let addon = yield addAddon(ADDON_URL);
     let tab1 = yield addTab("chrome://browser_dbg_addon4/content/test.xul");
 
     let addonDebugger = yield initAddonDebugger(ADDON_URL);
 
     is(addonDebugger.title, "Debugger - Test add-on with JS Modules", "Saw the right toolbox title.");
 
     // Check the inital list of sources is correct
--- a/browser/devtools/debugger/test/browser_dbg_addon-panels.js
+++ b/browser/devtools/debugger/test/browser_dbg_addon-panels.js
@@ -9,17 +9,17 @@ const ADDON_URL = EXAMPLE_URL + "addon3.
 let gAddon, gClient, gThreadClient, gDebugger, gSources;
 let PREFS = [
   "devtools.canvasdebugger.enabled",
   "devtools.shadereditor.enabled",
   "devtools.performance.enabled",
   "devtools.netmonitor.enabled"
 ];
 function test() {
-  Task.spawn(function () {
+  Task.spawn(function*() {
     let addon = yield addAddon(ADDON_URL);
     let addonDebugger = yield initAddonDebugger(ADDON_URL);
 
     // Store and enable all optional dev tools panels
     let originalPrefs = PREFS.map(pref => {
       let original = Services.prefs.getBoolPref(pref);
       Services.prefs.setBoolPref(pref, true)
       return original;
--- a/browser/devtools/debugger/test/browser_dbg_addon-sources.js
+++ b/browser/devtools/debugger/test/browser_dbg_addon-sources.js
@@ -1,19 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Ensure that the sources listed when debugging an addon are either from the 
+// Ensure that the sources listed when debugging an addon are either from the
 // addon itself, or the SDK, with proper groups and labels.
 
 const ADDON_URL = EXAMPLE_URL + "addon3.xpi";
 let gClient;
 
 function test() {
-  Task.spawn(function () {
+  Task.spawn(function*() {
     let addon = yield addAddon(ADDON_URL);
     let addonDebugger = yield initAddonDebugger(ADDON_URL);
 
     is(addonDebugger.title, "Debugger - browser_dbg_addon3", "Saw the right toolbox title.");
 
     // Check the inital list of sources is correct
     let groups = yield addonDebugger.getSourceGroups();
     is(groups[0].name, "jid1-ami3akps3baaeg@jetpack", "Add-on code should be the first group");
--- a/browser/devtools/debugger/test/browser_dbg_breadcrumbs-access.js
+++ b/browser/devtools/debugger/test/browser_dbg_breadcrumbs-access.js
@@ -42,17 +42,17 @@ function test() {
 
   function focusCurrentStackFrame() {
     EventUtils.sendMouseEvent({ type: "mousedown" },
       gFrames.selectedItem.target,
       gDebugger);
   }
 
   function checkNavigationWhileFocused() {
-    return Task.spawn(function() {
+    return Task.spawn(function*() {
       yield promise.all([
         waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
         waitForSourceAndCaret(gPanel, "-01.js", 5),
         waitForEditorLocationSet(gPanel),
         EventUtils.sendKey("UP", gDebugger)
       ]);
       checkState({ frame: 0, source: 0, line: 5 });
 
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-01.js
@@ -22,17 +22,17 @@ function test() {
 
     gView.toggleInstrumentsPane({ visible: true, animated: false });
 
     is(gView.instrumentsPaneHidden, false,
       "The instruments pane should be visible now.");
     is(gView.instrumentsPaneTab, "variables-tab",
       "The variables tab should be selected by default.");
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, ".html");
       is(gEvents.itemCount, 0, "There should be no events before reloading.");
 
       let reloaded = waitForSourcesAfterReload();
       gDebugger.DebuggerController._target.activeTab.reload();
 
       is(gEvents.itemCount, 0, "There should be no events while reloading.");
       yield reloaded;
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-02.js
@@ -9,26 +9,26 @@
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gEvents = gView.EventListeners;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, ".html");
       yield testFetchOnFocus();
       yield testFetchOnReloadWhenFocused();
       yield testFetchOnReloadWhenNotFocused();
       yield closeDebuggerAndFinish(aPanel);
     });
 
     function testFetchOnFocus() {
-      return Task.spawn(function() {
+      return Task.spawn(function*() {
         let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
 
         gView.toggleInstrumentsPane({ visible: true, animated: false }, 1);
         is(gView.instrumentsPaneHidden, false,
           "The instruments pane should be visible now.");
         is(gView.instrumentsPaneTab, "events-tab",
           "The events tab should be selected.");
 
@@ -37,17 +37,17 @@ function test() {
         ok(true,
           "Event listeners were fetched when the events tab was selected");
         is(gEvents.itemCount, 4,
           "There should be 4 events displayed in the view.");
       });
     }
 
     function testFetchOnReloadWhenFocused() {
-      return Task.spawn(function() {
+      return Task.spawn(function*() {
         let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
 
         let reloading = once(gDebugger.gTarget, "will-navigate");
         let reloaded = waitForSourcesAfterReload();
         gDebugger.DebuggerController._target.activeTab.reload();
 
         yield reloading;
 
@@ -68,17 +68,17 @@ function test() {
         is(gEvents.itemCount, 4,
           "There should be 4 events displayed in the view after reloading.");
         ok(true,
           "Event listeners were added back after the target finished navigating.");
       });
     }
 
     function testFetchOnReloadWhenNotFocused() {
-      return Task.spawn(function() {
+      return Task.spawn(function*() {
         gDebugger.on(gDebugger.EVENTS.EVENT_LISTENERS_FETCHED, () => {
           ok(false, "Shouldn't have fetched any event listeners.");
         });
         gDebugger.on(gDebugger.EVENTS.EVENT_BREAKPOINTS_UPDATED, () => {
           ok(false, "Shouldn't have updated any event breakpoints.");
         });
 
         gView.toggleInstrumentsPane({ visible: true, animated: false }, 0);
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-03.js
@@ -8,17 +8,17 @@
 const TAB_URL = EXAMPLE_URL + "doc_event-listeners-02.html";
 
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gEvents = gView.EventListeners;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, ".html");
 
       let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
       gView.toggleInstrumentsPane({ visible: true, animated: false }, 1);
       yield fetched;
 
       is(gEvents.widget._parent.querySelectorAll(".side-menu-widget-group").length, 3,
         "There should be 3 groups shown in the view.");
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-04.js
@@ -11,17 +11,17 @@ const TAB_URL = EXAMPLE_URL + "doc_event
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gController = gDebugger.DebuggerController
     let gEvents = gView.EventListeners;
     let gBreakpoints = gController.Breakpoints;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, ".html");
 
       let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
       gView.toggleInstrumentsPane({ visible: true, animated: false }, 1);
       yield fetched;
 
       testEventItem(0, false);
       testEventItem(1, false);
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-05.js
@@ -12,17 +12,17 @@ const TAB_URL = EXAMPLE_URL + "doc_event
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gController = gDebugger.DebuggerController
     let gEvents = gView.EventListeners;
     let gBreakpoints = gController.Breakpoints;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, ".html");
 
       let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
       gView.toggleInstrumentsPane({ visible: true, animated: false }, 1);
       yield fetched;
 
       testEventItem(0, false);
       testEventItem(1, false);
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-06.js
@@ -11,17 +11,17 @@ const TAB_URL = EXAMPLE_URL + "doc_event
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gController = gDebugger.DebuggerController
     let gEvents = gView.EventListeners;
     let gBreakpoints = gController.Breakpoints;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, ".html");
 
       let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
       gView.toggleInstrumentsPane({ visible: true, animated: false }, 1);
       yield fetched;
 
       testEventItem(0, false);
       testEventItem(1, false);
--- a/browser/devtools/debugger/test/browser_dbg_break-on-dom-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_break-on-dom-08.js
@@ -9,17 +9,17 @@ const TAB_URL = EXAMPLE_URL + "doc_event
 
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gTab = aTab;
     let gDebugger = aPanel.panelWin;
     let gView = gDebugger.DebuggerView;
     let gEvents = gView.EventListeners;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, ".html");
       yield callInTab(gTab, "addBodyClickEventListener");
 
       let fetched = waitForDebuggerEvents(aPanel, gDebugger.EVENTS.EVENT_LISTENERS_FETCHED);
       gView.toggleInstrumentsPane({ visible: true, animated: false }, 1);
       yield fetched;
       yield ensureThreadClientState(aPanel, "resumed");
 
--- a/browser/devtools/debugger/test/browser_dbg_breakpoints-disabled-reload.js
+++ b/browser/devtools/debugger/test/browser_dbg_breakpoints-disabled-reload.js
@@ -11,17 +11,17 @@ function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gTab = aTab;
     let gDebugger = aPanel.panelWin;
     let gEvents = gDebugger.EVENTS;
     let gEditor = gDebugger.DebuggerView.editor;
     let gSources = gDebugger.DebuggerView.Sources;
     let gBreakpoints = gDebugger.DebuggerController.Breakpoints;
     let gBreakpointLocation;
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, "-01.js");
       gBreakpointLocation = { actor: getSourceActor(gSources, EXAMPLE_URL + "code_script-switching-01.js"),
                               line: 5 };
 
       yield aPanel.addBreakpoint(gBreakpointLocation);
 
       yield ensureThreadClientState(aPanel, "resumed");
       yield testWhenBreakpointEnabledAndFirstSourceShown();
@@ -36,17 +36,17 @@ function test() {
       yield gSources.enableBreakpoint(gBreakpointLocation);
       yield reloadActiveTab(aPanel, gEvents.SOURCE_SHOWN);
       yield testWhenBreakpointEnabledAndSecondSourceShown();
 
       yield resumeDebuggerThenCloseAndFinish(aPanel);
     });
 
     function verifyView({ disabled, visible }) {
-      return Task.spawn(function() {
+      return Task.spawn(function*() {
         // It takes a tick for the checkbox in the SideMenuWidget and the
         // gutter in the editor to get updated.
         yield waitForTick();
 
         let breakpointItem = gSources.getBreakpoint(gBreakpointLocation);
         let visibleBreakpoints = gEditor.getBreakpoints();
         is(!!breakpointItem.attachment.disabled, disabled,
           "The selected brekapoint state was correct.");
@@ -60,49 +60,49 @@ function test() {
           "The selected breakpoint's visibility in the editor was correct.");
       });
     }
 
     // All the following executeSoon()'s are required to spin the event loop
     // before causing the debuggee to pause, to allow functions to yield first.
 
     function testWhenBreakpointEnabledAndFirstSourceShown() {
-      return Task.spawn(function() {
+      return Task.spawn(function*() {
         yield ensureSourceIs(aPanel, "-01.js");
         yield verifyView({ disabled: false, visible: true });
 
         callInTab(gTab, "firstCall");
         yield waitForDebuggerEvents(aPanel, gEvents.FETCHED_SCOPES);
         yield ensureSourceIs(aPanel, "-01.js");
         yield ensureCaretAt(aPanel, 5);
         yield verifyView({ disabled: false, visible: true });
 
         executeSoon(() => gDebugger.gThreadClient.resume());
         yield waitForSourceAndCaretAndScopes(aPanel, "-02.js", 1);
         yield verifyView({ disabled: false, visible: false });
       });
     }
 
     function testWhenBreakpointEnabledAndSecondSourceShown() {
-      return Task.spawn(function() {
+      return Task.spawn(function*() {
         yield ensureSourceIs(aPanel, "-02.js", true);
         yield verifyView({ disabled: false, visible: false });
 
         callInTab(gTab, "firstCall");
         yield waitForSourceAndCaretAndScopes(aPanel, "-01.js", 1);
         yield verifyView({ disabled: false, visible: true });
 
         executeSoon(() => gDebugger.gThreadClient.resume());
         yield waitForSourceAndCaretAndScopes(aPanel, "-02.js", 1);
         yield verifyView({ disabled: false, visible: false });
       });
     }
 
     function testWhenBreakpointDisabledAndSecondSourceShown() {
-      return Task.spawn(function() {
+      return Task.spawn(function*() {
         yield ensureSourceIs(aPanel, "-02.js", true);
         yield verifyView({ disabled: true, visible: false });
 
         callInTab(gTab, "firstCall");
         yield waitForDebuggerEvents(aPanel, gEvents.FETCHED_SCOPES);
         yield ensureSourceIs(aPanel, "-02.js");
         yield ensureCaretAt(aPanel, 6);
         yield verifyView({ disabled: true, visible: false });
--- a/browser/devtools/debugger/test/browser_dbg_cmd-blackbox.js
+++ b/browser/devtools/debugger/test/browser_dbg_cmd-blackbox.js
@@ -11,17 +11,17 @@ const BLACKBOXME_URL = EXAMPLE_URL + "co
 const BLACKBOXONE_URL = EXAMPLE_URL + "code_blackboxing_one.js";
 const BLACKBOXTWO_URL = EXAMPLE_URL + "code_blackboxing_two.js";
 const BLACKBOXTHREE_URL = EXAMPLE_URL + "code_blackboxing_three.js";
 
 function test() {
   return Task.spawn(spawnTest).then(finish, helpers.handleError);
 }
 
-function spawnTest() {
+function* spawnTest() {
   let options = yield helpers.openTab(TEST_URL);
   yield helpers.openToolbar(options);
 
   let toolbox = yield gDevTools.showToolbox(options.target, "jsdebugger");
   let panel = toolbox.getCurrentPanel();
 
   yield waitForDebuggerEvents(panel, panel.panelWin.EVENTS.SOURCE_SHOWN);
 
--- a/browser/devtools/debugger/test/browser_dbg_cmd-break.js
+++ b/browser/devtools/debugger/test/browser_dbg_cmd-break.js
@@ -13,17 +13,17 @@ function test() {
   let gLineNumber;
 
   let expectedActorObj = {
     value: null,
     message: ''
   };
 
   helpers.addTabWithToolbar(TAB_URL, aOptions => {
-    return Task.spawn(function() {
+    return Task.spawn(function*() {
       yield helpers.audit(aOptions, [{
         setup: 'break',
         check: {
           input:  'break',
           hints:       ' add line',
           markup: 'IIIII',
           status: 'ERROR',
         }
--- a/browser/devtools/debugger/test/browser_dbg_cmd-dbg.js
+++ b/browser/devtools/debugger/test/browser_dbg_cmd-dbg.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests that the debugger commands work as they should.
  */
 
 const TEST_URI = EXAMPLE_URL + "doc_cmd-dbg.html";
 
 function test() {
-  return Task.spawn(function() {
+  return Task.spawn(function*() {
     let options = yield helpers.openTab(TEST_URI);
     yield helpers.openToolbar(options);
 
     yield helpers.audit(options, [{
       setup: "dbg open",
       exec: { output: "" }
     }]);
 
--- a/browser/devtools/debugger/test/browser_dbg_controller-evaluate-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_controller-evaluate-01.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests the public evaluation API from the debugger controller.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let frames = win.DebuggerController.StackFrames;
     let framesView = win.DebuggerView.StackFrames;
     let sources = win.DebuggerController.SourceScripts;
     let sourcesView = win.DebuggerView.Sources;
     let editorView = win.DebuggerView.editor;
     let events = win.EVENTS;
--- a/browser/devtools/debugger/test/browser_dbg_controller-evaluate-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_controller-evaluate-02.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests the public evaluation API from the debugger controller.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let frames = win.DebuggerController.StackFrames;
     let framesView = win.DebuggerView.StackFrames;
     let sources = win.DebuggerController.SourceScripts;
     let sourcesView = win.DebuggerView.Sources;
     let editorView = win.DebuggerView.editor;
     let events = win.EVENTS;
--- a/browser/devtools/debugger/test/browser_dbg_file-reload.js
+++ b/browser/devtools/debugger/test/browser_dbg_file-reload.js
@@ -10,17 +10,17 @@ const JS_URL = EXAMPLE_URL + "sjs_random
 
 function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     let gDebugger = aPanel.panelWin;
     let gEditor = gDebugger.DebuggerView.editor;
     let gSources = gDebugger.DebuggerView.Sources;
     let gControllerSources = gDebugger.DebuggerController.SourceScripts;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(aPanel, JS_URL);
 
       is(gSources.itemCount, 1,
         "There should be one source displayed in the view.")
       is(getSelectedSourceURL(gSources), JS_URL,
         "The correct source is currently selected in the view.");
       ok(gEditor.getText().includes("bacon"),
         "The currently shown source contains bacon. Mmm, delicious!");
--- a/browser/devtools/debugger/test/browser_dbg_host-layout.js
+++ b/browser/devtools/debugger/test/browser_dbg_host-layout.js
@@ -4,46 +4,46 @@
 /**
  * This if the debugger's layout is correctly modified when the toolbox's
  * host changes.
  */
 
 let gDefaultHostType = Services.prefs.getCharPref("devtools.toolbox.host");
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     yield testHosts(["bottom", "side", "window"], ["horizontal", "vertical", "horizontal"]);
     yield testHosts(["side", "bottom", "side"], ["vertical", "horizontal", "vertical"]);
     yield testHosts(["bottom", "side", "bottom"], ["horizontal", "vertical", "horizontal"]);
     yield testHosts(["side", "window", "side"], ["vertical", "horizontal", "vertical"]);
     yield testHosts(["window", "side", "window"], ["horizontal", "vertical", "horizontal"]);
     finish();
   });
 }
 
 function testHosts(aHostTypes, aLayoutTypes) {
   let [firstHost, secondHost, thirdHost] = aHostTypes;
   let [firstLayout, secondLayout, thirdLayout] = aLayoutTypes;
 
   Services.prefs.setCharPref("devtools.toolbox.host", firstHost);
 
-  return Task.spawn(function() {
+  return Task.spawn(function*() {
     let [tab, debuggee, panel] = yield initDebugger("about:blank");
     yield testHost(tab, panel, firstHost, firstLayout);
     yield switchAndTestHost(tab, panel, secondHost, secondLayout);
     yield switchAndTestHost(tab, panel, thirdHost, thirdLayout);
     yield teardown(panel);
   });
 }
 
 function switchAndTestHost(aTab, aPanel, aHostType, aLayoutType) {
   let gToolbox = aPanel._toolbox;
   let gDebugger = aPanel.panelWin;
 
-  return Task.spawn(function() {
+  return Task.spawn(function*() {
     let layoutChanged = once(gDebugger, gDebugger.EVENTS.LAYOUT_CHANGED);
     let hostChanged = gToolbox.switchHost(aHostType);
 
     yield hostChanged;
     ok(true, "The toolbox's host has changed.");
 
     yield layoutChanged;
     ok(true, "The debugger's layout has changed.");
--- a/browser/devtools/debugger/test/browser_dbg_listtabs-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_listtabs-02.js
@@ -69,18 +69,18 @@ function addTabA() {
 function testTabA() {
   is(onListChangedCount, 1, "onListChanged handler call count");
 
   return gTabList.getList().then(aTabActors => {
     let tabActors = new Set(aTabActors);
     is(tabActors.size, 2, "gTabA opened: two tabs in list");
     ok(tabActors.has(gFirstActor), "gTabA opened: initial tab present");
 
-    info("actors: " + [a.url for (a of tabActors)]);
-    gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
+    info("actors: " + [...tabActors].map(a => a.url));
+    gActorA = [...tabActors].filter(a => a !== gFirstActor)[0];
     ok(gActorA.url.match(/^data:text\/html;/), "gTabA opened: new tab URL");
     is(gActorA.title, "JS Debugger BrowserTabList test page", "gTabA opened: new tab title");
   });
 }
 
 function addTabB() {
   return addTab(gTestPage).then(aTab => {
     gTabB = aTab;
@@ -113,18 +113,18 @@ function removeTabA() {
 function testTabClosed() {
   is(onListChangedCount, 3, "onListChanged handler call count");
 
   gTabList.getList().then(aTabActors => {
     let tabActors = new Set(aTabActors);
     is(tabActors.size, 2, "gTabA closed: two tabs in list");
     ok(tabActors.has(gFirstActor), "gTabA closed: initial tab present");
 
-    info("actors: " + [a.url for (a of tabActors)]);
-    gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
+    info("actors: " + [...tabActors].map(a => a.url));
+    gActorA = [...tabActors].filter(a => a!== gFirstActor)[0];
     ok(gActorA.url.match(/^data:text\/html;/), "gTabA closed: new tab URL");
     is(gActorA.title, "JS Debugger BrowserTabList test page", "gTabA closed: new tab title");
   });
 }
 
 function addTabC() {
   return addTab(gTestPage).then(aTab => {
     gTabC = aTab;
@@ -157,18 +157,18 @@ function removeTabC() {
 function testNewWindow() {
   is(onListChangedCount, 5, "onListChanged handler call count");
 
   return gTabList.getList().then(aTabActors => {
     let tabActors = new Set(aTabActors);
     is(tabActors.size, 3, "gTabC closed: three tabs in list");
     ok(tabActors.has(gFirstActor), "gTabC closed: initial tab present");
 
-    info("actors: " + [a.url for (a of tabActors)]);
-    gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
+    info("actors: " + [...tabActors].map(a => a.url));
+    gActorA = [...tabActors].filter(a => a !== gFirstActor)[0];
     ok(gActorA.url.match(/^data:text\/html;/), "gTabC closed: new tab URL");
     is(gActorA.title, "JS Debugger BrowserTabList test page", "gTabC closed: new tab title");
   });
 }
 
 function removeNewWindow() {
   let deferred = promise.defer();
 
@@ -186,18 +186,18 @@ function removeNewWindow() {
 function testWindowClosed() {
   is(onListChangedCount, 6, "onListChanged handler call count");
 
   return gTabList.getList().then(aTabActors => {
     let tabActors = new Set(aTabActors);
     is(tabActors.size, 2, "gNewWindow closed: two tabs in list");
     ok(tabActors.has(gFirstActor), "gNewWindow closed: initial tab present");
 
-    info("actors: " + [a.url for (a of tabActors)]);
-    gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
+    info("actors: " + [...tabActors].map(a => a.url));
+    gActorA = [...tabActors].filter(a => a !== gFirstActor)[0];
     ok(gActorA.url.match(/^data:text\/html;/), "gNewWindow closed: new tab URL");
     is(gActorA.title, "JS Debugger BrowserTabList test page", "gNewWindow closed: new tab title");
   });
 }
 
 function removeTabB() {
   let deferred = promise.defer();
 
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-05.js
@@ -14,17 +14,17 @@ function test() {
   initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gControllerSources = gDebugger.DebuggerController.SourceScripts;
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(gPanel, TAB_URL);
 
       // From this point onward, the source editor's text should never change.
       gEditor.once("change", () => {
         ok(false, "The source editor text shouldn't have changed.");
       });
 
       is(getSelectedSourceURL(gSources), TAB_URL,
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-06.js
@@ -30,17 +30,17 @@ function test() {
         if (aPacket.type == "prettyPrint") {
           gPrettyPrinted = true;
           return executeSoon(() => aCallback({ error: "prettyPrintError" }));
         }
         return aOriginalRequestMethod(aPacket, aCallback);
       };
     }(gClient.request));
 
-    Task.spawn(function() {
+    Task.spawn(function*() {
       yield waitForSourceShown(gPanel, JS_URL);
 
       // From this point onward, the source editor's text should never change.
       gEditor.once("change", () => {
         ok(false, "The source editor text shouldn't have changed.");
       });
 
       is(getSelectedSourceURL(gSources), JS_URL,
--- a/browser/devtools/debugger/test/browser_dbg_stack-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-07.js
@@ -24,17 +24,17 @@ function test() {
     gToolbar = gDebugger.DebuggerView.Toolbar;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest);
     callInTab(gTab, "firstCall");
   });
 }
 
 function performTest() {
-  return Task.spawn(function() {
+  return Task.spawn(function*() {
     yield selectBottomFrame();
     testBottomFrame(4);
 
     yield performStep("StepOver");
     testTopFrame(1);
 
     yield selectBottomFrame();
     testBottomFrame(4);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-accessibility.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-accessibility.js
@@ -57,17 +57,17 @@ function performTest() {
   };
 
   gVariablesView.eval = function() {};
   gVariablesView.switch = function() {};
   gVariablesView.delete = function() {};
   gVariablesView.rawObject = test;
   gVariablesView.scrollPageSize = 5;
 
-  return Task.spawn(function() {
+  return Task.spawn(function*() {
     yield waitForTick();
 
     // Part 0: Test generic focus methods on the variables view.
 
     gVariablesView.focusFirstVisibleItem();
     is(gVariablesView.getFocusedItem().name, "someProp0",
       "The 'someProp0' item should be focused.");
 
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-override-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-override-01.js
@@ -4,17 +4,17 @@
 /**
  * Tests that VariablesView methods responsible for styling variables
  * as overridden work properly.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_scope-variable-2.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let variables = win.DebuggerView.Variables;
 
     callInTab(tab, "test");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 23);
 
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-override-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-override-02.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests that overridden variables in the VariablesView are styled properly.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_scope-variable-2.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let variables = win.DebuggerView.Variables;
 
     // Wait for the hierarchy to be committed by the VariablesViewController.
     let committedLocalScopeHierarchy = promise.defer();
     variables.oncommit = committedLocalScopeHierarchy.resolve;
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js
@@ -4,17 +4,17 @@
 /**
  * Tests opening the variable inspection popup on a variable which has a
  * simple literal as the value.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     bubble._ignoreLiterals = false;
 
     function verifyContents(textContent, className) {
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js
@@ -4,17 +4,17 @@
 /**
  * Tests opening the variable inspection popup on a variable which has a
  * a property accessible via getters and setters.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view containers added to the tooltip.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-03.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests that the inspected indentifier is highlighted.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
 
     callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variable.
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-04.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests that the variable inspection popup is hidden when the editor scrolls.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
 
     callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variable.
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-05.js
@@ -4,17 +4,17 @@
 /**
  * Tests opening the variable inspection popup on a variable which has a
  * simple object as the value.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContents() {
       is(tooltip.querySelectorAll(".variables-view-container").length, 1,
         "There should be one variables view container added to the tooltip.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-06.js
@@ -5,17 +5,17 @@
  * Tests opening the variable inspection popup on a variable which has a
  * complext object as the value.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   requestLongerTimeout(2);
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContents() {
       is(tooltip.querySelectorAll(".variables-view-container").length, 1,
         "There should be one variables view container added to the tooltip.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js
@@ -4,17 +4,17 @@
 /**
  * Tests the variable inspection popup behaves correctly when switching
  * between simple and complex objects.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifySimpleContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view container added to the tooltip.");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests opening inspecting variables works across scopes.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_scope-variable.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let editor = win.DebuggerView.editor;
     let frames = win.DebuggerView.StackFrames;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-09.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-09.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests opening inspecting variables works across scopes.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_scope-variable-3.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     callInTab(tab, "test");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 15);
 
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-10.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-10.js
@@ -5,17 +5,17 @@
  * Makes sure the source editor's scroll location doesn't change when
  * a variable inspection popup is opened and a watch expression is
  * also evaluated at the same time.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let editor = win.DebuggerView.editor;
     let editorContainer = win.document.getElementById("editor");
     let bubble = win.DebuggerView.VariableBubble;
     let expressions = win.DebuggerView.WatchExpressions;
     let tooltip = bubble._tooltip.panel;
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-11.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-11.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests that the watch expression button is added in variable view popup.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_watch-expression-button.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let watch = win.DebuggerView.WatchExpressions;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     let label = win.L10N.getStr("addWatchExpressionButton");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-12.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-12.js
@@ -4,17 +4,17 @@
 /**
  * Tests that the clicking "Watch" button twice, for the same expression, only adds it
  * once.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_watch-expression-button.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let watch = win.DebuggerView.WatchExpressions;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContent(aExpression, aItemCount) {
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-13.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-13.js
@@ -4,17 +4,17 @@
 /**
  * Tests that the variable inspection popup has inspector links for DOMNode
  * properties and that the popup closes when the link is clicked
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_domnode-variables.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
     let toolbox = gDevTools.getToolbox(panel.target);
 
     function getDomNodeInTooltip(propertyName) {
       let domNodeProperties = tooltip.querySelectorAll(".token-domnode");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-15.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-15.js
@@ -3,17 +3,17 @@
 
 /**
  * Tests opening the variable inspection popup directly on literals.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-16.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-16.js
@@ -4,17 +4,17 @@
 /**
  * Tests if opening the variables inspection popup preserves the highlighting
  * associated with the currently debugged line.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
 
 function test() {
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let editor = win.DebuggerView.editor;
     let frames = win.DebuggerView.StackFrames;
     let variables = win.DebuggerView.Variables;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
--- a/browser/devtools/debugger/views/filter-view.js
+++ b/browser/devtools/debugger/views/filter-view.js
@@ -165,23 +165,27 @@ FilterView.prototype = {
 
     return [operator, args];
   },
 
   /**
    * Returns the current search operator.
    * @return string
    */
-  get searchOperator() this.searchData[0],
+  get searchOperator() {
+    return this.searchData[0];
+  },
 
   /**
    * Returns the current search arguments.
    * @return array
    */
-  get searchArguments() this.searchData[1],
+  get searchArguments() {
+    return this.searchData[1];
+  },
 
   /**
    * Clears the text from the searchbox and any changed views.
    */
   clearSearch: function() {
     this._searchbox.value = "";
     this.clearViews();
 
--- a/browser/devtools/debugger/views/global-search-view.js
+++ b/browser/devtools/debugger/views/global-search-view.js
@@ -45,19 +45,20 @@ GlobalSearchView.prototype = Heritage.ex
     this.widget.setAttribute("hidden", aFlag);
     this._splitter.setAttribute("hidden", aFlag);
   },
 
   /**
    * Gets the visibility state of the global search container.
    * @return boolean
    */
-  get hidden()
-    this.widget.getAttribute("hidden") == "true" ||
-    this._splitter.getAttribute("hidden") == "true",
+  get hidden() {
+    return this.widget.getAttribute("hidden") == "true" ||
+           this._splitter.getAttribute("hidden") == "true";
+  },
 
   /**
    * Hides and removes all items from this search container.
    */
   clearView: function() {
     this.hidden = true;
     this.empty();
   },
@@ -361,17 +362,19 @@ GlobalResults.prototype = {
    */
   add: function(aSourceResults) {
     this._store.push(aSourceResults);
   },
 
   /**
    * Gets the number of source results in this store.
    */
-  get matchCount() this._store.length
+  get matchCount() {
+    return this._store.length;
+  }
 };
 
 /**
  * An object containing all the matched lines for a specific source.
  * Iterable via "for (let [lineNumber, lineResults] of sourceResults) { }".
  *
  * @param string aActor
  *        The target source actor id.
@@ -395,17 +398,19 @@ SourceResults.prototype = {
    */
   add: function(aLineResults) {
     this._store.push(aLineResults);
   },
 
   /**
    * Gets the number of line results in this store.
    */
-  get matchCount() this._store.length,
+  get matchCount() {
+    return this._store.length;
+  },
 
   /**
    * Expands the element, showing all the added details.
    */
   expand: function() {
     this._resultsContainer.removeAttribute("hidden");
     this._arrow.setAttribute("open", "");
   },
@@ -424,31 +429,36 @@ SourceResults.prototype = {
   toggle: function(e) {
     this.expanded ^= 1;
   },
 
   /**
    * Gets this element's expanded state.
    * @return boolean
    */
-  get expanded()
-    this._resultsContainer.getAttribute("hidden") != "true" &&
-    this._arrow.hasAttribute("open"),
+  get expanded() {
+    return this._resultsContainer.getAttribute("hidden") != "true" &&
+           this._arrow.hasAttribute("open");
+  },
 
   /**
    * Sets this element's expanded state.
    * @param boolean aFlag
    */
-  set expanded(aFlag) this[aFlag ? "expand" : "collapse"](),
+  set expanded(aFlag) {
+    this[aFlag ? "expand" : "collapse"]();
+  },
 
   /**
    * Gets the element associated with this item.
    * @return nsIDOMNode
    */
-  get target() this._target,
+  get target() {
+    return this._target;
+  },
 
   /**
    * Customization function for creating this item's UI.
    *
    * @param nsIDOMNode aElementNode
    *        The element associated with the displayed item.
    * @param object aCallbacks
    *        An object containing all the necessary callback functions:
@@ -542,23 +552,27 @@ LineResults.prototype = {
   add: function(aString, aRange, aMatchFlag) {
     this._store.push({ string: aString, range: aRange, match: !!aMatchFlag });
     this._matchCount += aMatchFlag ? 1 : 0;
   },
 
   /**
    * Gets the number of word results in this store.
    */
-  get matchCount() this._matchCount,
+  get matchCount() {
+    return this._matchCount;
+  },
 
   /**
    * Gets the element associated with this item.
    * @return nsIDOMNode
    */
-  get target() this._target,
+  get target() {
+    return this._target;
+  },
 
   /**
    * Customization function for creating this item's UI.
    *
    * @param nsIDOMNode aElementNode
    *        The element associated with the displayed item.
    * @param object aCallbacks
    *        An object containing all the necessary callback functions:
--- a/browser/devtools/debugger/views/watch-expressions-view.js
+++ b/browser/devtools/debugger/views/watch-expressions-view.js
@@ -102,17 +102,17 @@ WatchExpressionsView.prototype = Heritag
    *
    * @param Variable aVar
    *        The variable representing the watch expression evaluation.
    * @param string aExpression
    *        The new watch expression text.
    */
   switchExpression: function(aVar, aExpression) {
     let expressionItem =
-      [i for (i of this) if (i.attachment.currentExpression == aVar.name)][0];
+      [...this].filter(i => i.attachment.currentExpression == aVar.name)[0];
 
     // Remove the watch expression if it's going to be empty or a duplicate.
     if (!aExpression || this.getAllStrings().indexOf(aExpression) != -1) {
       this.deleteExpression(aVar);
       return;
     }
 
     // Save the watch expression code string.
@@ -128,17 +128,17 @@ WatchExpressionsView.prototype = Heritag
    * This function is called whenever a watch expression's value is edited in
    * the variables view container.
    *
    * @param Variable aVar
    *        The variable representing the watch expression evaluation.
    */
   deleteExpression: function(aVar) {
     let expressionItem =
-      [i for (i of this) if (i.attachment.currentExpression == aVar.name)][0];
+      [...this].filter(i => i.attachment.currentExpression == aVar.name)[0];
 
     // Remove the watch expression.
     this.remove(expressionItem);
 
     // Synchronize with the controller's watch expressions store.
     this.StackFrames.syncWatchExpressions();
   },
 
--- a/browser/devtools/netmonitor/netmonitor-controller.js
+++ b/browser/devtools/netmonitor/netmonitor-controller.js
@@ -794,17 +794,22 @@ function whenDataAvailable(aDataStore, a
     clearInterval(interval);
     deferred.reject(new Error("Timed out while waiting for data"));
   }, WDA_DEFAULT_GIVE_UP_TIMEOUT);
 
   return deferred.promise;
 };
 
 const WDA_DEFAULT_VERIFY_INTERVAL = 50; // ms
-const WDA_DEFAULT_GIVE_UP_TIMEOUT = 2000; // ms
+
+// Use longer timeout during testing as the tests need this process to succeed
+// and two seconds is quite short on slow debug builds. The timeout here should
+// be at least equal to the general mochitest timeout of 45 seconds so that this
+// never gets hit during testing.
+const WDA_DEFAULT_GIVE_UP_TIMEOUT = gDevTools.testing ? 45000 : 2000; // ms
 
 /**
  * Helper method for debugging.
  * @param string
  */
 function dumpn(str) {
   if (wantLogging) {
     dump("NET-FRONTEND: " + str + "\n");
--- a/browser/devtools/styleinspector/computed-view.js
+++ b/browser/devtools/styleinspector/computed-view.js
@@ -1240,35 +1240,37 @@ PropertyView.prototype = {
     if (this.matchedExpanded && hasMatchedSelectors) {
       return this.tree.pageStyle.getMatchedSelectors(this.tree.viewedElement, this.name).then(matched => {
         if (!this.matchedExpanded) {
           return;
         }
 
         this._matchedSelectorResponse = matched;
 
-        this._buildMatchedSelectors();
+        this._buildMatchedSelectors()
+            .then(() => {
+              this.tree.inspector.emit("computed-view-property-expanded");
+            });
         this.matchedExpander.setAttribute("open", "");
-
-        this.tree.inspector.emit("computed-view-property-expanded");
       }).then(null, console.error);
     } else {
       this.matchedSelectorsContainer.innerHTML = "";
       this.matchedExpander.removeAttribute("open");
       this.tree.inspector.emit("computed-view-property-collapsed");
       return promise.resolve(undefined);
     }
   },
 
   get matchedSelectors()
   {
     return this._matchedSelectorResponse;
   },
 
   _buildMatchedSelectors: function() {
+    let promises = [];
     let frag = this.element.ownerDocument.createDocumentFragment();
 
     for (let selector of this.matchedSelectorViews) {
       let p = createChild(frag, "p");
       let span = createChild(p, "span", {
         class: "rule-link"
       });
       let link = createChild(span, "a", {
@@ -1287,19 +1289,21 @@ PropertyView.prototype = {
         class: "rule-text theme-fg-color3 " + selector.statusClass,
         title: selector.statusText,
         textContent: selector.sourceText
       });
       let valueSpan = createChild(status, "span", {
         class: "other-property-value theme-fg-color1"
       });
       valueSpan.appendChild(selector.outputFragment);
+      promises.push(selector.ready);
     }
 
     this.matchedSelectorsContainer.appendChild(frag);
+    return promise.all(promises);
   },
 
   /**
    * Provide access to the matched SelectorViews that we are currently
    * displaying.
    */
   get matchedSelectorViews()
   {
@@ -1386,17 +1390,17 @@ function SelectorView(aTree, aSelectorIn
 {
   this.tree = aTree;
   this.selectorInfo = aSelectorInfo;
   this._cacheStatusNames();
 
   this.openStyleEditor = this.openStyleEditor.bind(this);
   this.maybeOpenStyleEditor = this.maybeOpenStyleEditor.bind(this);
 
-  this.updateSourceLink();
+  this.ready = this.updateSourceLink();
 }
 
 /**
  * Decode for cssInfo.rule.status
  * @see SelectorView.prototype._cacheStatusNames
  * @see CssLogic.STATUS
  */
 SelectorView.STATUS_NAMES = [
--- a/browser/devtools/webide/content/webide.js
+++ b/browser/devtools/webide/content/webide.js
@@ -185,17 +185,17 @@ let UI = {
         this.updateConnectionTelemetry();
         break;
       case "before-project":
         if (!this.canCloseProject())  {
           details.cancel();
         }
         break;
       case "project":
-        this._updatePromise = Task.spawn(function() {
+        this._updatePromise = Task.spawn(function*() {
           UI.updateTitle();
           yield UI.destroyToolbox();
           UI.updateCommands();
           UI.updateProjectButton();
           UI.openProject();
           yield UI.autoStartProject();
           UI.autoOpenToolbox();
           UI.saveLastSelectedProject();
--- a/browser/devtools/webide/modules/app-manager.js
+++ b/browser/devtools/webide/modules/app-manager.js
@@ -672,17 +672,17 @@ let AppManager = exports.AppManager = {
       });
 
       yield validation.validate();
 
       if (validation.manifest) {
         let manifest = validation.manifest;
         let iconPath;
         if (manifest.icons) {
-          let size = Object.keys(manifest.icons).sort(function(a, b) b - a)[0];
+          let size = Object.keys(manifest.icons).sort((a, b) => b - a)[0];
           if (size) {
             iconPath = manifest.icons[size];
           }
         }
         if (!iconPath) {
           project.icon = AppManager.DEFAULT_PROJECT_ICON;
         } else {
           if (project.type == "hosted") {
--- a/browser/devtools/webide/modules/simulator-process.js
+++ b/browser/devtools/webide/modules/simulator-process.js
@@ -30,17 +30,19 @@ loader.lazyGetter(this, "OS", () => {
       return "";
   }
 });
 
 function SimulatorProcess() {}
 SimulatorProcess.prototype = {
 
   // Check if B2G is running.
-  get isRunning() !!this.process,
+  get isRunning() {
+    return !!this.process;
+  },
 
   // Start the process and connect the debugger client.
   run() {
 
     // Resolve B2G binary.
     let b2g = this.b2gBinary;
     if (!b2g || !b2g.exists()) {
       throw Error("B2G executable not found.");
--- a/browser/devtools/webide/test/browser_tabs.js
+++ b/browser/devtools/webide/test/browser_tabs.js
@@ -3,17 +3,17 @@
 "use strict";
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webide/test/doc_tabs.html";
 
 function test() {
   waitForExplicitFinish();
   requestCompleteLog();
 
-  Task.spawn(function() {
+  Task.spawn(function*() {
     const { DebuggerServer } =
       Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
 
     // Since we test the connections set below, destroy the server in case it
     // was left open.
     DebuggerServer.destroy();
     DebuggerServer.init();
     DebuggerServer.addBrowserActors();
--- a/browser/devtools/webide/test/browser_widget.js
+++ b/browser/devtools/webide/test/browser_widget.js
@@ -1,15 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 function test() {
   waitForExplicitFinish();
-  Task.spawn(function() {
+  Task.spawn(function*() {
     let win = yield openWebIDE();
     ok(document.querySelector("#webide-button"), "Found WebIDE button");
     Services.prefs.setBoolPref("devtools.webide.widget.enabled", false);
     ok(!document.querySelector("#webide-button"), "WebIDE button uninstalled");
     yield closeWebIDE(win);
     Services.prefs.clearUserPref("devtools.webide.widget.enabled");
   }).then(finish, handleError);
 }
--- a/browser/devtools/webide/test/sidebars/browser_tabs.js
+++ b/browser/devtools/webide/test/sidebars/browser_tabs.js
@@ -3,17 +3,17 @@
 "use strict";
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webide/test/doc_tabs.html";
 
 function test() {
   waitForExplicitFinish();
   requestCompleteLog();
 
-  Task.spawn(function() {
+  Task.spawn(function*() {
     const { DebuggerServer } =
       Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
 
     Services.prefs.setBoolPref("devtools.webide.sidebars", true);
 
     // Since we test the connections set below, destroy the server in case it
     // was left open.
     DebuggerServer.destroy();
--- a/browser/locales/en-US/chrome/browser/newTab.dtd
+++ b/browser/locales/en-US/chrome/browser/newTab.dtd
@@ -7,14 +7,12 @@
 <!ENTITY newtab.customize.classic "Show your top sites">
 <!ENTITY newtab.customize.cog.enhanced "Include suggested sites">
 <!ENTITY newtab.customize.cog.title "New Tab Controls">
 <!ENTITY newtab.customize.cog.learn "Learn about New Tab">
 <!ENTITY newtab.customize.title "Customize your New Tab page">
 <!ENTITY newtab.customize.suggested "Show suggested and your top sites">
 <!ENTITY newtab.customize.topsites "Show your top sites">
 <!ENTITY newtab.customize.blank2 "Show blank page">
-<!ENTITY newtab.customize.what "What is this page?">
-<!ENTITY newtab.intro.header "What is this page?">
 <!ENTITY newtab.undo.removedLabel "Thumbnail removed.">
 <!ENTITY newtab.undo.undoButton "Undo.">
 <!ENTITY newtab.undo.restoreButton "Restore All.">
 <!ENTITY newtab.undo.closeTooltip "Hide">
--- a/browser/themes/linux/newtab/newTab.css
+++ b/browser/themes/linux/newtab/newTab.css
@@ -9,12 +9,11 @@
   color: rgb(221,72,20);
 }
 
 #newtab-undo-close-button {
   height: 16px;
   width: 16px;
 }
 
-#newtab-intro-panel,
 .newtab-title {
   font-family: sans-serif;
 }
--- a/browser/themes/osx/newtab/newTab.css
+++ b/browser/themes/osx/newtab/newTab.css
@@ -4,12 +4,11 @@
 
 %include ../../shared/newtab/newTab.inc.css
 
 
 .newtab-undo-button {
   color: rgb(20,79,174);
 }
 
-#newtab-intro-panel,
 .newtab-title {
   font-family: Lucida Grande;
 }
--- a/browser/themes/shared/aboutSessionRestore.css
+++ b/browser/themes/shared/aboutSessionRestore.css
@@ -30,9 +30,9 @@ treechildren::-moz-tree-image(checked, s
   list-style-image: url("chrome://global/skin/in-content/check.svg#check-inverted");
 }
 
 treechildren::-moz-tree-image(partial) {
   list-style-image: url("chrome://global/skin/in-content/check-partial.svg#check-partial");
 }
 treechildren::-moz-tree-image(partial, selected) {
   list-style-image: url("chrome://global/skin/in-content/check-partial.svg#check-partial-inverted");
-}
\ No newline at end of file
+}
--- a/browser/themes/shared/newtab/newTab.inc.css
+++ b/browser/themes/shared/newtab/newTab.inc.css
@@ -150,17 +150,16 @@
 .newtab-site[type=enhanced] .newtab-thumbnail,
 .newtab-site[type=organic] .newtab-thumbnail,
 .newtab-site[type=sponsored] .newtab-thumbnail {
   background-position: center center;
   background-size: auto;
 }
 
 /* TITLES */
-#newtab-intro-what,
 .newtab-sponsored,
 .newtab-title,
 .newtab-suggested  {
   color: #5c5c5c;
 }
 
 .newtab-suggested[active] {
   background-color: rgba(51, 51, 51, 0.95);
--- a/browser/themes/windows/newtab/newTab.css
+++ b/browser/themes/windows/newtab/newTab.css
@@ -8,12 +8,11 @@
 .newtab-undo-button {
   color: rgb(0,102,204);
 }
 
 .newtab-undo-button > .button-box {
   padding: 0;
 }
 
-#newtab-intro-panel,
 .newtab-title {
   font-family: Segoe UI;
 }
--- a/dom/apps/AppsUtils.jsm
+++ b/dom/apps/AppsUtils.jsm
@@ -886,28 +886,27 @@ ManifestHelper.prototype = {
 
   get permissions() {
     if (this._manifest.permissions) {
       return this._manifest.permissions;
     }
     return {};
   },
 
-  get biggestIconURL() {
+  biggestIconURL: function(predicate) {
     let icons = this._localeProp("icons");
     if (!icons) {
       return null;
     }
 
-    let iconSizes = Object.keys(icons);
+    let iconSizes = Object.keys(icons).sort((a, b) => a - b)
+                          .filter(predicate || (() => true));
     if (iconSizes.length == 0) {
       return null;
     }
-
-    iconSizes.sort((a, b) => a - b);
     let biggestIconSize = iconSizes.pop();
     let biggestIcon = icons[biggestIconSize];
     let biggestIconURL = this._baseURI.resolve(biggestIcon);
 
     return biggestIconURL;
   },
 
   iconURLForSize: function(aSize) {
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -4237,17 +4237,17 @@ nsDocument::AddStyleSheetToStyleSets(nsI
     init.memberName = argName;                                                \
                                                                               \
     nsRefPtr<className> event =                                               \
       className::Constructor(this, NS_LITERAL_STRING(type), init);            \
     event->SetTrusted(true);                                                  \
     event->SetTarget(this);                                                   \
     nsRefPtr<AsyncEventDispatcher> asyncDispatcher =                          \
       new AsyncEventDispatcher(this, event);                                  \
-    asyncDispatcher->mDispatchChromeOnly = true;                              \
+    asyncDispatcher->mOnlyChromeDispatch = true;                              \
     asyncDispatcher->PostDOMEvent();                                          \
   } while (0);
 
 void
 nsDocument::NotifyStyleSheetAdded(nsIStyleSheet* aSheet, bool aDocumentSheet)
 {
   NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (this, aSheet, aDocumentSheet));
 
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -18,67 +18,42 @@ using namespace dom;
 
 /******************************************************************************
  * mozilla::AsyncEventDispatcher
  ******************************************************************************/
 
 AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget,
                                            WidgetEvent& aEvent)
   : mTarget(aTarget)
-  , mDispatchChromeOnly(false)
+  , mOnlyChromeDispatch(false)
 {
   MOZ_ASSERT(mTarget);
   EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, EmptyString(),
                                getter_AddRefs(mEvent));
   NS_ASSERTION(mEvent, "Should never fail to create an event");
   mEvent->DuplicatePrivateData();
   mEvent->SetTrusted(aEvent.mFlags.mIsTrusted);
 }
 
 NS_IMETHODIMP
 AsyncEventDispatcher::Run()
 {
-  if (mEvent) {
-    if (mDispatchChromeOnly) {
-      MOZ_ASSERT(mEvent->InternalDOMEvent()->IsTrusted());
-
-      nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
-      MOZ_ASSERT(node, "ChromeOnly dispatch supported with Node targets only!");
-      nsPIDOMWindow* window = node->OwnerDoc()->GetWindow();
-      if (!window) {
-        return NS_ERROR_INVALID_ARG;
-      }
-
-      nsCOMPtr<EventTarget> target = window->GetParentTarget();
-      if (!target) {
-        return NS_ERROR_INVALID_ARG;
-      }
-      EventDispatcher::DispatchDOMEvent(target, nullptr, mEvent,
-                                        nullptr, nullptr);
-    } else {
-      bool defaultActionEnabled; // This is not used because the caller is async
-      mTarget->DispatchEvent(mEvent, &defaultActionEnabled);
-    }
-  } else {
-    if (mDispatchChromeOnly) {
-      nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
-      MOZ_ASSERT(node, "ChromeOnly dispatch supported with Node targets only!");
-      nsContentUtils::DispatchChromeEvent(node->OwnerDoc(), node, mEventType,
-                                          mBubbles, false);
-    } else {
-      nsCOMPtr<nsIDOMEvent> event;
-      NS_NewDOMEvent(getter_AddRefs(event), mTarget, nullptr, nullptr);
-      nsresult rv = event->InitEvent(mEventType, mBubbles, false);
-      NS_ENSURE_SUCCESS(rv, rv);
-      event->SetTrusted(true);
-      bool dummy;
-      mTarget->DispatchEvent(event, &dummy);
-    }
+  nsCOMPtr<nsIDOMEvent> event = mEvent;
+  if (!event) {
+    NS_NewDOMEvent(getter_AddRefs(event), mTarget, nullptr, nullptr);
+    nsresult rv = event->InitEvent(mEventType, mBubbles, false);
+    NS_ENSURE_SUCCESS(rv, rv);
+    event->SetTrusted(true);
   }
-
+  if (mOnlyChromeDispatch) {
+    MOZ_ASSERT(event->InternalDOMEvent()->IsTrusted());
+    event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
+  }
+  bool dummy;
+  mTarget->DispatchEvent(event, &dummy);
   return NS_OK;
 }
 
 nsresult
 AsyncEventDispatcher::PostDOMEvent()
 {
   nsRefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
   return NS_DispatchToCurrentThread(this);
--- a/dom/events/AsyncEventDispatcher.h
+++ b/dom/events/AsyncEventDispatcher.h
@@ -23,52 +23,58 @@ namespace mozilla {
  * For example, you may need to fire an event from within layout, but
  * want to ensure that the event handler doesn't mutate the DOM at
  * the wrong time, in order to avoid resulting instability.
  */
  
 class AsyncEventDispatcher : public nsRunnable
 {
 public:
+  /**
+   * If aOnlyChromeDispatch is true, the event is dispatched to only
+   * chrome node. In that case, if aTarget is already a chrome node,
+   * the event is dispatched to it, otherwise the dispatch path starts
+   * at the first chrome ancestor of that target.
+   */
   AsyncEventDispatcher(nsINode* aTarget, const nsAString& aEventType,
-                       bool aBubbles, bool aDispatchChromeOnly)
+                       bool aBubbles, bool aOnlyChromeDispatch)
     : mTarget(aTarget)
     , mEventType(aEventType)
     , mBubbles(aBubbles)
-    , mDispatchChromeOnly(aDispatchChromeOnly)
+    , mOnlyChromeDispatch(aOnlyChromeDispatch)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, const nsAString& aEventType,
                        bool aBubbles)
     : mTarget(aTarget)
     , mEventType(aEventType)
     , mBubbles(aBubbles)
-    , mDispatchChromeOnly(false)
+    , mOnlyChromeDispatch(false)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, nsIDOMEvent* aEvent)
     : mTarget(aTarget)
     , mEvent(aEvent)
-    , mDispatchChromeOnly(false)
+    , mOnlyChromeDispatch(false)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, WidgetEvent& aEvent);
 
   NS_IMETHOD Run() override;
   nsresult PostDOMEvent();
   void RunDOMEventWhenSafe();
 
   nsCOMPtr<dom::EventTarget> mTarget;
   nsCOMPtr<nsIDOMEvent> mEvent;
   nsString              mEventType;
   bool                  mBubbles;
-  bool                  mDispatchChromeOnly;
+  bool                  mOnlyChromeDispatch;
 };
 
 class LoadBlockingAsyncEventDispatcher final : public AsyncEventDispatcher
 {
 public:
   LoadBlockingAsyncEventDispatcher(nsINode* aEventNode,
                                    const nsAString& aEventType,
                                    bool aBubbles, bool aDispatchChromeOnly)
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -477,16 +477,23 @@ NS_IMETHODIMP
 Event::StopImmediatePropagation()
 {
   mEvent->mFlags.mPropagationStopped = true;
   mEvent->mFlags.mImmediatePropagationStopped = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+Event::StopCrossProcessForwarding()
+{
+  mEvent->mFlags.mNoCrossProcessBoundaryForwarding = true;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 Event::GetIsTrusted(bool* aIsTrusted)
 {
   *aIsTrusted = IsTrusted();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Event::PreventDefault()
--- a/dom/events/Event.h
+++ b/dom/events/Event.h
@@ -304,16 +304,17 @@ private:
   NS_IMETHOD GetType(nsAString& aType) override { return _to GetType(aType); } \
   NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) override { return _to GetTarget(aTarget); } \
   NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) override { return _to GetCurrentTarget(aCurrentTarget); } \
   NS_IMETHOD GetEventPhase(uint16_t* aEventPhase) override { return _to GetEventPhase(aEventPhase); } \
   NS_IMETHOD GetBubbles(bool* aBubbles) override { return _to GetBubbles(aBubbles); } \
   NS_IMETHOD GetCancelable(bool* aCancelable) override { return _to GetCancelable(aCancelable); } \
   NS_IMETHOD GetTimeStamp(DOMTimeStamp* aTimeStamp) override { return _to GetTimeStamp(aTimeStamp); } \
   NS_IMETHOD StopPropagation(void) override { return _to StopPropagation(); } \
+  NS_IMETHOD StopCrossProcessForwarding(void) override { return _to StopCrossProcessForwarding(); } \
   NS_IMETHOD PreventDefault(void) override { return _to PreventDefault(); } \
   NS_IMETHOD InitEvent(const nsAString& eventTypeArg, bool canBubbleArg, bool cancelableArg) override { return _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg); } \
   NS_IMETHOD GetDefaultPrevented(bool* aDefaultPrevented) override { return _to GetDefaultPrevented(aDefaultPrevented); } \
   NS_IMETHOD StopImmediatePropagation(void) override { return _to StopImmediatePropagation(); } \
   NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) override { return _to GetOriginalTarget(aOriginalTarget); } \
   NS_IMETHOD GetExplicitOriginalTarget(nsIDOMEventTarget** aExplicitOriginalTarget) override { return _to GetExplicitOriginalTarget(aExplicitOriginalTarget); } \
   NS_IMETHOD GetPreventDefault(bool* aRetval) override { return _to GetPreventDefault(aRetval); } \
   NS_IMETHOD GetIsTrusted(bool* aIsTrusted) override { return _to GetIsTrusted(aIsTrusted); } \
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -35,17 +35,17 @@ class EventTarget;
  * The nsIDOMEvent interface is the primary datatype for all events in
  * the Document Object Model.
  *
  * For more information on this interface please see 
  * http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html and
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[builtinclass, uuid(02d54f52-a1f5-4ad2-b560-36f14012935e)]
+[builtinclass, uuid(63857daf-c084-4ea6-a8b9-6812e3176991)]
 interface nsIDOMEvent : nsISupports
 {
   // PhaseType
   /**
    * The event isn't being dispatched.
    */
   const unsigned short      NONE                           = 0;
   /**
@@ -208,16 +208,17 @@ interface nsIDOMEvent : nsISupports
   [notxpcom] boolean IsDispatchStopped();
   [notxpcom] WidgetEventPtr GetInternalNSEvent();
   [noscript,notxpcom] void SetTrusted(in boolean aTrusted);
   [notxpcom] void Serialize(in IPCMessagePtr aMsg,
                             in boolean aSerializeInterfaceType);
   [notxpcom] boolean Deserialize(in ConstIPCMessagePtr aMsg, out voidPtr aIter);
   [noscript,notxpcom] void SetOwner(in EventTargetPtr aOwner);
   [notxpcom] DOMEventPtr InternalDOMEvent();
+  [noscript] void stopCrossProcessForwarding();
 };
 
 %{C++
 
 nsresult
 NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult,
                mozilla::dom::EventTarget* aOwner,
                nsPresContext* aPresContext,
--- a/dom/manifest/ManifestProcessor.jsm
+++ b/dom/manifest/ManifestProcessor.jsm
@@ -16,17 +16,17 @@
  * icons and splash_screens.
  *
  * TODO: The constructor should accept the UA's supported orientations.
  * TODO: The constructor should accept the UA's supported display modes.
  * TODO: hook up developer tools to console. (1086997).
  */
 /*exported EXPORTED_SYMBOLS */
 /*JSLint options in comment below: */
-/*globals Components, XPCOMUtils*/
+/*globals Components, XPCOMUtils, Intl*/
 'use strict';
 this.EXPORTED_SYMBOLS = ['ManifestProcessor']; // jshint ignore:line
 const imports = {};
 const {
   utils: Cu
 } = Components;
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.importGlobalProperties(['URL']);
@@ -95,16 +95,17 @@ ManifestProcessor.prototype = {
     if (typeof rawManifest !== 'object' || rawManifest === null) {
       let msg = 'Manifest needs to be an object.';
       console.warn(msg);
       rawManifest = {};
     }
     const extractor = new ManifestValueExtractor(console);
     const imgObjProcessor = new ImgObjProcessor(console, extractor);
     const processedManifest = {
+      'lang': processLangMember(rawManifest),
       'start_url': processStartURLMember(rawManifest, manifestURL, docURL),
       'display': processDisplayMember(rawManifest),
       'orientation': processOrientationMember(rawManifest),
       'name': processNameMember(rawManifest),
       'icons': imgObjProcessor.process(
         rawManifest, manifestURL, 'icons'
       ),
       'splash_screens': imgObjProcessor.process(
@@ -241,12 +242,31 @@ ManifestProcessor.prototype = {
         objectName: 'manifest',
         object: aManifest,
         property: 'theme_color',
         expectedType: 'string',
         trim: true
       };
       return extractor.extractColorValue(spec);
     }
+
+    function processLangMember(aManifest) {
+      const spec = {
+        objectName: 'manifest',
+        object: aManifest,
+        property: 'lang',
+        expectedType: 'string',
+        trim: true
+      };
+      let tag = extractor.extractValue(spec);
+      // TODO: Check if tag is structurally valid.
+      //       Cannot do this because we don't support Intl API on Android.
+      //       https://bugzilla.mozilla.org/show_bug.cgi?id=864843
+      //       https://github.com/tc39/ecma402/issues/5
+      // TODO: perform canonicalization on the tag.
+      //       Can't do this today because there is no direct means to
+      //       access canonicalization algorithms through Intl API.
+      //       https://github.com/tc39/ecma402/issues/5
+      return tag;
+    }
   }
 };
-
 this.ManifestProcessor = ManifestProcessor; // jshint ignore:line
--- a/dom/manifest/test/mochitest.ini
+++ b/dom/manifest/test/mochitest.ini
@@ -1,19 +1,19 @@
 [DEFAULT]
 support-files =
 	common.js
 	resource.sjs
 	manifestLoader.html
-
 [test_ImageObjectProcessor_background_color.html]
 [test_ImageObjectProcessor_density.html]
 [test_ImageObjectProcessor_sizes.html]
 [test_ImageObjectProcessor_src.html]
 [test_ImageObjectProcessor_type.html]
 [test_ManifestProcessor_display.html]
 [test_ManifestProcessor_icons.html]
 [test_ManifestProcessor_JSON.html]
+[test_ManifestProcessor_lang.html]
 [test_ManifestProcessor_name_and_short_name.html]
 [test_ManifestProcessor_orientation.html]
-[test_ManifestProcessor_start_url.html]
 [test_ManifestProcessor_scope.html]
 [test_ManifestProcessor_splash_screens.html]
+[test_ManifestProcessor_start_url.html]
new file mode 100644
--- /dev/null
+++ b/dom/manifest/test/test_ManifestProcessor_lang.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML>
+<!--
+Bug 1143879 - Implement lang member of Web manifest
+https://bugzilla.mozilla.org/show_bug.cgi?id=1143879
+-->
+<meta charset="utf-8">
+<title>Test for Bug 1143879 - Implement lang member of Web manifest</title>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script src="common.js"></script>
+<script>
+/**
+ * lang member
+ * https://w3c.github.io/manifest/#lang-member
+ **/
+/*globals is, typeTests, data, processor, seperators, lineTerminators, todo_is*/
+'use strict';
+// Type checks: checks that only strings are accepted.
+for (var type of typeTests) {
+  var expected = `Expect non-string to be undefined.`;
+  data.jsonText = JSON.stringify({
+    lang: type
+  });
+  var result = processor.process(data);
+  is(result.lang, undefined, expected);
+}
+
+// Test valid language tags - derived from IANA and BCP-47 spec
+// and our Intl.js implementation.
+var validTags = [
+  'aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar', 'as', 'av', 'ay', 'az',
+  'ba', 'be', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'br', 'bs', 'ca', 'ce',
+  'ch', 'co', 'cr', 'cs', 'cu', 'cv', 'cy', 'da', 'de', 'dv', 'dz', 'ee',
+  'el', 'en', 'eo', 'es', 'et', 'eu', 'fa', 'ff', 'fi', 'fj', 'fo', 'fr',
+  'fy', 'ga', 'gd', 'gl', 'gn', 'gu', 'gv', 'ha', 'he', 'hi', 'ho', 'hr',
+  'ht', 'hu', 'hy', 'hz', 'ia', 'id', 'ie', 'ig', 'ik', 'in', 'io',
+  'is', 'it', 'iu', 'iw', 'ja', 'ji', 'jv', 'jw', 'ka', 'kg', 'ki', 'kj',
+  'kk', 'kl', 'km', 'kn', 'ko', 'kr', 'ks', 'ku', 'kv', 'kw', 'ky', 'la',
+  'lb', 'lg', 'li', 'ln', 'lo', 'lt', 'lu', 'lv', 'mg', 'mh', 'mi', 'mk',
+  'ml', 'mn', 'mo', 'mr', 'ms', 'mt', 'my', 'na', 'nb', 'nd', 'ne', 'ng',
+  'nl', 'nn', 'no', 'nr', 'nv', 'ny', 'oc', 'oj', 'om', 'or', 'os', 'pa',
+  'pi', 'pl', 'ps', 'pt', 'qu', 'rm', 'rn', 'ro', 'ru', 'rw', 'sa', 'sc',
+  'sd', 'se', 'sg', 'sh', 'si', 'sk', 'sl', 'sm', 'sn', 'so', 'sq', 'sr',
+  'ss', 'st', 'su', 'sv', 'sw', 'ta', 'te', 'tg', 'th', 'ti', 'tk', 'tl',
+  'tn', 'to', 'tr', 'ts', 'tt', 'tw', 'ty', 'ug', 'uk', 'ur', 'uz', 've',
+  'vi', 'vo', 'wa', 'wo', 'xh', 'yi', 'yo', 'za', 'zh', 'zu', 'en-US',
+  'jp-JS', 'pt-PT', 'pt-BR', 'de-CH', 'de-DE-1901', 'es-419', 'sl-IT-nedis',
+  'en-US-boont', 'mn-Cyrl-MN', 'x-fr-CH', 'sr-Cyrl', 'sr-Latn',
+  'hy-Latn-IT-arevela', 'zh-TW', 'en-GB-boont-r-extended-sequence-x-private',
+  'zh-nan-hans-bu-variant2-variant1-u-ca-chinese-t-zh-latn-x-private',
+  'zh-cmn-Hans-CN', 'cmn-Hans-CN', 'zh-yue-HK', 'yue-HK',
+  'de-CH-x-phonebk', 'az-Arab-x-AZE-derbend', 'x-whatever',
+  'qaa-Qaaa-QM-x-southern'
+];
+for (var tag of validTags) {
+  var expected = `Expect lang to be ${tag}.`;
+  data.jsonText = JSON.stringify({
+    lang: tag
+  });
+  var result = processor.process(data);
+  is(result.lang, tag, expected);
+}
+
+// trim tests - check that language tags get trimmed properly.
+for (var tag of validTags) {
+  var expected = `Expect trimmed tag to be returned.`;
+  var expandedtag = seperators + lineTerminators + tag;
+  expandedtag += lineTerminators + seperators;
+  data.jsonText = JSON.stringify({
+    lang: expandedtag
+  });
+  var result = processor.process(data);
+  is(result.lang, tag, expected);
+}
+
+//Invalid language tags, derived from BCP-47 and made up.
+var invalidTags = [
+  'de-419-DE', ' a-DE ', 'ar-a-aaa-b-bbb-a-ccc', 'sdafsdfaadsfdsf', 'i',
+  'i-phone', 'en US', 'EN-*-US-JP', 'JA-INVALID-TAG', '123123123'
+];
+for (var item of invalidTags) {
+  var expected = `Expect invalid tag (${item}) to be treated as undefined.`;
+  data.jsonText = JSON.stringify({
+    lang: item
+  });
+  var result = processor.process(data);
+  todo_is(result.lang, undefined, expected);
+}
+
+// Canonical form conversion tests. We convert the following tags, which are in
+// canonical form, to upper case and expect the processor to return them
+// in canonical form.
+var canonicalTags = [
+  'jp-JS', 'pt-PT', 'pt-BR', 'de-CH', 'de-DE-1901', 'es-419', 'sl-IT-nedis',
+  'en-US-boont', 'mn-Cyrl-MN', 'x-fr-CH', 'sr-Cyrl', 'sr-Latn',
+  'hy-Latn-IT-arevela', 'zh-TW', 'en-GB-boont-r-extended-sequence-x-private',
+  'zh-cmn-Hans-CN', 'cmn-Hans-CN', 'zh-yue-HK', 'yue-HK',
+  'de-CH-x-phonebk', 'az-Arab-x-AZE-derbend', 'x-whatever',
+  'qaa-Qaaa-QM-x-southern'
+];
+
+for (var tag of canonicalTags) {
+  var uppedTag = tag.toUpperCase();
+  var expected = `Expect tag (${uppedTag}) to be in canonical form (${tag}).`;
+  data.jsonText = JSON.stringify({
+    lang: uppedTag
+  });
+  var result = processor.process(data);
+  todo_is(result.lang, tag, expected);
+}
+
+</script>
--- a/dom/media/DecodedStream.cpp
+++ b/dom/media/DecodedStream.cpp
@@ -154,21 +154,16 @@ private:
     }
   }
 
   // Main thread only
   DecodedStream* mDecodedStream;
   nsRefPtr<MediaStream> mStream;
 };
 
-OutputStreamData::OutputStreamData()
-{
-  //
-}
-
 OutputStreamData::~OutputStreamData()
 {
   mListener->Forget();
 }
 
 void
 OutputStreamData::Init(DecodedStream* aDecodedStream, ProcessedMediaStream* aStream)
 {
@@ -190,34 +185,103 @@ DecodedStream::GetData()
   return mData.get();
 }
 
 void
 DecodedStream::DestroyData()
 {
   MOZ_ASSERT(NS_IsMainThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
+
+  // Avoid the redundant blocking to output stream.
+  if (!mData) {
+    return;
+  }
+
+  // All streams are having their SourceMediaStream disconnected, so they
+  // need to be explicitly blocked again.
+  auto& outputStreams = OutputStreams();
+  for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
+    OutputStreamData& os = outputStreams[i];
+    // Explicitly remove all existing ports.
+    // This is not strictly necessary but it's good form.
+    MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
+    os.mPort->Destroy();
+    os.mPort = nullptr;
+    // During cycle collection, nsDOMMediaStream can be destroyed and send
+    // its Destroy message before this decoder is destroyed. So we have to
+    // be careful not to send any messages after the Destroy().
+    if (os.mStream->IsDestroyed()) {
+      // Probably the DOM MediaStream was GCed. Clean up.
+      outputStreams.RemoveElementAt(i);
+    } else {
+      os.mStream->ChangeExplicitBlockerCount(1);
+    }
+  }
+
   mData = nullptr;
 }
 
 void
 DecodedStream::RecreateData(int64_t aInitialTime, SourceMediaStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
   MOZ_ASSERT(!mData);
+
   mData.reset(new DecodedStreamData(aInitialTime, aStream));
+
+  // Note that the delay between removing ports in DestroyDecodedStream
+  // and adding new ones won't cause a glitch since all graph operations
+  // between main-thread stable states take effect atomically.
+  auto& outputStreams = OutputStreams();
+  for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
+    OutputStreamData& os = outputStreams[i];
+    MOZ_ASSERT(!os.mStream->IsDestroyed(), "Should've been removed in DestroyData()");
+    Connect(&os);
+  }
 }
 
 nsTArray<OutputStreamData>&
 DecodedStream::OutputStreams()
 {
   GetReentrantMonitor().AssertCurrentThreadIn();
   return mOutputStreams;
 }
 
 ReentrantMonitor&
 DecodedStream::GetReentrantMonitor()
 {
   return mMonitor;
 }
 
+void
+DecodedStream::Connect(OutputStreamData* aStream)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  GetReentrantMonitor().AssertCurrentThreadIn();
+  NS_ASSERTION(!aStream->mPort, "Already connected?");
+
+  // The output stream must stay in sync with the decoded stream, so if
+  // either stream is blocked, we block the other.
+  aStream->mPort = aStream->mStream->AllocateInputPort(mData->mStream,
+      MediaInputPort::FLAG_BLOCK_INPUT | MediaInputPort::FLAG_BLOCK_OUTPUT);
+  // Unblock the output stream now. While it's connected to DecodedStream,
+  // DecodedStream is responsible for controlling blocking.
+  aStream->mStream->ChangeExplicitBlockerCount(-1);
+}
+
+void
+DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  GetReentrantMonitor().AssertCurrentThreadIn();
+
+  OutputStreamData* os = OutputStreams().AppendElement();
+  os->Init(this, aStream);
+  Connect(os);
+  if (aFinishWhenEnded) {
+    // Ensure that aStream finishes the moment mDecodedStream does.
+    aStream->SetAutofinish(true);
+  }
+}
+
 } // namespace mozilla
--- a/dom/media/DecodedStream.h
+++ b/dom/media/DecodedStream.h
@@ -14,17 +14,16 @@
 
 namespace mozilla {
 
 class MediaInputPort;
 class SourceMediaStream;
 class ProcessedMediaStream;
 class DecodedStream;
 class DecodedStreamGraphListener;
-class OutputStreamData;
 class OutputStreamListener;
 class ReentrantMonitor;
 
 namespace layers {
 class Image;
 }
 
 /*
@@ -77,39 +76,37 @@ public:
   bool mHaveBlockedForStateMachineNotPlaying;
   // True if we need to send a compensation video frame to ensure the
   // StreamTime going forward.
   bool mEOSVideoCompensation;
 };
 
 class OutputStreamData {
 public:
-  // Compiler-generated default constructor needs the complete definition
-  // of OutputStreamListener when constructing OutputStreamData. Provide our
-  // own default constructor for forward declaration of OutputStreamListener
-  // to work.
-  OutputStreamData();
   ~OutputStreamData();
   void Init(DecodedStream* aDecodedStream, ProcessedMediaStream* aStream);
   nsRefPtr<ProcessedMediaStream> mStream;
   // mPort connects DecodedStreamData::mStream to our mStream.
   nsRefPtr<MediaInputPort> mPort;
   nsRefPtr<OutputStreamListener> mListener;
 };
 
 class DecodedStream {
 public:
   explicit DecodedStream(ReentrantMonitor& aMonitor);
   DecodedStreamData* GetData();
   void DestroyData();
   void RecreateData(int64_t aInitialTime, SourceMediaStream* aStream);
   nsTArray<OutputStreamData>& OutputStreams();
   ReentrantMonitor& GetReentrantMonitor();
+  void Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
 
 private:
+  void Connect(OutputStreamData* aStream);
+
   UniquePtr<DecodedStreamData> mData;
   // Data about MediaStreams that are being fed by the decoder.
   nsTArray<OutputStreamData> mOutputStreams;
   ReentrantMonitor& mMonitor;
 };
 
 } // namespace mozilla
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -284,77 +284,30 @@ void MediaDecoder::Pause()
 }
 
 void MediaDecoder::SetVolume(double aVolume)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mVolume = aVolume;
 }
 
-void MediaDecoder::ConnectDecodedStreamToOutputStream(OutputStreamData* aStream)
-{
-  NS_ASSERTION(!aStream->mPort, "Already connected?");
-
-  // The output stream must stay in sync with the decoded stream, so if
-  // either stream is blocked, we block the other.
-  aStream->mPort = aStream->mStream->AllocateInputPort(GetDecodedStream()->mStream,
-      MediaInputPort::FLAG_BLOCK_INPUT | MediaInputPort::FLAG_BLOCK_OUTPUT);
-  // Unblock the output stream now. While it's connected to mDecodedStream,
-  // mDecodedStream is responsible for controlling blocking.
-  aStream->mStream->ChangeExplicitBlockerCount(-1);
-}
-
 void MediaDecoder::UpdateDecodedStream()
 {
   MOZ_ASSERT(NS_IsMainThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
 
   if (GetDecodedStream()) {
     bool blockForPlayState = mPlayState != PLAY_STATE_PLAYING || mLogicallySeeking;
     if (GetDecodedStream()->mHaveBlockedForPlayState != blockForPlayState) {
       GetDecodedStream()->mStream->ChangeExplicitBlockerCount(blockForPlayState ? 1 : -1);
       GetDecodedStream()->mHaveBlockedForPlayState = blockForPlayState;
     }
   }
 }
 
-void MediaDecoder::DestroyDecodedStream()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  GetReentrantMonitor().AssertCurrentThreadIn();
-
-  // Avoid the redundant blocking to output stream.
-  if (!GetDecodedStream()) {
-    return;
-  }
-
-  // All streams are having their SourceMediaStream disconnected, so they
-  // need to be explicitly blocked again.
-  auto& outputStreams = OutputStreams();
-  for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
-    OutputStreamData& os = outputStreams[i];
-    // Explicitly remove all existing ports.
-    // This is not strictly necessary but it's good form.
-    MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
-    os.mPort->Destroy();
-    os.mPort = nullptr;
-    // During cycle collection, nsDOMMediaStream can be destroyed and send
-    // its Destroy message before this decoder is destroyed. So we have to
-    // be careful not to send any messages after the Destroy().
-    if (os.mStream->IsDestroyed()) {
-      // Probably the DOM MediaStream was GCed. Clean up.
-      outputStreams.RemoveElementAt(i);
-    } else {
-      os.mStream->ChangeExplicitBlockerCount(1);
-    }
-  }
-
-  mDecodedStream.DestroyData();
-}
-
 void MediaDecoder::UpdateStreamBlockingForStateMachinePlaying()
 {
   GetReentrantMonitor().AssertCurrentThreadIn();
   if (!GetDecodedStream()) {
     return;
   }
   bool blockForStateMachineNotPlaying =
     mDecoderStateMachine && !mDecoderStateMachine->IsPlaying();
@@ -377,30 +330,20 @@ void MediaDecoder::RecreateDecodedStream
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   DECODER_LOG("RecreateDecodedStream aStartTimeUSecs=%lld!", aStartTimeUSecs);
 
   if (!aGraph) {
     aGraph = GetDecodedStream()->mStream->Graph();
   }
-  DestroyDecodedStream();
 
+  mDecodedStream.DestroyData();
   mDecodedStream.RecreateData(aStartTimeUSecs, aGraph->CreateSourceStream(nullptr));
 
-  // Note that the delay between removing ports in DestroyDecodedStream
-  // and adding new ones won't cause a glitch since all graph operations
-  // between main-thread stable states take effect atomically.
-  auto& outputStreams = OutputStreams();
-  for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
-    OutputStreamData& os = outputStreams[i];
-    MOZ_ASSERT(!os.mStream->IsDestroyed(),
-        "Should've been removed in DestroyDecodedStream()");
-    ConnectDecodedStreamToOutputStream(&os);
-  }
   UpdateStreamBlockingForStateMachinePlaying();
 
   GetDecodedStream()->mHaveBlockedForPlayState = mPlayState != PLAY_STATE_PLAYING;
   if (GetDecodedStream()->mHaveBlockedForPlayState) {
     GetDecodedStream()->mStream->ChangeExplicitBlockerCount(1);
   }
 }
 
@@ -413,23 +356,17 @@ void MediaDecoder::AddOutputStream(Proce
   {
     ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     if (mDecoderStateMachine) {
       mDecoderStateMachine->DispatchAudioCaptured();
     }
     if (!GetDecodedStream()) {
       RecreateDecodedStream(mLogicalPosition, aStream->Graph());
     }
-    OutputStreamData* os = OutputStreams().AppendElement();
-    os->Init(&mDecodedStream, aStream);
-    ConnectDecodedStreamToOutputStream(os);
-    if (aFinishWhenEnded) {
-      // Ensure that aStream finishes the moment mDecodedStream does.
-      aStream->SetAutofinish(true);
-    }
+    mDecodedStream.Connect(aStream, aFinishWhenEnded);
   }
 
   // This can be called before Load(), in which case our mDecoderStateMachine
   // won't have been created yet and we can rely on Load() to schedule it
   // once it is created.
   if (mDecoderStateMachine) {
     // Make sure the state machine thread runs so that any buffered data
     // is fed into our stream.
@@ -570,17 +507,17 @@ void MediaDecoder::Shutdown()
 
 MediaDecoder::~MediaDecoder()
 {
   MOZ_ASSERT(NS_IsMainThread());
   {
     // Don't destroy the decoded stream until destructor in order to keep the
     // invariant that the decoded stream is always available in capture mode.
     ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
-    DestroyDecodedStream();
+    mDecodedStream.DestroyData();
   }
   MediaMemoryTracker::RemoveMediaDecoder(this);
   UnpinForSeek();
   MOZ_COUNT_DTOR(MediaDecoder);
 }
 
 nsresult MediaDecoder::OpenResource(nsIStreamListener** aStreamListener)
 {
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -390,48 +390,32 @@ public:
 
   // All MediaStream-related data is protected by mReentrantMonitor.
   // We have at most one DecodedStreamData per MediaDecoder. Its stream
   // is used as the input for each ProcessedMediaStream created by calls to
   // captureStream(UntilEnded). Seeking creates a new source stream, as does
   // replaying after the input as ended. In the latter case, the new source is
   // not connected to streams created by captureStreamUntilEnded.
 
-  /**
-   * Connects mDecodedStream->mStream to aStream->mStream.
-   */
-  void ConnectDecodedStreamToOutputStream(OutputStreamData* aStream);
-
   void UpdateDecodedStream();
 
   /**
-   * Disconnects mDecodedStream->mStream from all outputs and clears
-   * mDecodedStream.
-   */
-  void DestroyDecodedStream();
-  /**
    * Recreates mDecodedStream. Call this to create mDecodedStream at first,
    * and when seeking, to ensure a new stream is set up with fresh buffers.
    * aStartTimeUSecs is relative to the state machine's mStartTime.
    * Decoder monitor must be held.
    */
   void RecreateDecodedStream(int64_t aStartTimeUSecs,
                              MediaStreamGraph* aGraph = nullptr);
   /**
    * Call this when mDecoderStateMachine or mDecoderStateMachine->IsPlaying() changes.
    * Decoder monitor must be held.
    */
   void UpdateStreamBlockingForStateMachinePlaying();
 
-  nsTArray<OutputStreamData>& OutputStreams()
-  {
-    GetReentrantMonitor().AssertCurrentThreadIn();
-    return mDecodedStream.OutputStreams();
-  }
-
   DecodedStreamData* GetDecodedStream()
   {
     GetReentrantMonitor().AssertCurrentThreadIn();
     return mDecodedStream.GetData();
   }
 
   // Add an output stream. All decoder output will be sent to the stream.
   // The stream is initially blocked. The decoder is responsible for unblocking
--- a/dom/media/omx/MediaOmxCommonDecoder.cpp
+++ b/dom/media/omx/MediaOmxCommonDecoder.cpp
@@ -42,17 +42,17 @@ MediaOmxCommonDecoder::SetPlatformCanOff
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   mCanOffloadAudio = aCanOffloadAudio;
 }
 
 bool
 MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
 {
   return (mCanOffloadAudio && !mFallbackToStateMachine &&
-          !OutputStreams().Length() && mPlaybackRate == 1.0);
+          !GetDecodedStream() && mPlaybackRate == 1.0);
 }
 
 void
 MediaOmxCommonDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
                                         MediaDecoderEventVisibility aEventVisibility)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/gfx/layers/IMFYCbCrImage.cpp
+++ b/gfx/layers/IMFYCbCrImage.cpp
@@ -203,19 +203,19 @@ IMFYCbCrImage::GetD3D9TextureClient(Comp
                                                   mData.mCbCrSize);
 
   return mTextureClient;
 }
 
 TextureClient*
 IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
 {
-  ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11MediaDevice();
+  ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice();
   if (!device ||
-    aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) {
+      aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) {
 
     IDirect3DDevice9* d3d9device = gfxWindowsPlatform::GetPlatform()->GetD3D9Device();
     if (d3d9device && aClient->GetForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9) {
       return GetD3D9TextureClient(aClient);
     }
     return nullptr;
   }
 
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -406,17 +406,16 @@ public:
   }
 };
 
 NS_IMPL_ISUPPORTS(D3D9SharedTextureReporter, nsIMemoryReporter)
 
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mD3D11DeviceInitialized(false)
   , mIsWARP(false)
-  , mCanInitMediaDevice(false)
   , mHasDeviceReset(false)
 {
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
     mUsingGDIFonts = false;
 
     /* 
@@ -1595,65 +1594,25 @@ gfxWindowsPlatform::GetD3D11ContentDevic
   }
 
   InitD3D11Devices();
 
   return mD3D11ContentDevice;
 }
 
 ID3D11Device*
-gfxWindowsPlatform::GetD3D11MediaDevice()
+gfxWindowsPlatform::GetD3D11ImageBridgeDevice()
 {
-  if (mD3D11MediaDevice) {
-    return mD3D11MediaDevice;
-  }
-
-  if (!mCanInitMediaDevice) {
-    return nullptr;
+  if (mD3D11DeviceInitialized) {
+    return mD3D11ImageBridgeDevice;
   }
 
-  mCanInitMediaDevice = false;
-
-  nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
-  decltype(D3D11CreateDevice)* d3d11CreateDevice = (decltype(D3D11CreateDevice)*)
-    GetProcAddress(d3d11Module, "D3D11CreateDevice");
-  MOZ_ASSERT(d3d11CreateDevice);
-
-  nsTArray<D3D_FEATURE_LEVEL> featureLevels;
-  if (IsWin8OrLater()) {
-    featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
-  }
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
-
-  RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
-  MOZ_ASSERT(adapter);
+  InitD3D11Devices();
 
-  HRESULT hr = E_INVALIDARG;
-
-  MOZ_SEH_TRY{
-    hr = d3d11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-                           D3D11_CREATE_DEVICE_BGRA_SUPPORT,
-                           featureLevels.Elements(), featureLevels.Length(),
-                           D3D11_SDK_VERSION, byRef(mD3D11MediaDevice), nullptr, nullptr);
-  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
-    mD3D11MediaDevice = nullptr;
-  }
-
-  d3d11Module.disown();
-
-  if (FAILED(hr)) {
-    return nullptr;
-  }
-
-  mD3D11MediaDevice->SetExceptionMode(0);
-
-  return mD3D11MediaDevice;
+  return mD3D11ImageBridgeDevice;
 }
 
 
 ReadbackManagerD3D11*
 gfxWindowsPlatform::GetReadbackManager()
 {
   if (!mD3D11ReadbackManager) {
     mD3D11ReadbackManager = new ReadbackManagerD3D11();
@@ -1771,29 +1730,21 @@ bool DoesD3D11DeviceWork(ID3D11Device *d
     }
   }
   result = true;
   return true;
 }
 
 // See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails
 // with E_OUTOFMEMORY.
-bool DoesD3D11TextureSharingWork(ID3D11Device *device)
+bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT format, UINT bindflags)
 {
-  static bool checked = false;
-  static bool result = false;
-
-  if (checked)
-      return result;
-  checked = true;
-
   if (gfxPrefs::Direct2DForceEnabled() ||
       gfxPrefs::LayersAccelerationForceEnabled())
   {
-    result = true;
     return true;
   }
 
   if (GetModuleHandleW(L"atidxx32.dll")) {
     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     if (gfxInfo) {
       nsString vendorID, vendorID2;
       gfxInfo->GetAdapterVendorID(vendorID);
@@ -1808,23 +1759,23 @@ bool DoesD3D11TextureSharingWork(ID3D11D
   }
 
   RefPtr<ID3D11Texture2D> texture;
   D3D11_TEXTURE2D_DESC desc;
   desc.Width = 32;
   desc.Height = 32;
   desc.MipLevels = 1;
   desc.ArraySize = 1;
-  desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+  desc.Format = format;
   desc.SampleDesc.Count = 1;
   desc.SampleDesc.Quality = 0;
   desc.Usage = D3D11_USAGE_DEFAULT;
   desc.CPUAccessFlags = 0;
   desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
-  desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+  desc.BindFlags = bindflags;
   if (FAILED(device->CreateTexture2D(&desc, NULL, byRef(texture)))) {
     return false;
   }
 
   HANDLE shareHandle;
   nsRefPtr<IDXGIResource> otherResource;
   if (FAILED(texture->QueryInterface(__uuidof(IDXGIResource),
                                      getter_AddRefs(otherResource))))
@@ -1855,20 +1806,32 @@ bool DoesD3D11TextureSharingWork(ID3D11D
   // This if(FAILED()) is the one that actually fails on systems affected by bug 1083071.
   if (FAILED(device->CreateShaderResourceView(sharedTexture, NULL, byRef(sharedView)))) {
 #if defined(MOZ_CRASHREPORTER)
     CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("CreateShaderResourceView failed\n"));
 #endif
     return false;
   }
 
-  result = true;
   return true;
 }
 
+bool DoesD3D11TextureSharingWork(ID3D11Device *device)
+{
+  static bool checked;
+  static bool result;
+
+  if (checked)
+    return result;
+  checked = true;
+
+  result = DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
+  return result;
+}
+
 void
 gfxWindowsPlatform::InitD3D11Devices()
 {
   // This function attempts to initialize our D3D11 devices. If the hardware
   // is not blacklisted for D3D11 layers. This will first attempt to create a
   // hardware accelerated device. If this creation fails or the hardware is
   // blacklisted, then this function will abort if WARP is disabled, causing us
   // to fallback to D3D9 or Basic layers. If WARP is not disabled it will use
@@ -2030,17 +1993,37 @@ gfxWindowsPlatform::InitD3D11Devices()
     }
 
     mD3D11ContentDevice->SetExceptionMode(0);
 
     Factory::SetDirect3D11Device(mD3D11ContentDevice);
   }
 
   if (!useWARP) {
-    mCanInitMediaDevice = true;
+    hr = E_INVALIDARG;
+
+    MOZ_SEH_TRY{
+      hr = d3d11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+                             D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+                             featureLevels.Elements(), featureLevels.Length(),
+                             D3D11_SDK_VERSION, byRef(mD3D11ImageBridgeDevice), nullptr, nullptr);
+    } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+      mD3D11ImageBridgeDevice = nullptr;
+    }
+
+    if (FAILED(hr)) {
+      d3d11Module.disown();
+      return;
+    }
+
+    mD3D11ImageBridgeDevice->SetExceptionMode(0);
+
+    if (!DoesD3D11TextureSharingWorkInternal(mD3D11ImageBridgeDevice, DXGI_FORMAT_A8_UNORM, D3D11_BIND_SHADER_RESOURCE)) {
+      mD3D11ImageBridgeDevice = nullptr;
+    }
   }
 
   // We leak these everywhere and we need them our entire runtime anyway, let's
   // leak it here as well.
   d3d11Module.disown();
 }
 
 TemporaryRef<ID3D11Device>
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -239,17 +239,18 @@ public:
     mozilla::layers::DeviceManagerD3D9* GetD3D9DeviceManager();
     IDirect3DDevice9* GetD3D9Device();
 #ifdef CAIRO_HAS_D2D_SURFACE
     cairo_device_t *GetD2DDevice() { return mD2DDevice; }
     ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nullptr; }
 #endif
     ID3D11Device *GetD3D11Device();
     ID3D11Device *GetD3D11ContentDevice();
-    ID3D11Device *GetD3D11MediaDevice();
+    // Device to be used on the ImageBridge thread
+    ID3D11Device *GetD3D11ImageBridgeDevice();
 
     // Create a D3D11 device to be used for DXVA decoding.
     mozilla::TemporaryRef<ID3D11Device> CreateD3D11DecoderDevice();
 
     mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
 
     static bool IsOptimus();
 
@@ -289,21 +290,20 @@ private:
 #endif
 #ifdef CAIRO_HAS_D2D_SURFACE
     cairo_device_t *mD2DDevice;
 #endif
     mozilla::RefPtr<IDXGIAdapter1> mAdapter;
     nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
     mozilla::RefPtr<ID3D11Device> mD3D11Device;
     mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice;
-    mozilla::RefPtr<ID3D11Device> mD3D11MediaDevice;
+    mozilla::RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
     bool mD3D11DeviceInitialized;
     mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
     bool mIsWARP;
-    bool mCanInitMediaDevice;
     bool mHasDeviceReset;
     DeviceResetReason mDeviceResetReason;
 
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
 };
 
 bool DoesD3D11TextureSharingWork(ID3D11Device *device);
 bool DoesD3D11DeviceWork(ID3D11Device *device);
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -2173,16 +2173,17 @@ nsXULPopupManager::HandleKeyboardEventWi
   aKeyEvent->GetKeyCode(&keyCode);
 
   // Escape should close panels, but the other keys should have no effect.
   if (aTopVisibleMenuItem &&
       aTopVisibleMenuItem->PopupType() != ePopupTypeMenu) {
     if (keyCode == nsIDOMKeyEvent::DOM_VK_ESCAPE) {
       HidePopup(aTopVisibleMenuItem->Content(), false, false, false, true);
       aKeyEvent->StopPropagation();
+      aKeyEvent->StopCrossProcessForwarding();
       aKeyEvent->PreventDefault();
     }
     return true;
   }
 
   bool consume = (mPopups || mActiveMenuBar);
   switch (keyCode) {
     case nsIDOMKeyEvent::DOM_VK_LEFT:
@@ -2244,16 +2245,17 @@ nsXULPopupManager::HandleKeyboardEventWi
     }
 
     default:
       return false;
   }
 
   if (consume) {
     aKeyEvent->StopPropagation();
+    aKeyEvent->StopCrossProcessForwarding();
     aKeyEvent->PreventDefault();
   }
   return true;
 }
 
 nsMenuFrame*
 nsXULPopupManager::GetNextMenuItem(nsContainerFrame* aParent,
                                    nsMenuFrame* aStart,
@@ -2444,16 +2446,17 @@ nsXULPopupManager::KeyUp(nsIDOMKeyEvent*
   // don't do anything if a menu isn't open or a menubar isn't active
   if (!mActiveMenuBar) {
     nsMenuChainItem* item = GetTopVisibleMenu();
     if (!item || item->PopupType() != ePopupTypeMenu)
       return NS_OK;
   }
 
   aKeyEvent->StopPropagation();
+  aKeyEvent->StopCrossProcessForwarding();
   aKeyEvent->PreventDefault();
 
   return NS_OK; // I am consuming event
 }
 
 nsresult
 nsXULPopupManager::KeyDown(nsIDOMKeyEvent* aKeyEvent)
 {
@@ -2502,16 +2505,17 @@ nsXULPopupManager::KeyDown(nsIDOMKeyEven
       }
       aKeyEvent->PreventDefault();
     }
   }
 
   // Since a menu was open, stop propagation of the event to keep other event
   // listeners from becoming confused.
   aKeyEvent->StopPropagation();
+  aKeyEvent->StopCrossProcessForwarding();
   return NS_OK;
 }
 
 nsresult
 nsXULPopupManager::KeyPress(nsIDOMKeyEvent* aKeyEvent)
 {
   // Don't check prevent default flag -- menus always get first shot at key events.
 
@@ -2523,16 +2527,17 @@ nsXULPopupManager::KeyPress(nsIDOMKeyEve
 
   nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
   NS_ENSURE_TRUE(keyEvent, NS_ERROR_UNEXPECTED);
   // if a menu is open or a menubar is active, it consumes the key event
   bool consume = (mPopups || mActiveMenuBar);
   HandleShortcutNavigation(keyEvent, nullptr);
   if (consume) {
     aKeyEvent->StopPropagation();
+    aKeyEvent->StopCrossProcessForwarding();
     aKeyEvent->PreventDefault();
   }
 
   return NS_OK; // I am consuming event
 }
 
 NS_IMETHODIMP
 nsXULPopupShowingEvent::Run()
--- a/mobile/android/chrome/content/aboutApps.js
+++ b/mobile/android/chrome/content/aboutApps.js
@@ -109,17 +109,17 @@ function addApplication(aApp) {
 
   let container = document.createElement("div");
   container.className = "app list-item";
   container.setAttribute("contextmenu", "appmenu");
   container.setAttribute("id", "app-" + aApp.manifestURL);
   container.setAttribute("title", manifest.name);
 
   let img = document.createElement("img");
-  img.src = manifest.biggestIconURL || DEFAULT_ICON;
+  img.src = manifest.biggestIconURL() || DEFAULT_ICON;
   img.onerror = function() {
     // If the image failed to load, and it was not our default icon, attempt to
     // use our default as a fallback.
     if (img.src != DEFAULT_ICON) {
       img.src = DEFAULT_ICON;
     }
   }
   img.setAttribute("title", manifest.name);
--- a/services/cloudsync/CloudSyncPlacesWrapper.jsm
+++ b/services/cloudsync/CloudSyncPlacesWrapper.jsm
@@ -75,33 +75,16 @@ PlacesWrapper.prototype = {
 
     this.asyncQuery(query, ["guid"])
         .then(getGuid, deferred.reject)
         .then(deferred.resolve, deferred.reject);
 
     return deferred.promise;
   },
 
-  setGuidForLocalId: function (localId, guid) {
-    let deferred = Promise.defer();
-
-    let stmt = "UPDATE moz_bookmarks " +
-               "SET guid = :guid " +
-               "WHERE id = :item_id";
-    let query = this.placesQueries.getQuery(stmt);
-
-    query.params.guid = guid;
-    query.params.item_id = localId;
-
-    this.asyncQuery(query)
-        .then(deferred.resolve, deferred.reject);
-
-    return deferred.promise;
-  },
-
   getItemsById: function (ids, types) {
     let deferred = Promise.defer();
     let stmt = "SELECT b.id, b.type, b.parent, b.position, b.title, b.guid, b.dateAdded, b.lastModified, p.url " +
                "FROM moz_bookmarks b " +
                "LEFT JOIN moz_places p ON b.fk = p.id " +
                "WHERE b.id in (" + ids.join(",") + ") AND b.type in (" + types.join(",") + ")";
     let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
     let query = db.createAsyncStatement(stmt);
--- a/services/sync/modules/engines/bookmarks.js
+++ b/services/sync/modules/engines/bookmarks.js
@@ -1149,16 +1149,17 @@ BookmarksStore.prototype = {
   _setGUID: function _setGUID(id, guid) {
     if (!guid)
       guid = Utils.makeGUID();
 
     let stmt = this._setGUIDStm;
     stmt.params.guid = guid;
     stmt.params.item_id = id;
     Async.querySpinningly(stmt);
+    PlacesUtils.invalidateCachedGuidFor(id);
     return guid;
   },
 
   get _guidForIdStm() {
     return this._getStmt(
       "SELECT guid " +
       "FROM moz_bookmarks " +
       "WHERE id = :item_id");
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -1459,29 +1459,43 @@ this.PlacesUtils = {
    * its item id.
    *
    * @param aItemId
    *        an item id
    * @return {Promise}
    * @resolves to the GUID.
    * @rejects if aItemId is invalid.
    */
-  promiseItemGuid: function (aItemId) GuidHelper.getItemGuid(aItemId),
+  promiseItemGuid(aItemId) {
+    return GuidHelper.getItemGuid(aItemId)
+  },
 
   /**
    * Get the item id for an item (a bookmark, a folder or a separator) given
    * its unique id.
    *
    * @param aGuid
    *        an item GUID
-   * @retrun {Promise}
+   * @return {Promise}
    * @resolves to the GUID.
    * @rejects if there's no item for the given GUID.
    */
-  promiseItemId: function (aGuid) GuidHelper.getItemId(aGuid),
+  promiseItemId(aGuid) {
+    return GuidHelper.getItemId(aGuid)
+  },
+
+  /**
+   * Invalidate the GUID cache for the given itemId.
+   *
+   * @param aItemId
+   *        an item id
+   */
+  invalidateCachedGuidFor(aItemId) {
+    GuidHelper.invalidateCacheForItemId(aItemId)
+  },
 
   /**
    * Asynchronously retrieve a JS-object representation of a places bookmarks
    * item (a bookmark, a folder, or a separator) along with all of its
    * descendants.
    *
    * @param [optional] aItemGuid
    *        the (topmost) item to be queried.  If it's not passed, the places
@@ -1560,17 +1574,17 @@ this.PlacesUtils = {
       if (aIncludeParentGuid)
         copyProps("parentGuid");
 
       let itemId = aRow.getResultByName("id");
       if (aOptions.includeItemIds)
         item.id = itemId;
 
       // Cache it for promiseItemId consumers regardless.
-      GuidHelper.idsForGuids.set(item.guid, itemId);
+      GuidHelper.updateCache(itemId, item.guid);
 
       let type = aRow.getResultByName("type");
       if (type == Ci.nsINavBookmarksService.TYPE_BOOKMARK)
         copyProps("charset", "tags", "iconuri");
 
       // Add annotations.
       if (aRow.getResultByName("has_annos")) {
         try {
@@ -2161,17 +2175,17 @@ let GuidHelper = {
     let rows = yield conn.executeCached(
       "SELECT b.id, b.guid from moz_bookmarks b WHERE b.guid = :guid LIMIT 1",
       { guid: aGuid });
     if (rows.length == 0)
       throw new Error("no item found for the given GUID");
 
     this.ensureObservingRemovedItems();
     let itemId = rows[0].getResultByName("id");
-    this.idsForGuids.set(aGuid, itemId);
+    this.updateCache(itemId, aGuid);
     return itemId;
   }),
 
   getItemGuid: Task.async(function* (aItemId) {
     let cached = this.guidsForIds.get(aItemId);
     if (cached !== undefined)
       return cached;
 
@@ -2180,40 +2194,61 @@ let GuidHelper = {
     let rows = yield conn.executeCached(
       "SELECT b.id, b.guid from moz_bookmarks b WHERE b.id = :id LIMIT 1",
       { id: aItemId });
     if (rows.length == 0)
       throw new Error("no item found for the given itemId");
 
     this.ensureObservingRemovedItems();
     let guid = rows[0].getResultByName("guid");
-    this.guidsForIds.set(aItemId, guid);
+    this.updateCache(aItemId, guid);
     return guid;
   }),
 
+  /**
+   * Updates the cache.
+   *
+   * @note This is the only place where the cache should be populated,
+   *       invalidation relies on both Maps being populated at the same time.
+   */
+  updateCache(aItemId, aGuid) {
+    if (typeof(aItemId) != "number" || aItemId <= 0)
+      throw new Error("Trying to update the GUIDs cache with an invalid itemId");
+    if (typeof(aGuid) != "string" || !/^[a-zA-Z0-9\-_]{12}$/.test(aGuid))
+      throw new Error("Trying to update the GUIDs cache with an invalid GUID");
+    this.guidsForIds.set(aItemId, aGuid);
+    this.idsForGuids.set(aGuid, aItemId);
+  },
+
+  invalidateCacheForItemId(aItemId) {
+    let guid = this.guidsForIds.get(aItemId);
+    this.guidsForIds.delete(aItemId);
+    this.idsForGuids.delete(guid);
+  },
+
   ensureObservingRemovedItems: function () {
     if (!("observer" in this)) {
       /**
        * This observers serves two purposes:
        * (1) Invalidate cached id<->GUID paris on when items are removed.
        * (2) Cache GUIDs given us free of charge by onItemAdded/onItemRemoved.
       *      So, for exmaple, when the NewBookmark needs the new GUID, we already
       *      have it cached.
       */
       this.observer = {
         onItemAdded: (aItemId, aParentId, aIndex, aItemType, aURI, aTitle,
                       aDateAdded, aGuid, aParentGuid) => {
-          this.guidsForIds.set(aItemId, aGuid);
-          this.guidsForIds.set(aParentId, aParentGuid);
+          this.updateCache(aItemId, aGuid);
+          this.updateCache(aParentId, aParentGuid);
         },
         onItemRemoved:
         (aItemId, aParentId, aIndex, aItemTyep, aURI, aGuid, aParentGuid) => {
           this.guidsForIds.delete(aItemId);
           this.idsForGuids.delete(aGuid);
-          this.guidsForIds.set(aParentId, aParentGuid);
+          this.updateCache(aParentId, aParentGuid);
         },
 
         QueryInterface: XPCOMUtils.generateQI(Ci.nsINavBookmarkObserver),
 
         onBeginUpdateBatch: function() {},
         onEndUpdateBatch: function() {},
         onItemChanged: function() {},
         onItemVisited: function() {},
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unit/test_PlacesUtils_invalidateCachedGuidFor.js
@@ -0,0 +1,24 @@
+add_task(function* () {
+  do_print("Add a bookmark.");
+  let bm = yield PlacesUtils.bookmarks.insert({ url: "http://example.com/",
+                                                parentGuid: PlacesUtils.bookmarks.unfiledGuid });
+  let id = yield PlacesUtils.promiseItemId(bm.guid);
+  Assert.equal((yield PlacesUtils.promiseItemGuid(id)), bm.guid);
+
+  // Ensure invalidating a non-existent itemId doesn't throw.
+  PlacesUtils.invalidateCachedGuidFor(null);
+  PlacesUtils.invalidateCachedGuidFor(9999);
+
+  do_print("Change the GUID.");
+  let db = yield PlacesUtils.promiseWrappedConnection();
+  yield db.execute("UPDATE moz_bookmarks SET guid = :guid WHERE id = :id",
+                   { guid: "123456789012", id});
+  // The cache should still point to the wrong id.
+  Assert.equal((yield PlacesUtils.promiseItemGuid(id)), bm.guid);
+
+  do_print("Invalidate the cache.");
+  PlacesUtils.invalidateCachedGuidFor(id);
+  Assert.equal((yield PlacesUtils.promiseItemGuid(id)), "123456789012");
+  Assert.equal((yield PlacesUtils.promiseItemId("123456789012")), id);
+  yield Assert.rejects(PlacesUtils.promiseItemId(bm.guid), /no item found for the given GUID/);
+});
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -115,16 +115,17 @@ fail-if = os == "android"
 skip-if = true
 [test_null_interfaces.js]
 [test_onItemChanged_tags.js]
 [test_pageGuid_bookmarkGuid.js]
 [test_frecency_observers.js]
 [test_placeURIs.js]
 [test_PlacesSearchAutocompleteProvider.js]
 [test_PlacesUtils_asyncGetBookmarkIds.js]
+[test_PlacesUtils_invalidateCachedGuidFor.js]
 [test_PlacesUtils_lazyobservers.js]
 [test_placesTxn.js]
 [test_preventive_maintenance.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_preventive_maintenance_checkAndFixDatabase.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
--- a/toolkit/themes/shared/in-content/common.inc.css
+++ b/toolkit/themes/shared/in-content/common.inc.css
@@ -699,16 +699,17 @@ xul|listbox xul|listitem[selected="true"
 }
 
 /* Trees */
 
 xul|tree {
   -moz-appearance: none;
   font-size: 1em;
   border: 1px solid var(--in-content-box-border-color);
+  margin: 0;
 }
 
 xul|tree:-moz-focusring,
 xul|richlistbox:-moz-focusring {
   border: 1px dotted var(--in-content-border-focus);
 }
 
 xul|listheader,
--- a/toolkit/themes/shared/in-content/info-pages.inc.css
+++ b/toolkit/themes/shared/in-content/info-pages.inc.css
@@ -1,27 +1,35 @@
 @import url("chrome://global/skin/in-content/common.css");
 /* Body and container */
 body {
   display: flex;
+  flex-direction: column;
   box-sizing: padding-box;
   min-height: 100vh;
   padding-top: 0;
   padding-bottom: 0;
   -moz-padding-start: calc(48px + 4.6em);
   -moz-padding-end: 48px;
   align-items: center;
   justify-content: center;
 }
 
 .container {
   min-width: 13em;
   max-width: 52em;
 }
 
+.container.flex {
+  display: flex;
+  flex-direction: column;
+  flex-grow: 1;
+  margin: 10vh 0;
+}
+
 /* Typography */
 .title {
   background-image: url("chrome://browser/skin/aboutNetError_info.svg");
   background-position: left 0;
   background-repeat: no-repeat;
   background-size: 1.6em;
   -moz-margin-start: -2.3em;
   -moz-padding-start: 2.3em;
@@ -77,13 +85,21 @@ ul {
   min-width: 150px;
 }
 
 .button-container > button:first-child {
   -moz-margin-start: 0;
 }
 
 /* Trees */
-tree {
-  min-height: 12em;
+.tree-container {
   margin-top: 1.2em;
+  flex-grow: 1;
+  min-height: 12em;
+}
+
+.tree-container > tree {
+  height: 100%;
+}
+
+tree {
   width: 100%;
-}
\ No newline at end of file
+}
--- a/toolkit/webapps/NativeApp.jsm
+++ b/toolkit/webapps/NativeApp.jsm
@@ -98,18 +98,24 @@ CommonNativeApp.prototype = {
    *
    * @param aManifest {Object} the manifest data provided by the web app
    *
    */
   _setData: function(aApp, aManifest) {
     let manifest = new ManifestHelper(aManifest, aApp.origin, aApp.manifestURL);
     let origin = Services.io.newURI(aApp.origin, null, null);
 
-    this.iconURI = Services.io.newURI(manifest.biggestIconURL || DEFAULT_ICON_URL,
-                                      null, null);
+#ifdef XP_WIN
+    let biggestIconURL = manifest.biggestIconURL(v => v <= 256);
+#else
+    let biggestIconURL = manifest.biggestIconURL();
+#endif
+
+    this.iconURI = Services.io.newURI(biggestIconURL || DEFAULT_ICON_URL, null,
+                                      null);
 
     if (manifest.developer) {
       if (manifest.developer.name) {
         let devName = manifest.developer.name.substr(0, 128);
         if (devName) {
           this.developerName = devName;
         }
       }
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ddb90d8b8fd296d0f46fff1bf364d55cec915dac
GIT binary patch
literal 5636
zc%17D@N?(olHy`uVBq!ia0y~yU}6Aa4mKe5rQ*sjAjMc5<nF|<?wrg^1_sf6o-U3d
z6^w7MISMi;@Gv_b*#G=c!sBgxn_enc-_vz(U|?io;aI}rr?qwi3x|M$L&E`a0|px=
zkf;C$mjuJXORj1TAXRJ)@(N&vBO|jy#I6%y)dv_pFoPKi8VL+6-r_UC#z`>LLCj@g
z<!MNGsU!^6$b5hwWIjXVf(Awbo!AtR4GIYiKfqQg2#6RkG%fA+0c+%8um@Yk(!|8(
zu%TokCrD!h;{$fE3mpOuFmO!MGXiTgVEDr@>ex}ojyiVKv7?S1b?m5PM;$xr*ipxh
zI(F2tqmCVQ?5JZ$9XsmSQOAxtcGR&$&anqr`z+c2xbbC_FaUw4tDnm{r-UW|_~3bn
--- a/toolkit/webapps/tests/test_hosted_icons.xul
+++ b/toolkit/webapps/tests/test_hosted_icons.xul
@@ -52,16 +52,18 @@ let iconTests = [
   // Absolute URI
   {"32": "http://example.com/chrome/toolkit/webapps/tests/data/icon.png"},
   // Relative URI
   {"32": "/chrome/toolkit/webapps/tests/data/icon.png"},
   // Data URI icon
   {"32": generateDataURI(getFile(getTestFilePath("data/icon.png"))) },
   // URI to a file that isn't an image
   {"32": "/chrome/toolkit/webapps/tests/data/app/index.html"},
+  // Large icon that won't be used on Windows (bug #1152597)
+  {"512": "/chrome/toolkit/webapps/tests/data/512.png"},
 ];
 
 // This is an array of the icon sizes associated with the elements of
 // iconTests. Each element in the iconSizes array is an array of two values:
 //  - The expected size of the icon
 //  - An epsilon value that defines an accepted range around the icon size.
 // On each platform the size is different (because the format of the file is
 // different: ICO on Windows, PNG on Linux, ICNS on Mac).
@@ -74,32 +76,36 @@ let iconSizes;
 
 if (LINUX) {
   iconSizes = [
     [4009, 0],
     [2787, 0],
     [2787, 0],
     [2787, 0],
     [4009, 0],
+    [2195, 0],
   ];
 } else if (WIN) {
   iconSizes = [
     [16958, 0],
     [4286, 0],
     [4286, 0],
     [4286, 0],
     [16958, 0],
+    // Windows ICO doesn't support 512x512 icons. The default should be chosen.
+    [16958, 0],
   ];
 } else if (MAC) {
   iconSizes = [
     [14000, 2000],
     [27000, 2000],
     [27000, 2000],
     [27000, 2000],
     [14000, 2000],
+    [1000, 2000],
   ];
 }
 
 let testAppInfo = new TestAppInfo(app);
 
 let runTest = Task.async(function*() {
   SimpleTest.registerCleanupFunction(() => testAppInfo.cleanup());
 
--- a/toolkit/webapps/tests/test_packaged_icons.xul
+++ b/toolkit/webapps/tests/test_packaged_icons.xul
@@ -60,16 +60,18 @@ let iconTests = [
   // Absolute URI
   {"32": "http://example.com/chrome/toolkit/webapps/tests/data/icon.png"},
   // Relative URI
   {"32": "/icon.png"},
   // Data URI icon
   {"32": generateDataURI(testIconFile) },
   // URI to a file that isn't an image
   {"32": "/index.html"},
+  // Large icon that won't be used on Windows (bug #1152597)
+  {"512": "http://example.com/chrome/toolkit/webapps/tests/data/512.png"},
 ];
 
 // This is an array of the icon sizes associated with the elements of
 // iconTests. Each element in the iconSizes array is an array of two values:
 //  - The expected size of the icon
 //  - An epsilon value that defines an accepted range around the icon size.
 // On each platform the size is different (because the format of the file is
 // different: ICO on Windows, PNG on Linux, ICNS on Mac).
@@ -82,32 +84,36 @@ let iconSizes;
 
 if (LINUX) {
   iconSizes = [
     [4009, 0],
     [2787, 0],
     [2787, 0],
     [2787, 0],
     [4009, 0],
+    [2195, 0],
   ];
 } else if (WIN) {
   iconSizes = [
     [16958, 0],
     [4286, 0],
     [4286, 0],
     [4286, 0],
     [16958, 0],
+    // Windows ICO doesn't support 512x512 icons. The default should be chosen.
+    [16958, 0],
   ];
 } else if (MAC) {
   iconSizes = [
     [14000, 2000],
     [27000, 2000],
     [27000, 2000],
     [27000, 2000],
     [14000, 2000],
+    [1000, 2000],
   ];
 }
 
 let testAppInfo = new TestAppInfo(app, true);
 
 let runTest = Task.async(function*() {
   SimpleTest.registerCleanupFunction(() => testAppInfo.cleanup());