Merge m-c to birch.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 23 Apr 2013 14:27:53 -0400
changeset 129580 424ddd76303b4d2fb7a5faf972d6714323c9e86c
parent 129579 761a78c8ab0306c58b88eb5fef5f434e0cb11cf6 (current diff)
parent 129571 591caa6e37af1ad075bb2dbcc2101cbbfbb380c0 (diff)
child 129618 8b1a7228674af2f0470f2fbe3c52f69fe78b5e58
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone23.0a1
Merge m-c to birch.
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1077,16 +1077,17 @@ pref("devtools.debugger.ui.variables-sea
 // Enable the Profiler
 pref("devtools.profiler.enabled", true);
 
 // Enable the Network Monitor
 pref("devtools.netmonitor.enabled", true);
 
 // The default Network Monitor UI settings
 pref("devtools.netmonitor.panes-network-details-width", 450);
+pref("devtools.netmonitor.panes-network-details-height", 450);
 
 // Enable the Tilt inspector
 pref("devtools.tilt.enabled", true);
 pref("devtools.tilt.intro_transition", true);
 pref("devtools.tilt.outro_transition", true);
 
 // Enable the Scratchpad tool.
 pref("devtools.scratchpad.enabled", true);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6761,18 +6761,20 @@ let gPrivateBrowsingUI = {
             newWindow.label = newPrivateWindow.label;
             newWindow.accessKey = newPrivateWindow.accessKey;
             newWindow.command = newPrivateWindow.command;
           }
         });
       }
     }
 
-    if (gURLBar) {
-      // Disable switch to tab autocompletion for private windows
+    if (gURLBar &&
+        !PrivateBrowsingUtils.permanentPrivateBrowsing) {
+      // Disable switch to tab autocompletion for private windows 
+      // (not for "Always use private browsing" mode)
       gURLBar.setAttribute("autocompletesearchparam", "");
     }
   }
 };
 
 
 /**
  * Switch to a tab that has a given URI, and focusses its browser window.
@@ -6785,19 +6787,20 @@ let gPrivateBrowsingUI = {
  *        True to open a new tab and switch to it, if no existing tab is found.
  *        If no suitable window is found, a new one will be opened.
  * @return True if an existing tab was found, false otherwise
  */
 function switchToTabHavingURI(aURI, aOpenNew) {
   // This will switch to the tab in aWindow having aURI, if present.
   function switchIfURIInWindow(aWindow) {
     // Only switch to the tab if neither the source and desination window are
-    // private.
-    if (PrivateBrowsingUtils.isWindowPrivate(window) ||
-        PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
+    // private and they are not in permanent private borwsing mode
+    if ((PrivateBrowsingUtils.isWindowPrivate(window) ||
+        PrivateBrowsingUtils.isWindowPrivate(aWindow)) &&
+        !PrivateBrowsingUtils.permanentPrivateBrowsing) {
       return false;
     }
 
     let browsers = aWindow.gBrowser.browsers;
     for (let i = 0; i < browsers.length; i++) {
       let browser = browsers[i];
       if (browser.currentURI.equals(aURI)) {
         // Focus the matching window & tab
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -645,17 +645,18 @@
                 let autocomplete = this.mTabBrowser._placesAutocomplete;
                 if (this.mBrowser.registeredOpenURI) {
                   autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI);
                   delete this.mBrowser.registeredOpenURI;
                 }
                 // Tabs in private windows aren't registered as "Open" so
                 // that they don't appear as switch-to-tab candidates.
                 if (!isBlankPageURL(aLocation.spec) &&
-                    !PrivateBrowsingUtils.isWindowPrivate(window)) {
+                    (!PrivateBrowsingUtils.isWindowPrivate(window) ||
+                    PrivateBrowsingUtils.permanentPrivateBrowsing)) {
                   autocomplete.registerOpenPage(aLocation);
                   this.mBrowser.registeredOpenURI = aLocation;
                 }
               }
 
               if (!this.mBlank) {
                 this._callProgressListeners("onLocationChange",
                                             [aWebProgress, aRequest, aLocation,
--- a/browser/devtools/commandline/gcli.jsm
+++ b/browser/devtools/commandline/gcli.jsm
@@ -7303,22 +7303,20 @@ Output.prototype.complete = function(dat
 };
 
 exports.Output = Output;
 
 /**
  * Functions and data related to the execution of a command
  */
 exports.createExecutionContext = function(requisition) {
-  return {
+  var context = {
     exec: requisition.exec.bind(requisition),
     update: requisition.update.bind(requisition),
     updateExec: requisition.updateExec.bind(requisition),
-    document: requisition.document,
-    environment: requisition.environment,
     createView: view.createView,
     typedData: function(data, type) {
       return {
         isTypedData: true,
         data: data,
         type: type
       };
     },
@@ -7329,16 +7327,28 @@ exports.createExecutionContext = functio
     /**
      * @deprecated Use defer() instead, which does the same thing, but is not
      * confusingly named
      */
     createPromise: function() {
       return Promise.defer();
     }
   };
+
+  Object.defineProperty(context, 'environment', {
+    get: function() { return requisition.environment; },
+    enumerable : true
+  });
+
+  Object.defineProperty(context, 'document', {
+    get: function() { return requisition.document; },
+    enumerable : true
+  });
+
+  return context;
 };
 
 
 });
 define("text!gcli/ui/intro.html", [], "\n" +
   "<div>\n" +
   "  <p>${l10n.introTextOpening2}</p>\n" +
   "\n" +
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-data.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-data.js
@@ -648,51 +648,51 @@ function testKeyboardAccessibility(callb
               is(gVariablesView.getFocusedItem().name, "someProp5",
                 "The someProp5 item should be focused now.");
 
               EventUtils.sendKey("DOWN", gDebugger);
               is(gVariablesView.getFocusedItem().name, "0",
                 "The 0 item should be focused now.");
 
               EventUtils.sendKey("END", gDebugger);
-              is(gVariablesView.getFocusedItem().name, "foo",
-                "The foo item should be focused now.");
+              is(gVariablesView.getFocusedItem().name, "bar",
+                "The bar item should be focused now.");
 
               EventUtils.sendKey("DOWN", gDebugger);
               is(gVariablesView.getFocusedItem().name, "bar",
-                "The bar item should be focused now.");
+                "The bar item should still be focused now.");
 
               EventUtils.sendKey("UP", gDebugger);
               is(gVariablesView.getFocusedItem().name, "foo",
                 "The foo item should be focused now.");
 
               EventUtils.sendKey("RIGHT", gDebugger);
               is(gVariablesView.getFocusedItem().name, "foo",
                 "The foo item should still be focused now.");
 
               EventUtils.sendKey("PAGE_DOWN", gDebugger);
-              is(gVariablesView.getFocusedItem().name, "foo",
-                "The foo item should still be focused now.");
+              is(gVariablesView.getFocusedItem().name, "bar",
+                "The bar item should be focused now.");
 
               EventUtils.sendKey("PAGE_UP", gDebugger);
+              is(gVariablesView.getFocusedItem().name, "someProp7",
+                "The someProp7 item should be focused now.");
+
+              EventUtils.sendKey("UP", gDebugger);
               is(gVariablesView.getFocusedItem().name, "__proto__",
                 "The __proto__ item should be focused now.");
 
               EventUtils.sendKey("UP", gDebugger);
               is(gVariablesView.getFocusedItem().name, "set",
                 "The set item should be focused now.");
 
               EventUtils.sendKey("UP", gDebugger);
               is(gVariablesView.getFocusedItem().name, "get",
                 "The get item should be focused now.");
 
-              EventUtils.sendKey("UP", gDebugger);
-              is(gVariablesView.getFocusedItem().name, "p8",
-                "The p8 item should be focused now.");
-
               EventUtils.sendKey("HOME", gDebugger);
               is(gVariablesView.getFocusedItem().name, "someProp0",
                 "The someProp0 item should be focused now.");
 
               EventUtils.sendKey("UP", gDebugger);
               is(gVariablesView.getFocusedItem().name, "someProp0",
                 "The someProp0 item should still be focused now.");
 
@@ -823,16 +823,28 @@ function testKeyboardAccessibility(callb
                 "The top-level __proto__ item should be expanded.");
 
               EventUtils.sendKey("LEFT", gDebugger);
               is(gVariablesView.getFocusedItem().name, "__proto__",
                 "The top-level __proto__ item should still be focused.");
               is(gVariablesView.getFocusedItem().expanded, false,
                 "The top-level __proto__ item should not be expanded.");
 
+              EventUtils.sendKey("END", gDebugger);
+              is(gVariablesView.getFocusedItem().name, "foo",
+                "The foo scope should be focused.");
+
+              EventUtils.sendKey("PAGE_UP", gDebugger);
+              is(gVariablesView.getFocusedItem().name, "__proto__",
+                "The __proto__ property should be focused.");
+
+              EventUtils.sendKey("PAGE_DOWN", gDebugger);
+              is(gVariablesView.getFocusedItem().name, "foo",
+                "The foo scope should be focused.");
+
               executeSoon(callback);
             });
           });
         });
       });
     });
   });
 }
--- a/browser/devtools/framework/Target.jsm
+++ b/browser/devtools/framework/Target.jsm
@@ -270,35 +270,41 @@ TabTarget.prototype = {
 
       this._client = new DebuggerClient(DebuggerServer.connectPipe());
       // A local TabTarget will never perform chrome debugging.
       this._chrome = false;
     }
 
     this._setupRemoteListeners();
 
-    if (this.isRemote) {
-      // In the remote debugging case, the protocol connection will have been
-      // already initialized in the connection screen code.
-      this._remote.resolve(null);
-    } else {
+    let attachTab = () => {
+      this._client.attachTab(this._form.actor, (aResponse, aTabClient) => {
+        if (!aTabClient) {
+          this._remote.reject("Unable to attach to the tab");
+          return;
+        }
+        this.threadActor = aResponse.threadActor;
+        this._remote.resolve(null);
+      });
+    };
+
+    if (this.isLocalTab) {
       this._client.connect((aType, aTraits) => {
         this._client.listTabs(aResponse => {
           this._form = aResponse.tabs[aResponse.selected];
-
-          this._client.attachTab(this._form.actor, (aResponse, aTabClient) => {
-            if (!aTabClient) {
-              this._remote.reject("Unable to attach to the tab");
-              return;
-            }
-            this.threadActor = aResponse.threadActor;
-            this._remote.resolve(null);
-          });
+          attachTab();
         });
       });
+    } else if (!this.chrome) {
+      // In the remote debugging case, the protocol connection will have been
+      // already initialized in the connection screen code.
+      attachTab();
+    } else {
+      // Remote chrome debugging doesn't need anything at this point.
+      this._remote.resolve(null);
     }
 
     return this._remote.promise;
   },
 
   /**
    * Listen to the different events.
    */
--- a/browser/devtools/netmonitor/netmonitor-controller.js
+++ b/browser/devtools/netmonitor/netmonitor-controller.js
@@ -510,17 +510,18 @@ NetworkEventsHandler.prototype = {
  * Localization convenience methods.
  */
 let L10N = new ViewHelpers.L10N(NET_STRINGS_URI);
 
 /**
  * Shortcuts for accessing various network monitor preferences.
  */
 let Prefs = new ViewHelpers.Prefs("devtools.netmonitor", {
-  networkDetailsWidth: ["Int", "panes-network-details-width"]
+  networkDetailsWidth: ["Int", "panes-network-details-width"],
+  networkDetailsHeight: ["Int", "panes-network-details-height"]
 });
 
 /**
  * Convenient way of emitting events from the panel window.
  */
 EventEmitter.decorate(this);
 
 /**
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -2,16 +2,17 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const EPSILON = 0.001;
 const REQUESTS_REFRESH_RATE = 50; // ms
+const REQUESTS_HEADERS_SAFE_BOUNDS = 30; // px
 const REQUESTS_WATERFALL_SAFE_BOUNDS = 100; // px
 const REQUESTS_WATERFALL_BACKGROUND_PATTERN = [5, 250, 1000, 2000]; // ms
 const DEFAULT_HTTP_VERSION = "HTTP/1.1";
 const HEADERS_SIZE_DECIMALS = 3;
 const CONTENT_SIZE_DECIMALS = 2;
 const CONTENT_MIME_TYPE_ABBREVIATIONS = {
   "ecmascript": "js",
   "javascript": "js",
@@ -97,26 +98,28 @@ let NetMonitorView = {
 
     this._detailsPane = $("#details-pane");
     this._detailsPaneToggleButton = $("#details-pane-toggle");
 
     this._collapsePaneString = L10N.getStr("collapseDetailsPane");
     this._expandPaneString = L10N.getStr("expandDetailsPane");
 
     this._detailsPane.setAttribute("width", Prefs.networkDetailsWidth);
+    this._detailsPane.setAttribute("height", Prefs.networkDetailsHeight);
     this.toggleDetailsPane({ visible: false });
   },
 
   /**
    * Destroys the UI for all the displayed panes.
    */
   _destroyPanes: function DV__destroyPanes() {
     dumpn("Destroying the NetMonitorView panes");
 
     Prefs.networkDetailsWidth = this._detailsPane.getAttribute("width");
+    Prefs.networkDetailsHeight = this._detailsPane.getAttribute("height");
 
     this._detailsPane = null;
     this._detailsPaneToggleButton = null;
   },
 
   /**
    * Gets the visibility state of the network details pane.
    * @return boolean
@@ -587,16 +590,37 @@ create({ constructor: RequestsMenuView, 
    *        True if this container's width was changed.
    */
   _flushWaterfallViews: function NVRM__flushWaterfallViews(aReset) {
     // To avoid expensive operations like getBoundingClientRect(), the
     // waterfalls width is cached. However, in certain scenarios like when
     // the window is resized, this needs to be invalidated.
     if (aReset) {
       this._cachedWaterfallWidth = 0;
+
+      let table = $("#network-table");
+      let toolbar = $("#requests-menu-toolbar");
+      let columns = [
+        [".requests-menu-waterfall", "waterfall-overflows"],
+        [".requests-menu-size", "size-overflows"],
+        [".requests-menu-type", "type-overflows"],
+        [".requests-menu-domain", "domain-overflows"]
+      ];
+
+      // Flush headers.
+      columns.forEach(([, attribute]) => table.removeAttribute(attribute));
+      let availableWidth = toolbar.getBoundingClientRect().width;
+
+      // Hide overflowing columns.
+      columns.forEach(([className, attribute]) => {
+        let bounds = $(".requests-menu-header" + className).getBoundingClientRect();
+        if (bounds.right > availableWidth - REQUESTS_HEADERS_SAFE_BOUNDS) {
+          table.setAttribute(attribute, "");
+        }
+      });
     }
 
     // Determine the scaling to be applied to all the waterfalls so that
     // everything is visible at once. One millisecond == one unscaled pixel.
     let availableWidth = this._waterfallWidth - REQUESTS_WATERFALL_SAFE_BOUNDS;
     let longestWidth = this._lastRequestEndedMillis - this._firstRequestStartedMillis;
     let scale = Math.min(Math.max(availableWidth / longestWidth, EPSILON), 1);
 
--- a/browser/devtools/netmonitor/netmonitor.css
+++ b/browser/devtools/netmonitor/netmonitor.css
@@ -8,13 +8,41 @@
 }
 
 #timings-summary-blocked {
   display: none; /* This doesn't work yet. */
 }
 
 /* Responsive sidebar */
 @media (max-width: 700px) {
+  #toolbar-spacer,
   #details-pane-toggle,
+  #details-pane[pane-collapsed],
   .requests-menu-waterfall {
     display: none;
   }
 }
+
+@media (min-width: 701px) {
+  #network-table[waterfall-overflows] .requests-menu-waterfall {
+    display: none;
+  }
+
+  #network-table[size-overflows] .requests-menu-size {
+    display: none;
+  }
+
+  #network-table[type-overflows] .requests-menu-type {
+    display: none;
+  }
+
+  #network-table[domain-overflows] .requests-menu-domain {
+    display: none;
+  }
+
+  #network-table[type-overflows] .requests-menu-domain {
+    -moz-box-flex: 1;
+  }
+
+  #network-table[domain-overflows] .requests-menu-file {
+    -moz-box-flex: 1;
+  }
+}
--- a/browser/devtools/netmonitor/netmonitor.xul
+++ b/browser/devtools/netmonitor/netmonitor.xul
@@ -41,17 +41,17 @@
         <label id="requests-menu-size-label"
                class="plain requests-menu-header requests-menu-size"
                value="&netmonitorUI.toolbar.size;"
                crop="end"/>
         <label id="requests-menu-waterfall-label"
                class="plain requests-menu-header requests-menu-waterfall"
                value="&netmonitorUI.toolbar.waterfall;"
                crop="end"/>
-        <spacer flex="1"/>
+        <spacer id="toolbar-spacer" flex="1"/>
         <toolbarbutton id="details-pane-toggle"
                        class="devtools-toolbarbutton"
                        tooltiptext="&netmonitorUI.panesButton.tooltip;"
                        tabindex="0"/>
       </toolbar>
       <label class="plain requests-menu-empty-notice"
              value="&netmonitorUI.emptyNotice;"/>
       <vbox id="requests-menu-contents" flex="1">
--- a/browser/devtools/netmonitor/test/browser_net_prefs-reload.js
+++ b/browser/devtools/netmonitor/test/browser_net_prefs-reload.js
@@ -4,23 +4,30 @@
 /**
  * Tests if the prefs that should survive across tool reloads work.
  */
 
 function test() {
   initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
     info("Starting test... ");
 
+    // This test reopens the network monitor a bunch of times, for different
+    // hosts (bottom, side, window). This seems to be slow on debug builds.
+    requestLongerTimeout(2);
+
     let prefsToCheck = {
       networkDetailsWidth: {
         newValue: ~~(Math.random() * 200 + 100),
-        validate: () =>
-          ~~aMonitor._view._detailsPane.getAttribute("width"),
-        modifyFrontend: (aValue) =>
-          aMonitor._view._detailsPane.setAttribute("width", aValue)
+        validate: ($) => ~~$("#details-pane").getAttribute("width"),
+        modifyFrontend: ($, aValue) => $("#details-pane").setAttribute("width", aValue)
+      },
+      networkDetailsHeight: {
+        newValue: ~~(Math.random() * 300 + 100),
+        validate: ($) => ~~$("#details-pane").getAttribute("height"),
+        modifyFrontend: ($, aValue) => $("#details-pane").setAttribute("height", aValue)
       },
       /* add more prefs here... */
     };
 
     function storeFirstPrefValues() {
       info("Caching initial pref values.");
 
       for (let name in prefsToCheck) {
@@ -34,97 +41,177 @@ function test() {
 
       for (let name in prefsToCheck) {
         let currentValue = aMonitor.panelWin.Prefs[name];
         let firstValue = prefsToCheck[name].firstValue;
         let validate = prefsToCheck[name].validate;
 
         is(currentValue, firstValue,
           "Pref " + name + " should be equal to first value: " + firstValue);
-        is(currentValue, validate(),
+        is(currentValue, validate(aMonitor.panelWin.$),
           "Pref " + name + " should validate: " + currentValue);
       }
     }
 
     function modifyFrontend() {
       info("Modifying UI elements to the specified new values.");
 
       for (let name in prefsToCheck) {
         let currentValue = aMonitor.panelWin.Prefs[name];
         let firstValue = prefsToCheck[name].firstValue;
         let newValue = prefsToCheck[name].newValue;
         let validate = prefsToCheck[name].validate;
         let modifyFrontend = prefsToCheck[name].modifyFrontend;
 
-        modifyFrontend(newValue);
+        modifyFrontend(aMonitor.panelWin.$, newValue);
         info("Modified UI element affecting " + name + " to: " + newValue);
 
         is(currentValue, firstValue,
           "Pref " + name + " should still be equal to first value: " + firstValue);
         isnot(currentValue, newValue,
           "Pref " + name + " should't yet be equal to second value: " + newValue);
-        is(newValue, validate(),
+        is(newValue, validate(aMonitor.panelWin.$),
           "The UI element affecting " + name + " should validate: " + newValue);
       }
     }
 
     function validateNewPrefValues() {
       info("Invalidating old pref values to the modified UI elements.");
 
       for (let name in prefsToCheck) {
         let currentValue = aMonitor.panelWin.Prefs[name];
         let firstValue = prefsToCheck[name].firstValue;
         let newValue = prefsToCheck[name].newValue;
         let validate = prefsToCheck[name].validate;
-        let modifyFrontend = prefsToCheck[name].modifyFrontend;
 
         isnot(currentValue, firstValue,
           "Pref " + name + " should't be equal to first value: " + firstValue);
         is(currentValue, newValue,
           "Pref " + name + " should now be equal to second value: " + newValue);
-        is(newValue, validate(),
+        is(newValue, validate(aMonitor.panelWin.$),
           "The UI element affecting " + name + " should validate: " + newValue);
       }
     }
 
     function resetFrontend() {
       info("Resetting UI elements to the cached initial pref values.");
 
       for (let name in prefsToCheck) {
         let currentValue = aMonitor.panelWin.Prefs[name];
         let firstValue = prefsToCheck[name].firstValue;
         let newValue = prefsToCheck[name].newValue;
         let validate = prefsToCheck[name].validate;
         let modifyFrontend = prefsToCheck[name].modifyFrontend;
 
-        modifyFrontend(firstValue);
+        modifyFrontend(aMonitor.panelWin.$, firstValue);
         info("Modified UI element affecting " + name + " to: " + firstValue);
 
         isnot(currentValue, firstValue,
           "Pref " + name + " should't yet be equal to first value: " + firstValue);
         is(currentValue, newValue,
           "Pref " + name + " should still be equal to second value: " + newValue);
-        is(firstValue, validate(),
+        is(firstValue, validate(aMonitor.panelWin.$),
           "The UI element affecting " + name + " should validate: " + firstValue);
       }
     }
 
-    storeFirstPrefValues();
+    function testBottom() {
+      info("Testing prefs reload for a bottom host.");
+      storeFirstPrefValues();
+
+      // Validate and modify while toolbox is on the bottom.
+      validateFirstPrefValues();
+      modifyFrontend();
+
+      return restartNetMonitor(aMonitor)
+        .then(([,, aNewMonitor]) => {
+          aMonitor = aNewMonitor;
+
+          // Revalidate and reset frontend while toolbox is on the bottom.
+          validateNewPrefValues();
+          resetFrontend();
+
+          return restartNetMonitor(aMonitor);
+        })
+        .then(([,, aNewMonitor]) => {
+          aMonitor = aNewMonitor;
 
-    // Validate and modify.
-    validateFirstPrefValues();
-    modifyFrontend();
-    restartNetMonitor(aMonitor).then(([,, aNewMonitor]) => {
-      aMonitor = aNewMonitor;
+          // Revalidate.
+          validateFirstPrefValues();
+        });
+    }
+
+    function testSide() {
+      info("Moving toolbox to the side...");
+
+      return aMonitor._toolbox.switchHost(Toolbox.HostType.SIDE)
+        .then(() => {
+          info("Testing prefs reload for a side host.");
+          storeFirstPrefValues();
+
+          // Validate and modify frontend while toolbox is on the side.
+          validateFirstPrefValues();
+          modifyFrontend();
+
+          return restartNetMonitor(aMonitor);
+        })
+        .then(([,, aNewMonitor]) => {
+          aMonitor = aNewMonitor;
+
+          // Revalidate and reset frontend while toolbox is on the side.
+          validateNewPrefValues();
+          resetFrontend();
 
-      // Revalidate and reset.
-      validateNewPrefValues();
-      resetFrontend();
-      restartNetMonitor(aMonitor).then(([,, aNewMonitor]) => {
-        aMonitor = aNewMonitor;
+          return restartNetMonitor(aMonitor);
+        })
+        .then(([,, aNewMonitor]) => {
+          aMonitor = aNewMonitor;
+
+          // Revalidate.
+          validateFirstPrefValues();
+        });
+    }
+
+    function testWindow() {
+      info("Moving toolbox into a window...");
+
+      return aMonitor._toolbox.switchHost(Toolbox.HostType.WINDOW)
+        .then(() => {
+          info("Testing prefs reload for a window host.");
+          storeFirstPrefValues();
+
+          // Validate and modify frontend while toolbox is in a window.
+          validateFirstPrefValues();
+          modifyFrontend();
+
+          return restartNetMonitor(aMonitor);
+        })
+        .then(([,, aNewMonitor]) => {
+          aMonitor = aNewMonitor;
 
-        // Revalidate and finish.
-        validateFirstPrefValues();
-        teardown(aMonitor).then(finish);
-      });
-    });
+          // Revalidate and reset frontend while toolbox is in a window.
+          validateNewPrefValues();
+          resetFrontend();
+
+          return restartNetMonitor(aMonitor);
+        })
+        .then(([,, aNewMonitor]) => {
+          aMonitor = aNewMonitor;
+
+          // Revalidate.
+          validateFirstPrefValues();
+        });
+    }
+
+    function cleanupAndFinish() {
+      info("Moving toolbox back to the bottom...");
+
+      aMonitor._toolbox.switchHost(Toolbox.HostType.BOTTOM)
+        .then(() => teardown(aMonitor))
+        .then(finish);
+    }
+
+    testBottom()
+      .then(testSide)
+      .then(testWindow)
+      .then(cleanupAndFinish);
   });
 }
--- a/browser/devtools/netmonitor/test/head.js
+++ b/browser/devtools/netmonitor/test/head.js
@@ -2,16 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
 let { Promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
 let { TargetFactory } = Cu.import("resource:///modules/devtools/Target.jsm", {});
+let { Toolbox } = Cu.import("resource:///modules/devtools/Toolbox.jsm", {});
 let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
 
 const EXAMPLE_URL = "http://example.com/browser/browser/devtools/netmonitor/test/";
 
 const SIMPLE_URL = EXAMPLE_URL + "html_simple-test-page.html";
 const NAVIGATE_URL = EXAMPLE_URL + "html_navigate-test-page.html";
 const CONTENT_TYPE_URL = EXAMPLE_URL + "html_content-type-test-page.html";
 const STATUS_CODES_URL = EXAMPLE_URL + "html_status-codes-test-page.html";
--- a/browser/devtools/shared/DeveloperToolbar.jsm
+++ b/browser/devtools/shared/DeveloperToolbar.jsm
@@ -501,17 +501,17 @@ DeveloperToolbar.prototype.destroy = fun
 {
   if (this._lastState == NOTIFICATIONS.HIDE) {
     return;
   }
 
   let tabbrowser = this._chromeWindow.getBrowser();
   tabbrowser.tabContainer.removeEventListener("TabSelect", this, false);
   tabbrowser.tabContainer.removeEventListener("TabClose", this, false);
-  tabbrowser.removeEventListener("load", this, true); 
+  tabbrowser.removeEventListener("load", this, true);
   tabbrowser.removeEventListener("beforeunload", this, true);
 
   Array.prototype.forEach.call(tabbrowser.tabs, this._stopErrorsCount, this);
 
   this.display.focusManager.removeMonitoredElement(this.outputPanel._frame);
   this.display.focusManager.removeMonitoredElement(this._element);
 
   this.display.onVisibilityChange.remove(this.outputPanel._visibilityChanged, this.outputPanel);
--- a/browser/devtools/shared/widgets/VariablesView.jsm
+++ b/browser/devtools/shared/widgets/VariablesView.jsm
@@ -47,16 +47,17 @@ const STR = Services.strings.createBundl
  * @param nsIDOMNode aParentNode
  *        The parent node to hold this view.
  * @param object aFlags [optional]
  *        An object contaning initialization options for this view.
  *        e.g. { lazyEmpty: true, searchEnabled: true ... }
  */
 this.VariablesView = function VariablesView(aParentNode, aFlags = {}) {
   this._store = new Map();
+  this._items = [];
   this._itemsByElement = new WeakMap();
   this._prevHierarchy = new Map();
   this._currHierarchy = new Map();
 
   this._parent = aParentNode;
   this._parent.classList.add("variables-view-container");
   this._appendEmptyNotice();
 
@@ -98,16 +99,17 @@ VariablesView.prototype = {
    *         The newly created Scope instance.
    */
   addScope: function VV_addScope(aName = "") {
     this._removeEmptyNotice();
     this._toggleSearchVisibility(true);
 
     let scope = new Scope(this, aName);
     this._store.set(scope.id, scope);
+    this._items.push(scope);
     this._currHierarchy.set(aName, scope);
     this._itemsByElement.set(scope._target, scope);
     scope.header = !!aName;
     return scope;
   },
 
   /**
    * Removes all items from this container.
@@ -130,16 +132,17 @@ VariablesView.prototype = {
     let list = this._list;
     let firstChild;
 
     while (firstChild = list.firstChild) {
       list.removeChild(firstChild);
     }
 
     this._store.clear();
+    this._items.length = 0;
     this._itemsByElement.clear();
 
     this._appendEmptyNotice();
     this._toggleSearchVisibility(false);
   },
 
   /**
    * Emptying this container and rebuilding it immediately afterwards would
@@ -156,16 +159,17 @@ VariablesView.prototype = {
    * @see VariablesView.empty
    * @see VariablesView.commitHierarchy
    */
   _emptySoon: function VV__emptySoon(aTimeout) {
     let prevList = this._list;
     let currList = this._list = this.document.createElement("scrollbox");
 
     this._store.clear();
+    this._items.length = 0;
     this._itemsByElement.clear();
 
     this._emptyTimeout = this.window.setTimeout(function() {
       this._emptyTimeout = null;
 
       prevList.removeEventListener("keypress", this._onViewKeyPress, false);
       currList.addEventListener("keypress", this._onViewKeyPress, false);
       currList.setAttribute("orient", "vertical");
@@ -524,74 +528,83 @@ VariablesView.prototype = {
       let match = scope._firstMatch;
       if (match) {
         match.expand();
       }
     }
   },
 
   /**
-   * Focuses the first visible variable or property in this container.
+   * Find the first item in the tree of visible items in this container that
+   * matches the predicate. Searches in visual order (the order seen by the
+   * user). Descends into each scope to check the scope and its children.
+   *
+   * @param function aPredicate
+   *        A function that returns true when a match is found.
+   * @return Scope | Variable | Property
+   *         The first visible scope, variable or property, or null if nothing
+   *         is found.
+   */
+  _findInVisibleItems: function VV__findInVisibleItems(aPredicate) {
+    for (let scope of this._items) {
+      let result = scope._findInVisibleItems(aPredicate);
+      if (result) {
+        return result;
+      }
+    }
+    return null;
+  },
+
+  /**
+   * Find the last item in the tree of visible items in this container that
+   * matches the predicate. Searches in reverse visual order (opposite of the
+   * order seen by the user). Descends into each scope to check the scope and
+   * its children.
+   *
+   * @param function aPredicate
+   *        A function that returns true when a match is found.
+   * @return Scope | Variable | Property
+   *         The last visible scope, variable or property, or null if nothing
+   *         is found.
+   */
+  _findInVisibleItemsReverse: function VV__findInVisibleItemsReverse(aPredicate) {
+    for (let i = this._items.length - 1; i >= 0; i--) {
+      let scope = this._items[i];
+      let result = scope._findInVisibleItemsReverse(aPredicate);
+      if (result) {
+        return result;
+      }
+    }
+    return null;
+  },
+
+  /**
+   * Focuses the first visible scope, variable, or property in this container.
    */
   focusFirstVisibleNode: function VV_focusFirstVisibleNode() {
-    let property, variable, scope;
-
-    for (let [, item] of this._currHierarchy) {
-      if (!item.focusable) {
-        continue;
-      }
-      if (item instanceof Property) {
-        property = item;
-        break;
-      } else if (item instanceof Variable) {
-        variable = item;
-        break;
-      } else if (item instanceof Scope) {
-        scope = item;
-        break;
-      }
-    }
-    if (scope) {
-      this._focusItem(scope);
-    } else if (variable) {
-      this._focusItem(variable);
-    } else if (property) {
-      this._focusItem(property);
+    let focusableItem = this._findInVisibleItems(item => item.focusable);
+
+    if (focusableItem) {
+      this._focusItem(focusableItem);
     }
     this._parent.scrollTop = 0;
     this._parent.scrollLeft = 0;
   },
 
   /**
-   * Focuses the last visible variable or property in this container.
+   * Focuses the last visible scope, variable, or property in this container.
    */
   focusLastVisibleNode: function VV_focusLastVisibleNode() {
-    let property, variable, scope;
-
-    for (let [, item] of this._currHierarchy) {
-      if (!item.focusable) {
-        continue;
-      }
-      if (item instanceof Property) {
-        property = item;
-      } else if (item instanceof Variable) {
-        variable = item;
-      } else if (item instanceof Scope) {
-        scope = item;
-      }
+    let focusableItem = this._findInVisibleItemsReverse(item => item.focusable);
+
+    if (focusableItem) {
+      this._focusItem(focusableItem);
     }
-    if (property && (!variable || property.isDescendantOf(variable))) {
-      this._focusItem(property);
-    } else if (variable && (!scope || variable.isDescendantOf(scope))) {
-      this._focusItem(variable);
-    } else if (scope) {
-      this._focusItem(scope);
-      this._parent.scrollTop = this._parent.scrollHeight;
-      this._parent.scrollLeft = 0;
-    }
+    this._parent.scrollTop = this._parent.scrollHeight;
+    this._parent.scrollLeft = 0;
   },
 
   /**
    * Searches for the scope in this container displayed by the specified node.
    *
    * @param nsIDOMNode aNode
    *        The node to search for.
    * @return Scope
@@ -883,16 +896,17 @@ VariablesView.prototype = {
    * @return nsIDOMWindow
    */
   get window() this._window || (this._window = this.document.defaultView),
 
   _document: null,
   _window: null,
 
   _store: null,
+  _items: null,
   _prevHierarchy: null,
   _currHierarchy: null,
   _enumVisible: true,
   _nonEnumVisible: true,
   _emptyTimeout: null,
   _searchTimeout: null,
   _searchFunction: null,
   _parent: null,
@@ -1077,16 +1091,18 @@ function Scope(aView, aName, aFlags = {}
   this.editableNameTooltip = aView.editableNameTooltip;
   this.editButtonTooltip = aView.editButtonTooltip;
   this.deleteButtonTooltip = aView.deleteButtonTooltip;
   this.descriptorTooltip = aView.descriptorTooltip;
   this.contextMenuId = aView.contextMenuId;
   this.separatorStr = aView.separatorStr;
 
   this._store = new Map();
+  this._enumItems = [];
+  this._nonEnumItems = [];
   this._init(aName.trim(), aFlags);
 }
 
 Scope.prototype = {
   /**
    * Adds a variable to contain any inspected properties.
    *
    * @param string aName
@@ -1781,16 +1797,99 @@ Scope.prototype = {
       if (match) {
         return match;
       }
     }
     return null;
   },
 
   /**
+   * Find the first item in the tree of visible items in this item that matches
+   * the predicate. Searches in visual order (the order seen by the user).
+   * Tests itself, then descends into first the enumerable children and then
+   * the non-enumerable children (since they are presented in separate groups).
+   *
+   * @param function aPredicate
+   *        A function that returns true when a match is found.
+   * @return Scope | Variable | Property
+   *         The first visible scope, variable or property, or null if nothing
+   *         is found.
+   */
+  _findInVisibleItems: function S__findInVisibleItems(aPredicate) {
+    if (aPredicate(this)) {
+      return this;
+    }
+
+    if (this._isExpanded) {
+      if (this._variablesView._enumVisible) {
+        for (let item of this._enumItems) {
+          let result = item._findInVisibleItems(aPredicate);
+          if (result) {
+            return result;
+          }
+        }
+      }
+
+      if (this._variablesView._nonEnumVisible) {
+        for (let item of this._nonEnumItems) {
+          let result = item._findInVisibleItems(aPredicate);
+          if (result) {
+            return result;
+          }
+        }
+      }
+    }
+
+    return null;
+  },
+
+  /**
+   * Find the last item in the tree of visible items in this item that matches
+   * the predicate. Searches in reverse visual order (opposite of the order
+   * seen by the user). Descends into first the non-enumerable children, then
+   * the enumerable children (since they are presented in separate groups), and
+   * finally tests itself.
+   *
+   * @param function aPredicate
+   *        A function that returns true when a match is found.
+   * @return Scope | Variable | Property
+   *         The last visible scope, variable or property, or null if nothing
+   *         is found.
+   */
+  _findInVisibleItemsReverse: function S__findInVisibleItemsReverse(aPredicate) {
+    if (this._isExpanded) {
+      if (this._variablesView._nonEnumVisible) {
+        for (let i = this._nonEnumItems.length - 1; i >= 0; i--) {
+          let item = this._nonEnumItems[i];
+          let result = item._findInVisibleItemsReverse(aPredicate);
+          if (result) {
+            return result;
+          }
+        }
+      }
+
+      if (this._variablesView._enumVisible) {
+        for (let i = this._enumItems.length - 1; i >= 0; i--) {
+          let item = this._enumItems[i];
+          let result = item._findInVisibleItemsReverse(aPredicate);
+          if (result) {
+            return result;
+          }
+        }
+      }
+    }
+
+    if (aPredicate(this)) {
+      return this;
+    }
+
+    return null;
+  },
+
+  /**
    * Gets top level variables view instance.
    * @return VariablesView
    */
   get _variablesView() this._topView || (this._topView = (function(self) {
     let parentView = self.ownerView;
     let topView;
 
     while (topView = parentView.ownerView) {
@@ -1849,17 +1948,19 @@ Scope.prototype = {
   _isMatch: true,
   _idString: "",
   _nameString: "",
   _target: null,
   _arrow: null,
   _name: null,
   _title: null,
   _enum: null,
+  _enumItems: null,
   _nonenum: null,
+  _nonEnumItems: null,
   _throbber: null
 };
 
 /**
  * A Variable is a Scope holding Property instances.
  * Iterable via "for (let [name, property] in instance) { }".
  *
  * @param Scope aScope
@@ -2162,18 +2263,20 @@ ViewHelpers.create({ constructor: Variab
    * @param boolean aImmediateFlag
    *        @see Scope.prototype._lazyAppend
    */
   _onInit: function V__onInit(aImmediateFlag) {
     if (this._initialDescriptor.enumerable ||
         this._nameString == "this" ||
         this._nameString == "<exception>") {
       this.ownerView._lazyAppend(aImmediateFlag, true, this._target);
+      this.ownerView._enumItems.push(this);
     } else {
       this.ownerView._lazyAppend(aImmediateFlag, false, this._target);
+      this.ownerView._nonEnumItems.push(this);
     }
   },
 
   /**
    * Creates the necessary nodes for this variable.
    */
   _displayVariable: function V__createVariable() {
     let document = this.document;
@@ -2669,18 +2772,20 @@ ViewHelpers.create({ constructor: Proper
    * be attached to the owner view.
    *
    * @param boolean aImmediateFlag
    *        @see Scope.prototype._lazyAppend
    */
   _onInit: function P__onInit(aImmediateFlag) {
     if (this._initialDescriptor.enumerable) {
       this.ownerView._lazyAppend(aImmediateFlag, true, this._target);
+      this.ownerView._enumItems.push(this);
     } else {
       this.ownerView._lazyAppend(aImmediateFlag, false, this._target);
+      this.ownerView._nonEnumItems.push(this);
     }
   }
 });
 
 /**
  * A generator-iterator over the VariablesView, Scopes, Variables and Properties.
  */
 VariablesView.prototype.__iterator__ =
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -658,19 +658,29 @@ var HeadsUpDisplayUICommands = {
 
       if (!DebuggerServer.initialized) {
         DebuggerServer.init();
         DebuggerServer.addBrowserActors();
       }
 
       let client = new DebuggerClient(DebuggerServer.connectPipe());
       client.connect(() =>
-        client.listTabs((aResponse) =>
-          deferred.resolve({ form: aResponse, client: client })
-        ));
+        client.listTabs((aResponse) => {
+          // Add Global Process debugging...
+          let globals = JSON.parse(JSON.stringify(aResponse));
+          delete globals.tabs;
+          delete globals.selected;
+          // ...only if there are appropriate actors (a 'from' property will
+          // always be there).
+          if (Object.keys(globals).length > 1) {
+            deferred.resolve({ form: globals, client: client, chrome: true });
+          } else {
+            deferred.reject("Global console not found!");
+          }
+        }));
 
       return deferred.promise;
     }
 
     let target;
     function getTarget(aConnection)
     {
       let options = {
--- a/browser/devtools/webconsole/webconsole.xul
+++ b/browser/devtools/webconsole/webconsole.xul
@@ -57,18 +57,18 @@
       <menuitem id="saveBodiesContextMenu" type="checkbox" label="&saveBodies.label;"
                 accesskey="&saveBodies.accesskey;"/>
       <menuitem id="menu_openURL" label="&openURL.label;"
                 accesskey="&openURL.accesskey;" command="consoleCmd_openURL"
                 selection="network" selectionType="single"/>
       <menuitem id="menu_copyURL" label="&copyURLCmd.label;"
                 accesskey="&copyURLCmd.accesskey;" command="consoleCmd_copyURL"
                 selection="network" selectionType="single"/>
-      <menuitem id="menu_copy"/>
-      <menuitem id="menu_selectAll"/>
+      <menuitem id="cMenu_copy"/>
+      <menuitem id="cMenu_selectAll"/>
     </menupopup>
   </popupset>
 
   <box class="hud-outer-wrapper devtools-responsive-container" flex="1">
     <vbox class="hud-console-wrapper" flex="1">
       <toolbar class="hud-console-filter-toolbar devtools-toolbar" mode="full">
         <toolbarbutton label="&btnPageNet.label;" type="menu-button"
                        category="net" class="devtools-toolbarbutton webconsole-filter-button"
--- a/browser/themes/linux/devtools/netmonitor.css
+++ b/browser/themes/linux/devtools/netmonitor.css
@@ -88,21 +88,23 @@
 }
 
 .requests-menu-method {
   text-align: center;
   font-weight: 600;
 }
 
 .requests-menu-file {
-  width: 14em;
+  width: 20vw;
+  min-width: 4em;
 }
 
 .requests-menu-domain {
-  width: 14em;
+  width: 14vw;
+  min-width: 10em;
 }
 
 .requests-menu-type {
   text-align: center;
   width: 4em;
 }
 
 .requests-menu-size {
@@ -298,18 +300,49 @@
   transition: transform 0.2s ease-out;
 }
 
 /* Responsive sidebar */
 @media (max-width: 700px) {
   #details-pane {
     max-width: none;
     margin: 0 !important;
-    /* To prevent all the margin hacks to hide the sidebar */
+    /* To prevent all the margin hacks to hide the sidebar. */
+  }
+
+  .requests-menu-status-and-method {
+    width: 14vw;
+  }
+
+  .requests-menu-file,
+  .requests-menu-domain {
+    width: 30vw;
+    min-width: 10em;
+  }
+
+  .requests-menu-type {
+    width: 8vw;
   }
 
   .requests-menu-size {
-    border-width: 0px !important;
+    width: 16vw;
+    border-width: 0 !important;
     box-shadow: none !important;
-    /* !important are required here because Timeline is not visible and thus
-       the right border and box-shadow of Size column should be hidden */
+    /* The "Timeline" header is not visible anymore, and thus the
+       right border and box-shadow of "Size" column should be hidden. */
   }
 }
+
+@media (min-width: 701px) {
+  #network-table[type-overflows] .requests-menu-domain {
+    border-width: 0 !important;
+    box-shadow: none !important;
+    /* The "Type" header is not visible anymore, and thus the
+       right border and box-shadow of "Domain" column should be hidden. */
+  }
+
+  #network-table[domain-overflows] .requests-menu-file {
+    border-width: 0 !important;
+    box-shadow: none !important;
+    /* The "Domain" header is not visible anymore, and thus the
+       right border and box-shadow of "File" column should be hidden. */
+  }
+}
--- a/browser/themes/osx/devtools/netmonitor.css
+++ b/browser/themes/osx/devtools/netmonitor.css
@@ -88,21 +88,23 @@
 }
 
 .requests-menu-method {
   text-align: center;
   font-weight: 600;
 }
 
 .requests-menu-file {
-  width: 16em;
+  width: 20vw;
+  min-width: 4em;
 }
 
 .requests-menu-domain {
-  width: 16em;
+  width: 14vw;
+  min-width: 10em;
 }
 
 .requests-menu-type {
   text-align: center;
   width: 4em;
 }
 
 .requests-menu-size {
@@ -298,18 +300,49 @@
   transition: transform 0.2s ease-out;
 }
 
 /* Responsive sidebar */
 @media (max-width: 700px) {
   #details-pane {
     max-width: none;
     margin: 0 !important;
-    /* To prevent all the margin hacks to hide the sidebar */
+    /* To prevent all the margin hacks to hide the sidebar. */
+  }
+
+  .requests-menu-status-and-method {
+    width: 14vw;
+  }
+
+  .requests-menu-file,
+  .requests-menu-domain {
+    width: 30vw;
+    min-width: 10em;
+  }
+
+  .requests-menu-type {
+    width: 8vw;
   }
 
   .requests-menu-size {
-    border-width: 0px !important;
+    width: 16vw;
+    border-width: 0 !important;
     box-shadow: none !important;
-    /* !important are required here because Timeline is not visible and thus
-       the right border and box-shadow of Size column should be hidden */
+    /* The "Timeline" header is not visible anymore, and thus the
+       right border and box-shadow of "Size" column should be hidden. */
   }
 }
+
+@media (min-width: 701px) {
+  #network-table[type-overflows] .requests-menu-domain {
+    border-width: 0 !important;
+    box-shadow: none !important;
+    /* The "Type" header is not visible anymore, and thus the
+       right border and box-shadow of "Domain" column should be hidden. */
+  }
+
+  #network-table[domain-overflows] .requests-menu-file {
+    border-width: 0 !important;
+    box-shadow: none !important;
+    /* The "Domain" header is not visible anymore, and thus the
+       right border and box-shadow of "File" column should be hidden. */
+  }
+}
--- a/browser/themes/windows/devtools/netmonitor.css
+++ b/browser/themes/windows/devtools/netmonitor.css
@@ -88,21 +88,23 @@
 }
 
 .requests-menu-method {
   text-align: center;
   font-weight: 600;
 }
 
 .requests-menu-file {
-  width: 16em;
+  width: 20vw;
+  min-width: 4em;
 }
 
 .requests-menu-domain {
-  width: 16em;
+  width: 14vw;
+  min-width: 10em;
 }
 
 .requests-menu-type {
   text-align: center;
   width: 4em;
 }
 
 .requests-menu-size {
@@ -298,18 +300,49 @@
   transition: transform 0.2s ease-out;
 }
 
 /* Responsive sidebar */
 @media (max-width: 700px) {
   #details-pane {
     max-width: none;
     margin: 0 !important;
-    /* To prevent all the margin hacks to hide the sidebar */
+    /* To prevent all the margin hacks to hide the sidebar. */
+  }
+
+  .requests-menu-status-and-method {
+    width: 14vw;
+  }
+
+  .requests-menu-file,
+  .requests-menu-domain {
+    width: 30vw;
+    min-width: 10em;
+  }
+
+  .requests-menu-type {
+    width: 8vw;
   }
 
   .requests-menu-size {
-    border-width: 0px !important;
+    width: 16vw;
+    border-width: 0 !important;
     box-shadow: none !important;
-    /* !important are required here because Timeline is not visible and thus
-       the right border and box-shadow of Size column should be hidden */
+    /* The "Timeline" header is not visible anymore, and thus the
+       right border and box-shadow of "Size" column should be hidden. */
   }
 }
+
+@media (min-width: 701px) {
+  #network-table[type-overflows] .requests-menu-domain {
+    border-width: 0 !important;
+    box-shadow: none !important;
+    /* The "Type" header is not visible anymore, and thus the
+       right border and box-shadow of "Domain" column should be hidden. */
+  }
+
+  #network-table[domain-overflows] .requests-menu-file {
+    border-width: 0 !important;
+    box-shadow: none !important;
+    /* The "Domain" header is not visible anymore, and thus the
+       right border and box-shadow of "File" column should be hidden. */
+  }
+}
--- a/toolkit/devtools/debugger/server/dbg-script-actors.js
+++ b/toolkit/devtools/debugger/server/dbg-script-actors.js
@@ -592,35 +592,41 @@ ThreadActor.prototype = {
    * take that into account.
    *
    * @param object aLocation
    *        The location of the breakpoint as specified in the protocol.
    */
   _setBreakpoint: function TA__setBreakpoint(aLocation) {
     let breakpoints = this._breakpointStore[aLocation.url];
 
+    // Get or create the breakpoint actor for the given location
     let actor;
     if (breakpoints[aLocation.line].actor) {
       actor = breakpoints[aLocation.line].actor;
     } else {
       actor = breakpoints[aLocation.line].actor = new BreakpointActor(this, {
         url: aLocation.url,
         line: aLocation.line
       });
       this._hooks.addToParentPool(actor);
     }
 
+    // Find all scripts matching the given location
     let scripts = this.dbg.findScripts(aLocation);
     if (scripts.length == 0) {
       return {
         error: "noScript",
         actor: actor.actorID
       };
     }
 
+   /**
+     * For each script, if the given line has at least one entry point, set
+     * breakpoint on the bytecode offet for each of them.
+     */
     let found = false;
     for (let script of scripts) {
       let offsets = script.getLineOffsets(aLocation.line);
       if (offsets.length > 0) {
         for (let offset of offsets) {
           script.setBreakpoint(offset, actor);
         }
         actor.addScript(script, this);
@@ -628,65 +634,93 @@ ThreadActor.prototype = {
       }
     }
     if (found) {
       return {
         actor: actor.actorID
       };
     }
 
+   /**
+     * If we get here, no breakpoint was set. This is because the given line
+     * has no entry points, for example because it is empty. As a fallback
+     * strategy, we try to set the breakpoint on the smallest line greater
+     * than or equal to the given line that as at least one entry point.
+     */
+
+    // Find all innermost scripts matching the given location
     let scripts = this.dbg.findScripts({
       url: aLocation.url,
       line: aLocation.line,
       innermost: true
     });
 
+    /**
+     * For each innermost script, look for the smallest line greater than or
+     * equal to the given line that has one or more entry points. If found, set
+     * a breakpoint on the bytecode offset for each of its entry points.
+     */
     let actualLocation;
     let found = false;
     for (let script of scripts) {
       let offsets = script.getAllOffsets();
       for (let line = aLocation.line; line < offsets.length; ++line) {
         if (offsets[line]) {
           for (let offset of offsets[line]) {
             script.setBreakpoint(offset, actor);
           }
           actor.addScript(script, this);
           if (!actualLocation) {
             actualLocation = {
               url: aLocation.url,
               line: line,
-              column: aLocation.column
+              column: 0
             };
           }
           found = true;
           break;
         }
       }
     }
     if (found) {
       if (breakpoints[actualLocation.line] &&
           breakpoints[actualLocation.line].actor) {
+        /**
+         * We already have a breakpoint actor for the actual location, so
+         * actor we created earlier is now redundant. Delete it, update the
+         * breakpoint store, and return the actor for the actual location.
+         */
         actor.onDelete();
         delete breakpoints[aLocation.line];
         return {
           actor: breakpoints[actualLocation.line].actor.actorID,
           actualLocation: actualLocation
         };
       } else {
+        /**
+         * We don't have a breakpoint actor for the actual location yet.
+         * Instead or creating a new actor, reuse the actor we created earlier,
+         * and update the breakpoint store.
+         */
         actor.location = actualLocation;
         breakpoints[actualLocation.line] = breakpoints[aLocation.line];
+        delete breakpoints[aLocation.line];
+        // WARNING: This overwrites aLocation.line
         breakpoints[actualLocation.line].line = actualLocation.line;
-        delete breakpoints[aLocation.line];
         return {
           actor: actor.actorID,
           actualLocation: actualLocation
         };
       }
     }
 
+    /**
+     * If we get here, no line matching the given line was found, so just
+     * epically.
+     */
     return {
       error: "noCodeAtLineColumn",
       actor: actor.actorID
     };
   },
 
   /**
    * Get the script and source lists from the debugger.
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -97,17 +97,17 @@ function initialize(event) {
     return;
   }
 
   // Default to the last selected category
   var view = gCategories.node.value;
 
   // Allow passing in a view through the window arguments
   if ("arguments" in window && window.arguments.length > 0 &&
-      "view" in window.arguments[0]) {
+      window.arguments[0] !== null && "view" in window.arguments[0]) {
     view = window.arguments[0].view;
   }
 
   gViewController.loadInitialView(view);
 }
 
 function notifyInitialized() {
   if (!gIsInitializing)