Merge mx-team to m-c
authorWes Kocher <wkocher@mozilla.com>
Wed, 25 Sep 2013 20:43:35 -0700
changeset 163503 e85b0372cece1bb73a37bd89a8c053971021c835
parent 163494 902ae6cd5fa1c2d58f3df5d93ab053a2885cddb9 (current diff)
parent 163502 851e6aed858aa95386bb3e16d0fdc3093e3d1541 (diff)
child 163531 87b26cec9ee1b84075a24ef5b180221577458b93
child 163541 0b43f32e0af7e93128e64c36f830e965119663d1
child 163549 160ec7af5cb95369a0d5338ae035999f89563ee6
child 171344 91a937dfb947145bbc2250fbff2cd58b6f4833eb
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.0a1
first release with
nightly linux32
e85b0372cece / 27.0a1 / 20130926030207 / files
nightly linux64
e85b0372cece / 27.0a1 / 20130926030207 / files
nightly mac
e85b0372cece / 27.0a1 / 20130926030207 / files
nightly win32
e85b0372cece / 27.0a1 / 20130926030207 / files
nightly win64
e85b0372cece / 27.0a1 / 20130926030207 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mx-team to m-c
mobile/android/base/background/announcements/AnnouncementsStartReceiver.java
mobile/android/base/background/healthreport/upload/HealthReportBroadcastReceiver.java
mobile/android/base/background/healthreport/upload/HealthReportBroadcastService.java
mobile/android/base/background/healthreport/upload/HealthReportUploadStartReceiver.java
--- a/browser/devtools/framework/gDevTools.jsm
+++ b/browser/devtools/framework/gDevTools.jsm
@@ -122,53 +122,76 @@ DevTools.prototype = {
       if (devtools.defaultTools.indexOf(value) == -1) {
         tools.push(value);
       }
     }
     return tools.sort(this.ordinalSort);
   },
 
   /**
+   * Get a tool definition if it exists and is enabled.
+   *
+   * @param {string} toolId
+   *        The id of the tool to show
+   *
+   * @return {ToolDefinition|null} tool
+   *         The ToolDefinition for the id or null.
+   */
+  getToolDefinition: function DT_getToolDefinition(toolId) {
+    let tool = this._tools.get(toolId);
+    if (!tool) {
+      return null;
+    } else if (tool.id == "options") {
+      return tool;
+    }
+
+    let enabled;
+    try {
+      enabled = Services.prefs.getBoolPref(tool.visibilityswitch);
+    } catch (e) {
+      enabled = true;
+    }
+
+    return enabled ? tool : null;
+  },
+
+  /**
    * Allow ToolBoxes to get at the list of tools that they should populate
    * themselves with.
    *
    * @return {Map} tools
    *         A map of the the tool definitions registered in this instance
    */
   getToolDefinitionMap: function DT_getToolDefinitionMap() {
     let tools = new Map();
 
-    for (let [key, value] of this._tools) {
-      let enabled;
-
-      try {
-        enabled = Services.prefs.getBoolPref(value.visibilityswitch);
-      } catch(e) {
-        enabled = true;
-      }
-
-      if (enabled || value.id == "options") {
-        tools.set(key, value);
+    for (let [id, definition] of this._tools) {
+      if (this.getToolDefinition(id)) {
+        tools.set(id, definition);
       }
     }
+
     return tools;
   },
 
   /**
    * Tools have an inherent ordering that can't be represented in a Map so
    * getToolDefinitionArray provides an alternative representation of the
    * definitions sorted by ordinal value.
    *
    * @return {Array} tools
    *         A sorted array of the tool definitions registered in this instance
    */
   getToolDefinitionArray: function DT_getToolDefinitionArray() {
     let definitions = [];
-    for (let [id, definition] of this.getToolDefinitionMap()) {
-      definitions.push(definition);
+
+    for (let [id, definition] of this._tools) {
+      if (this.getToolDefinition(id)) {
+        definitions.push(definition);
+      }
     }
 
     return definitions.sort(this.ordinalSort);
   },
 
   /**
    * Show a Toolbox for a target (either by creating a new one, or if a toolbox
    * already exists for the target, by bring to the front the existing one)
@@ -410,18 +433,17 @@ let gDevToolsBrowser = {
    * - if the toolbox is open, and the targetted tool is selected,
    *   and the host is NOT a window, we close the toolbox
    * - if the toolbox is open, and the targetted tool is selected,
    *   and the host is a window, we raise the toolbox window
    */
   selectToolCommand: function(gBrowser, toolId) {
     let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
     let toolbox = gDevTools.getToolbox(target);
-    let tools = gDevTools.getToolDefinitionMap();
-    let toolDefinition = tools.get(toolId);
+    let toolDefinition = gDevTools.getToolDefinition(toolId);
 
     if (toolbox && toolbox.currentToolId == toolId) {
       toolbox.fireCustomKey(toolId);
 
       if (toolDefinition.preventClosingOnKey || toolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
         toolbox.raise();
       } else {
         toolbox.destroy();
@@ -598,23 +620,16 @@ let gDevToolsBrowser = {
     let fragAppMenuItems = doc.createDocumentFragment();
     let fragMenuItems = doc.createDocumentFragment();
 
     for (let toolDefinition of gDevTools.getToolDefinitionArray()) {
       if (toolDefinition.id == "options") {
         continue;
       }
 
-      // Skip if the tool is disabled.
-      try {
-        if (!Services.prefs.getBoolPref(toolDefinition.visibilityswitch)) {
-          continue;
-        }
-      } catch(e) {}
-
       let elements = gDevToolsBrowser._createToolMenuElements(toolDefinition, doc);
 
       if (!elements) {
         return;
       }
 
       fragCommands.appendChild(elements.cmd);
       if (elements.key) {
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -1,58 +1,52 @@
 /* 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 {Cc, Ci, Cu} = require("chrome");
 const MAX_ORDINAL = 99;
 const ZOOM_PREF = "devtools.toolbox.zoomValue";
 const MIN_ZOOM = 0.5;
 const MAX_ZOOM = 2;
 
+let {Cc, Ci, Cu} = require("chrome");
 let promise = require("sdk/core/promise");
 let EventEmitter = require("devtools/shared/event-emitter");
 let Telemetry = require("devtools/shared/telemetry");
 let HUDService = require("devtools/webconsole/hudservice");
 
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/devtools/gDevTools.jsm");
 Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
 
 loader.lazyGetter(this, "Hosts", () => require("devtools/framework/toolbox-hosts").Hosts);
 
-XPCOMUtils.defineLazyModuleGetter(this, "CommandUtils",
-                                  "resource:///modules/devtools/DeveloperToolbar.jsm");
+loader.lazyImporter(this, "CommandUtils", "resource:///modules/devtools/DeveloperToolbar.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "toolboxStrings", function() {
+loader.lazyGetter(this, "toolboxStrings", () => {
   let bundle = Services.strings.createBundle("chrome://browser/locale/devtools/toolbox.properties");
-  let l10n = function(aName, ...aArgs) {
+  return (name, ...args) => {
     try {
-      if (aArgs.length == 0) {
-        return bundle.GetStringFromName(aName);
-      } else {
-        return bundle.formatStringFromName(aName, aArgs, aArgs.length);
+      if (!args.length) {
+        return bundle.GetStringFromName(name);
       }
+      return bundle.formatStringFromName(name, args, args.length);
     } catch (ex) {
-      Services.console.logStringMessage("Error reading '" + aName + "'");
+      Services.console.logStringMessage("Error reading '" + name + "'");
     }
   };
-  return l10n;
 });
 
-XPCOMUtils.defineLazyGetter(this, "Requisition", function() {
-  let scope = {};
-  Cu.import("resource://gre/modules/devtools/Require.jsm", scope);
+loader.lazyGetter(this, "Requisition", () => {
+  let {require} = Cu.import("resource://gre/modules/devtools/Require.jsm", {});
   Cu.import("resource://gre/modules/devtools/gcli.jsm", {});
-
-  let req = scope.require;
-  return req('gcli/cli').Requisition;
+  return require("gcli/cli").Requisition;
 });
 
 /**
  * A "Toolbox" is the component that holds all the tools for one specific
  * target. Visually, it's a document that includes the tools tabs and all
  * the iframes where the tool panels will be living in.
  *
  * @param {object} target
@@ -64,37 +58,36 @@ XPCOMUtils.defineLazyGetter(this, "Requi
  */
 function Toolbox(target, selectedTool, hostType) {
   this._target = target;
   this._toolPanels = new Map();
   this._telemetry = new Telemetry();
 
   this._toolRegistered = this._toolRegistered.bind(this);
   this._toolUnregistered = this._toolUnregistered.bind(this);
+  this._refreshHostTitle = this._refreshHostTitle.bind(this);
   this.destroy = this.destroy.bind(this);
 
   this._target.on("close", this.destroy);
 
   if (!hostType) {
     hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST);
   }
   if (!selectedTool) {
     selectedTool = Services.prefs.getCharPref(this._prefs.LAST_TOOL);
   }
-  let definitions = gDevTools.getToolDefinitionMap();
-  if (!definitions.get(selectedTool) && selectedTool != "options") {
+  if (!gDevTools.getToolDefinition(selectedTool)) {
     selectedTool = "webconsole";
   }
   this._defaultToolId = selectedTool;
 
   this._host = this._createHost(hostType);
 
   EventEmitter.decorate(this);
 
-  this._refreshHostTitle = this._refreshHostTitle.bind(this);
   this._target.on("navigate", this._refreshHostTitle);
   this.on("host-changed", this._refreshHostTitle);
   this.on("select", this._refreshHostTitle);
 
   gDevTools.on("tool-registered", this._toolRegistered);
   gDevTools.on("tool-unregistered", this._toolUnregistered);
 }
 exports.Toolbox = Toolbox;
@@ -102,58 +95,53 @@ exports.Toolbox = Toolbox;
 /**
  * The toolbox can be 'hosted' either embedded in a browser window
  * or in a separate window.
  */
 Toolbox.HostType = {
   BOTTOM: "bottom",
   SIDE: "side",
   WINDOW: "window"
-}
+};
 
 Toolbox.prototype = {
   _URL: "chrome://browser/content/devtools/framework/toolbox.xul",
 
   _prefs: {
     LAST_HOST: "devtools.toolbox.host",
     LAST_TOOL: "devtools.toolbox.selectedTool",
     SIDE_ENABLED: "devtools.toolbox.sideEnabled"
   },
 
-  HostType: Toolbox.HostType,
+  currentToolId: null,
 
   /**
    * Returns a *copy* of the _toolPanels collection.
    *
    * @return {Map} panels
    *         All the running panels in the toolbox
    */
-  getToolPanels: function TB_getToolPanels() {
-    let panels = new Map();
-
-    for (let [key, value] of this._toolPanels) {
-      panels.set(key, value);
-    }
-    return panels;
+  getToolPanels: function() {
+    return new Map(this._toolPanels);
   },
 
   /**
    * Access the panel for a given tool
    */
-  getPanel: function TBOX_getPanel(id) {
-    return this.getToolPanels().get(id);
+  getPanel: function(id) {
+    return this._toolPanels.get(id);
   },
 
   /**
    * This is a shortcut for getPanel(currentToolId) because it is much more
    * likely that we're going to want to get the panel that we've just made
    * visible
    */
-  getCurrentPanel: function TBOX_getCurrentPanel() {
-    return this.getToolPanels().get(this.currentToolId);
+  getCurrentPanel: function() {
+    return this._toolPanels.get(this.currentToolId);
   },
 
   /**
    * Get/alter the target of a Toolbox so we're debugging something different.
    * See Target.jsm for more details.
    * TODO: Do we allow |toolbox.target = null;| ?
    */
   get target() {
@@ -164,27 +152,16 @@ Toolbox.prototype = {
    * Get/alter the host of a Toolbox, i.e. is it in browser or in a separate
    * tab. See HostType for more details.
    */
   get hostType() {
     return this._host.type;
   },
 
   /**
-   * Get/alter the currently displayed tool.
-   */
-  get currentToolId() {
-    return this._currentToolId;
-  },
-
-  set currentToolId(value) {
-    this._currentToolId = value;
-  },
-
-  /**
    * Get the iframe containing the toolbox UI.
    */
   get frame() {
     return this._host.frame;
   },
 
   /**
    * Shortcut to the document containing the toolbox UI
@@ -198,20 +175,22 @@ Toolbox.prototype = {
    */
   get zoomValue() {
     return parseFloat(Services.prefs.getCharPref(ZOOM_PREF));
   },
 
   /**
    * Open the toolbox
    */
-  open: function TBOX_open() {
+  open: function() {
     let deferred = promise.defer();
 
-    this._host.create().then(iframe => {
+    return this._host.create().then(iframe => {
+      let deferred = promise.defer();
+
       let domReady = () => {
         iframe.removeEventListener("DOMContentLoaded", domReady, true);
 
         this.isReady = true;
 
         let closeButton = this.doc.getElementById("toolbox-close");
         closeButton.addEventListener("command", this.destroy, true);
 
@@ -221,288 +200,274 @@ Toolbox.prototype = {
         this._buildButtons();
         this._addKeysToWindow();
         this._addToolSwitchingKeys();
         this._addZoomKeys();
         this._loadInitialZoom();
 
         this._telemetry.toolOpened("toolbox");
 
-        this.selectTool(this._defaultToolId).then(function(panel) {
+        this.selectTool(this._defaultToolId).then(panel => {
           this.emit("ready");
           deferred.resolve();
-        }.bind(this));
+        });
       };
 
       iframe.addEventListener("DOMContentLoaded", domReady, true);
       iframe.setAttribute("src", this._URL);
+
+      return deferred.promise;
     });
-
-    return deferred.promise;
   },
 
-  _buildOptions: function TBOX__buildOptions() {
+  _buildOptions: function() {
     let key = this.doc.getElementById("toolbox-options-key");
-    key.addEventListener("command", function(toolId) {
-      this.selectTool(toolId);
-    }.bind(this, "options"), true);
+    key.addEventListener("command", () => {
+      this.selectTool("options");
+    }, true);
   },
 
-  _addToolSwitchingKeys: function TBOX__addToolSwitchingKeys() {
+  _addToolSwitchingKeys: function() {
     let nextKey = this.doc.getElementById("toolbox-next-tool-key");
     nextKey.addEventListener("command", this.selectNextTool.bind(this), true);
     let prevKey = this.doc.getElementById("toolbox-previous-tool-key");
     prevKey.addEventListener("command", this.selectPreviousTool.bind(this), true);
   },
 
   /**
    * Wire up the listeners for the zoom keys.
    */
-  _addZoomKeys: function TBOX__addZoomKeys() {
+  _addZoomKeys: function() {
     let inKey = this.doc.getElementById("toolbox-zoom-in-key");
     inKey.addEventListener("command", this.zoomIn.bind(this), true);
 
     let inKey2 = this.doc.getElementById("toolbox-zoom-in-key2");
     inKey2.addEventListener("command", this.zoomIn.bind(this), true);
 
     let outKey = this.doc.getElementById("toolbox-zoom-out-key");
     outKey.addEventListener("command", this.zoomOut.bind(this), true);
 
     let resetKey = this.doc.getElementById("toolbox-zoom-reset-key");
     resetKey.addEventListener("command", this.zoomReset.bind(this), true);
   },
 
   /**
    * Set zoom on toolbox to whatever the last setting was.
    */
-  _loadInitialZoom: function TBOX__loadInitialZoom() {
+  _loadInitialZoom: function() {
     this.setZoom(this.zoomValue);
   },
 
   /**
    * Increase zoom level of toolbox window - make things bigger.
    */
-  zoomIn: function TBOX__zoomIn() {
+  zoomIn: function() {
     this.setZoom(this.zoomValue + 0.1);
   },
 
   /**
    * Decrease zoom level of toolbox window - make things smaller.
    */
-  zoomOut: function TBOX__zoomOut() {
+  zoomOut: function() {
     this.setZoom(this.zoomValue - 0.1);
   },
 
   /**
    * Reset zoom level of the toolbox window.
    */
-  zoomReset: function TBOX__zoomReset() {
+  zoomReset: function() {
     this.setZoom(1);
   },
 
   /**
    * Set zoom level of the toolbox window.
    *
    * @param {number} zoomValue
    *        Zoom level e.g. 1.2
    */
-  setZoom: function TBOX__setZoom(zoomValue) {
+  setZoom: function(zoomValue) {
     // cap zoom value
     zoomValue = Math.max(zoomValue, MIN_ZOOM);
     zoomValue = Math.min(zoomValue, MAX_ZOOM);
 
     let contViewer = this.frame.docShell.contentViewer;
     let docViewer = contViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
 
     docViewer.fullZoom = zoomValue;
 
     Services.prefs.setCharPref(ZOOM_PREF, zoomValue);
   },
 
   /**
    * Adds the keys and commands to the Toolbox Window in window mode.
    */
-  _addKeysToWindow: function TBOX__addKeysToWindow() {
+  _addKeysToWindow: function() {
     if (this.hostType != Toolbox.HostType.WINDOW) {
       return;
     }
+
     let doc = this.doc.defaultView.parent.document;
+
     for (let [id, toolDefinition] of gDevTools.getToolDefinitionMap()) {
-      if (toolDefinition.key) {
-        // Prevent multiple entries for the same tool.
-        if (doc.getElementById("key_" + id)) {
-          continue;
-        }
-        let key = doc.createElement("key");
-        key.id = "key_" + id;
+      // Prevent multiple entries for the same tool.
+      if (!toolDefinition.key || doc.getElementById("key_" + id)) {
+        continue;
+      }
 
-        if (toolDefinition.key.startsWith("VK_")) {
-          key.setAttribute("keycode", toolDefinition.key);
-        } else {
-          key.setAttribute("key", toolDefinition.key);
-        }
+      let toolId = id;
+      let key = doc.createElement("key");
 
-        key.setAttribute("modifiers", toolDefinition.modifiers);
-        key.setAttribute("oncommand", "void(0);"); // needed. See bug 371900
-        key.addEventListener("command", function(toolId) {
-          this.selectTool(toolId).then(() => {
-              this.fireCustomKey(toolId);
-          });
-        }.bind(this, id), true);
-        doc.getElementById("toolbox-keyset").appendChild(key);
-      }
-    }
+      key.id = "key_" + toolId;
 
-    // Add key for opening Scratchpad from the detached window
-    if(doc.getElementById("key_scratchpad") == null) {
-      let key = doc.createElement("key");
-      key.id = "key_scratchpad";
+      if (toolDefinition.key.startsWith("VK_")) {
+        key.setAttribute("keycode", toolDefinition.key);
+      } else {
+        key.setAttribute("key", toolDefinition.key);
+      }
 
-      key.setAttribute("keycode", toolboxStrings("scratchpad.keycode"));
-      key.setAttribute("modifiers", "shift");
-      key.setAttribute("oncommand", "void(0)"); // needed. See bug 371900
-      key.addEventListener("command", function() {
-        ScratchpadManager.openScratchpad();
+      key.setAttribute("modifiers", toolDefinition.modifiers);
+      key.setAttribute("oncommand", "void(0);"); // needed. See bug 371900
+      key.addEventListener("command", () => {
+        this.selectTool(toolId).then(() => this.fireCustomKey(toolId));
       }, true);
       doc.getElementById("toolbox-keyset").appendChild(key);
     }
 
     // Add key for toggling the browser console from the detached window
-    if(doc.getElementById("key_browserconsole") == null) {
+    if (!doc.getElementById("key_browserconsole")) {
       let key = doc.createElement("key");
       key.id = "key_browserconsole";
 
       key.setAttribute("key", toolboxStrings("browserConsoleCmd.commandkey"));
       key.setAttribute("modifiers", "accel,shift");
       key.setAttribute("oncommand", "void(0)"); // needed. See bug 371900
-      key.addEventListener("command", function() {
+      key.addEventListener("command", () => {
         HUDService.toggleBrowserConsole();
       }, true);
       doc.getElementById("toolbox-keyset").appendChild(key);
     }
   },
 
 
   /**
    * Handle any custom key events.  Returns true if there was a custom key binding run
    * @param {string} toolId
    *        Which tool to run the command on (skip if not current)
    */
-  fireCustomKey: function TBOX_fireCustomKey(toolId) {
-    let tools = gDevTools.getToolDefinitionMap();
-    let activeToolDefinition = tools.get(toolId);
+  fireCustomKey: function(toolId) {
+    let toolDefinition = gDevTools.getToolDefinition(toolId);
 
-    if (activeToolDefinition.onkey && this.currentToolId === toolId) {
-        activeToolDefinition.onkey(this.getCurrentPanel());
+    if (toolDefinition.onkey && this.currentToolId === toolId) {
+      toolDefinition.onkey(this.getCurrentPanel());
     }
   },
 
   /**
    * Build the buttons for changing hosts. Called every time
    * the host changes.
    */
-  _buildDockButtons: function TBOX_createDockButtons() {
+  _buildDockButtons: function() {
     let dockBox = this.doc.getElementById("toolbox-dock-buttons");
 
     while (dockBox.firstChild) {
       dockBox.removeChild(dockBox.firstChild);
     }
 
     if (!this._target.isLocalTab) {
       return;
     }
 
     let closeButton = this.doc.getElementById("toolbox-close");
-    if (this.hostType === this.HostType.WINDOW) {
+    if (this.hostType == Toolbox.HostType.WINDOW) {
       closeButton.setAttribute("hidden", "true");
     } else {
       closeButton.removeAttribute("hidden");
     }
 
     let sideEnabled = Services.prefs.getBoolPref(this._prefs.SIDE_ENABLED);
 
-    for each (let position in this.HostType) {
+    for (let type in Toolbox.HostType) {
+      let position = Toolbox.HostType[type];
       if (position == this.hostType ||
-         (!sideEnabled && position == this.HostType.SIDE)) {
+          (!sideEnabled && position == Toolbox.HostType.SIDE)) {
         continue;
       }
 
       let button = this.doc.createElement("toolbarbutton");
       button.id = "toolbox-dock-" + position;
       button.className = "toolbox-dock-button";
       button.setAttribute("tooltiptext", toolboxStrings("toolboxDockButtons." +
                                                         position + ".tooltip"));
-      button.addEventListener("command", function(position) {
+      button.addEventListener("command", () => {
         this.switchHost(position);
-      }.bind(this, position));
+      });
 
       dockBox.appendChild(button);
     }
   },
 
   /**
    * Add tabs to the toolbox UI for registered tools
    */
-  _buildTabs: function TBOX_buildTabs() {
+  _buildTabs: function() {
     for (let definition of gDevTools.getToolDefinitionArray()) {
       this._buildTabForTool(definition);
     }
   },
 
   /**
    * Add buttons to the UI as specified in the devtools.window.toolbarSpec pref
    */
-  _buildButtons: function TBOX_buildButtons() {
+  _buildButtons: function() {
     if (!this.target.isLocalTab) {
       return;
     }
 
-    let toolbarSpec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
+    let spec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
     let env = CommandUtils.createEnvironment(this.target.tab.ownerDocument,
                                              this.target.window.document);
-    let requisition = new Requisition(env);
-
-    let buttons = CommandUtils.createButtons(toolbarSpec, this._target, this.doc, requisition);
-
+    let req = new Requisition(env);
+    let buttons = CommandUtils.createButtons(spec, this._target, this.doc, req);
     let container = this.doc.getElementById("toolbox-buttons");
     buttons.forEach(container.appendChild.bind(container));
   },
 
   /**
    * Build a tab for one tool definition and add to the toolbox
    *
    * @param {string} toolDefinition
    *        Tool definition of the tool to build a tab for.
    */
-  _buildTabForTool: function TBOX_buildTabForTool(toolDefinition) {
+  _buildTabForTool: function(toolDefinition) {
     if (!toolDefinition.isTargetSupported(this._target)) {
       return;
     }
 
     let tabs = this.doc.getElementById("toolbox-tabs");
     let deck = this.doc.getElementById("toolbox-deck");
 
     let id = toolDefinition.id;
 
+    if (toolDefinition.ordinal == undefined || toolDefinition.ordinal < 0) {
+      toolDefinition.ordinal = MAX_ORDINAL;
+    }
+
     let radio = this.doc.createElement("radio");
     // The radio element is not being used in the conventional way, thus
     // the devtools-tab class replaces the radio XBL binding with its base
     // binding (the control-item binding).
     radio.className = "toolbox-tab devtools-tab";
     radio.id = "toolbox-tab-" + id;
     radio.setAttribute("toolid", id);
-    if (toolDefinition.ordinal == undefined || toolDefinition.ordinal < 0) {
-      toolDefinition.ordinal = MAX_ORDINAL;
-    }
     radio.setAttribute("ordinal", toolDefinition.ordinal);
     radio.setAttribute("tooltiptext", toolDefinition.tooltip);
 
-    radio.addEventListener("command", function(id) {
+    radio.addEventListener("command", () => {
       this.selectTool(id);
-    }.bind(this, id));
+    });
 
     // spacer lets us center the image and label, while allowing cropping
     let spacer = this.doc.createElement("spacer");
     spacer.setAttribute("flex", "1");
     radio.appendChild(spacer);
 
     if (toolDefinition.icon) {
       let image = this.doc.createElement("image");
@@ -532,19 +497,18 @@ Toolbox.prototype = {
     vbox.id = "toolbox-panel-" + id;
 
 
     // If there is no tab yet, or the ordinal to be added is the largest one.
     if (tabs.childNodes.length == 0 ||
         +tabs.lastChild.getAttribute("ordinal") <= toolDefinition.ordinal) {
       tabs.appendChild(radio);
       deck.appendChild(vbox);
-    }
-    // else, iterate over all the tabs to get the correct location.
-    else {
+    } else {
+      // else, iterate over all the tabs to get the correct location.
       Array.some(tabs.childNodes, (node, i) => {
         if (+node.getAttribute("ordinal") > toolDefinition.ordinal) {
           tabs.insertBefore(radio, node);
           deck.insertBefore(vbox, deck.childNodes[i]);
           return true;
         }
       });
     }
@@ -553,37 +517,38 @@ Toolbox.prototype = {
   },
 
   /**
    * Ensure the tool with the given id is loaded.
    *
    * @param {string} id
    *        The id of the tool to load.
    */
-  loadTool: function TBOX_loadTool(id) {
+  loadTool: function(id) {
     let deferred = promise.defer();
     let iframe = this.doc.getElementById("toolbox-panel-iframe-" + id);
 
     if (iframe) {
       let panel = this._toolPanels.get(id);
       if (panel) {
         deferred.resolve(panel);
       } else {
-        this.once(id + "-ready", (panel) => {
+        this.once(id + "-ready", panel => {
           deferred.resolve(panel);
         });
       }
       return deferred.promise;
     }
 
-    let definition = gDevTools.getToolDefinitionMap().get(id);
+    let definition = gDevTools.getToolDefinition(id);
     if (!definition) {
       deferred.reject(new Error("no such tool id "+id));
       return deferred.promise;
     }
+
     iframe = this.doc.createElement("iframe");
     iframe.className = "toolbox-panel-iframe";
     iframe.id = "toolbox-panel-iframe-" + id;
     iframe.setAttribute("flex", 1);
     iframe.setAttribute("forceOwnRefreshDriver", "");
     iframe.tooltip = "aHTMLTooltip";
 
     let vbox = this.doc.getElementById("toolbox-panel-" + id);
@@ -607,42 +572,43 @@ Toolbox.prototype = {
   },
 
   /**
    * Switch to the tool with the given id
    *
    * @param {string} id
    *        The id of the tool to switch to
    */
-  selectTool: function TBOX_selectTool(id) {
+  selectTool: function(id) {
     let selected = this.doc.querySelector(".devtools-tab[selected]");
     if (selected) {
       selected.removeAttribute("selected");
     }
+
     let tab = this.doc.getElementById("toolbox-tab-" + id);
     tab.setAttribute("selected", "true");
 
-    let prevToolId = this._currentToolId;
 
-    if (this._currentToolId == id) {
+    if (this.currentToolId == id) {
       // re-focus tool to get key events again
       this.focusTool(id);
 
       // Return the existing panel in order to have a consistent return value.
       return promise.resolve(this._toolPanels.get(id));
     }
 
     if (!this.isReady) {
       throw new Error("Can't select tool, wait for toolbox 'ready' event");
     }
-    let tab = this.doc.getElementById("toolbox-tab-" + id);
+
+    tab = this.doc.getElementById("toolbox-tab-" + id);
 
     if (tab) {
-      if (prevToolId) {
-        this._telemetry.toolClosed(prevToolId);
+      if (this.currentToolId) {
+        this._telemetry.toolClosed(this.currentToolId);
       }
       this._telemetry.toolOpened(id);
     } else {
       throw new Error("No tool found");
     }
 
     let tabstrip = this.doc.getElementById("toolbox-tabs");
 
@@ -657,22 +623,22 @@ Toolbox.prototype = {
       }
     }
     tabstrip.selectedItem = tab;
 
     // and select the right iframe
     let deck = this.doc.getElementById("toolbox-deck");
     deck.selectedIndex = index;
 
-    this._currentToolId = id;
+    this.currentToolId = id;
     if (id != "options") {
       Services.prefs.setCharPref(this._prefs.LAST_TOOL, id);
     }
 
-    return this.loadTool(id).then((panel) => {
+    return this.loadTool(id).then(panel => {
       // focus the tool's frame to start receiving key events
       this.focusTool(id);
 
       this.emit("select", id);
       this.emit(id + "-selected", panel);
       return panel;
     });
   },
@@ -685,69 +651,68 @@ Toolbox.prototype = {
   focusTool: function(id) {
     let iframe = this.doc.getElementById("toolbox-panel-iframe-" + id);
     iframe.focus();
   },
 
   /**
    * Loads the tool next to the currently selected tool.
    */
-  selectNextTool: function TBOX_selectNextTool() {
+  selectNextTool: function() {
     let selected = this.doc.querySelector(".devtools-tab[selected]");
     let next = selected.nextSibling || selected.parentNode.firstChild;
     let tool = next.getAttribute("toolid");
     return this.selectTool(tool);
   },
 
   /**
    * Loads the tool just left to the currently selected tool.
    */
-  selectPreviousTool: function TBOX_selectPreviousTool() {
+  selectPreviousTool: function() {
     let selected = this.doc.querySelector(".devtools-tab[selected]");
     let previous = selected.previousSibling || selected.parentNode.lastChild;
     let tool = previous.getAttribute("toolid");
     return this.selectTool(tool);
   },
 
   /**
    * Highlights the tool's tab if it is not the currently selected tool.
    *
    * @param {string} id
    *        The id of the tool to highlight
    */
-  highlightTool: function TBOX_highlightTool(id) {
+  highlightTool: function(id) {
     let tab = this.doc.getElementById("toolbox-tab-" + id);
     tab && tab.classList.add("highlighted");
   },
 
   /**
    * De-highlights the tool's tab.
    *
    * @param {string} id
    *        The id of the tool to unhighlight
    */
-  unhighlightTool: function TBOX_unhighlightTool(id) {
+  unhighlightTool: function(id) {
     let tab = this.doc.getElementById("toolbox-tab-" + id);
     tab && tab.classList.remove("highlighted");
   },
 
   /**
    * Raise the toolbox host.
    */
-  raise: function TBOX_raise() {
+  raise: function() {
     this._host.raise();
   },
 
   /**
    * Refresh the host's title.
    */
-  _refreshHostTitle: function TBOX_refreshHostTitle() {
+  _refreshHostTitle: function() {
     let toolName;
-    let toolId = this.currentToolId;
-    let toolDef = gDevTools.getToolDefinitionMap().get(toolId);
+    let toolDef = gDevTools.getToolDefinition(this.currentToolId);
     if (toolDef) {
       toolName = toolDef.label;
     } else {
       // no tool is selected
       toolName = toolboxStrings("toolbox.defaultTitle");
     }
     let title = toolboxStrings("toolbox.titleTemplate",
                                toolName, this.target.url);
@@ -762,102 +727,95 @@ Toolbox.prototype = {
    * mix and match hosts and targets.
    *
    * @param {string} hostType
    *        The host type of the new host object
    *
    * @return {Host} host
    *        The created host object
    */
-  _createHost: function TBOX_createHost(hostType) {
+  _createHost: function(hostType) {
     if (!Hosts[hostType]) {
-      throw new Error('Unknown hostType: '+ hostType);
+      throw new Error("Unknown hostType: " + hostType);
     }
-    let newHost = new Hosts[hostType](this.target.tab);
 
     // clean up the toolbox if its window is closed
+    let newHost = new Hosts[hostType](this.target.tab);
     newHost.on("window-closed", this.destroy);
-
     return newHost;
   },
 
   /**
    * Switch to a new host for the toolbox UI. E.g.
    * bottom, sidebar, separate window.
    *
    * @param {string} hostType
    *        The host type of the new host object
    */
-  switchHost: function TBOX_switchHost(hostType) {
-    if (hostType == this._host.type) {
-      return;
-    }
-
-    if (!this._target.isLocalTab) {
+  switchHost: function(hostType) {
+    if (hostType == this._host.type || !this._target.isLocalTab) {
       return;
     }
 
     let newHost = this._createHost(hostType);
-    return newHost.create().then(function(iframe) {
+    return newHost.create().then(iframe => {
       // change toolbox document's parent to the new host
       iframe.QueryInterface(Ci.nsIFrameLoaderOwner);
       iframe.swapFrameLoaders(this.frame);
 
       this._host.off("window-closed", this.destroy);
       this._host.destroy();
 
       this._host = newHost;
 
       Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type);
 
       this._buildDockButtons();
       this._addKeysToWindow();
 
       this.emit("host-changed");
-    }.bind(this));
+    });
   },
 
   /**
    * Handler for the tool-registered event.
    * @param  {string} event
    *         Name of the event ("tool-registered")
    * @param  {string} toolId
    *         Id of the tool that was registered
    */
-  _toolRegistered: function TBOX_toolRegistered(event, toolId) {
-    let defs = gDevTools.getToolDefinitionMap();
-    let tool = defs.get(toolId);
-
+  _toolRegistered: function(event, toolId) {
+    let tool = gDevTools.getToolDefinition(toolId);
     this._buildTabForTool(tool);
   },
 
   /**
    * Handler for the tool-unregistered event.
    * @param  {string} event
    *         Name of the event ("tool-unregistered")
    * @param  {string|object} toolId
    *         Definition or id of the tool that was unregistered. Passing the
    *         tool id should be avoided as it is a temporary measure.
    */
-  _toolUnregistered: function TBOX_toolUnregistered(event, toolId) {
+  _toolUnregistered: function(event, toolId) {
     if (typeof toolId != "string") {
       toolId = toolId.id;
     }
 
     if (this._toolPanels.has(toolId)) {
       let instance = this._toolPanels.get(toolId);
       instance.destroy();
       this._toolPanels.delete(toolId);
     }
 
     let radio = this.doc.getElementById("toolbox-tab-" + toolId);
     let panel = this.doc.getElementById("toolbox-panel-" + toolId);
 
     if (radio) {
-      if (this._currentToolId == toolId) {
+      if (this.currentToolId == toolId) {
         let nextToolName = null;
         if (radio.nextSibling) {
           nextToolName = radio.nextSibling.getAttribute("toolid");
         }
         if (radio.previousSibling) {
           nextToolName = radio.previousSibling.getAttribute("toolid");
         }
         if (nextToolName) {
@@ -875,90 +833,81 @@ Toolbox.prototype = {
       let doc = this.doc.defaultView.parent.document;
       let key = doc.getElementById("key_" + toolId);
       if (key) {
         key.parentNode.removeChild(key);
       }
     }
   },
 
-
   /**
    * Get the toolbox's notification box
    *
    * @return The notification box element.
    */
-  getNotificationBox: function TBOX_getNotificationBox() {
+  getNotificationBox: function() {
     return this.doc.getElementById("toolbox-notificationbox");
   },
 
   /**
    * Remove all UI elements, detach from target and clear up
    */
-  destroy: function TBOX_destroy() {
+  destroy: function() {
     // If several things call destroy then we give them all the same
     // destruction promise so we're sure to destroy only once
     if (this._destroyer) {
       return this._destroyer;
     }
-    // Assign the "_destroyer" property before calling the other
-    // destroyer methods to guarantee that the Toolbox's destroy
-    // method is only executed once.
-    let deferred = promise.defer();
-    this._destroyer = deferred.promise;
 
     this._target.off("navigate", this._refreshHostTitle);
     this.off("select", this._refreshHostTitle);
     this.off("host-changed", this._refreshHostTitle);
 
     gDevTools.off("tool-registered", this._toolRegistered);
     gDevTools.off("tool-unregistered", this._toolUnregistered);
 
     // Revert docShell.allowJavascript back to its original value if it was
     // changed via the Disable JS option.
     if (typeof this._origAllowJavascript != "undefined") {
       let docShell = this._host.hostTab.linkedBrowser.docShell;
       docShell.allowJavascript = this._origAllowJavascript;
-      delete this._origAllowJavascript;
+      this._origAllowJavascript = undefined;
     }
 
     let outstanding = [];
 
     for (let [id, panel] of this._toolPanels) {
       try {
         outstanding.push(panel.destroy());
-      } catch(e) {
+      } catch (e) {
         // We don't want to stop here if any panel fail to close.
         console.error(e);
       }
     }
 
     let container = this.doc.getElementById("toolbox-buttons");
-    while(container.firstChild) {
+    while (container.firstChild) {
       container.removeChild(container.firstChild);
     }
 
     outstanding.push(this._host.destroy());
 
     this._telemetry.destroy();
 
-    promise.all(outstanding).then(() => {
+    return this._destroyer = promise.all(outstanding).then(() => {
       // Targets need to be notified that the toolbox is being torn down.
       // This is done after other destruction tasks since it may tear down
       // fronts and the debugger transport which earlier destroy methods may
       // require to complete.
       if (this._target) {
         let target = this._target;
         this._target = null;
         target.off("close", this.destroy);
         return target.destroy();
       }
-    }).then(function() {
+    }).then(() => {
       this.emit("destroyed");
       // Free _host after the call to destroyed in order to let a chance
       // to destroyed listeners to still query toolbox attributes
       this._host = null;
-      deferred.resolve();
-    }.bind(this));
-
-    return this._destroyer;
+    });
   }
 };
--- a/browser/metro/base/content/TopSites.js
+++ b/browser/metro/base/content/TopSites.js
@@ -3,20 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 /**
  * singleton to provide data-level functionality to the views
  */
 let TopSites = {
-  _initialized: false,
-
-  Site: Site,
-
   prepareCache: function(aForce){
     // front to the NewTabUtils' links cache
     //  -ensure NewTabUtils.links links are pre-cached
 
     // avoid re-fetching links data while a fetch is in flight
     if (this._promisedCache && !aForce) {
       return this._promisedCache;
     }
@@ -146,16 +142,17 @@ let TopSites = {
         NewTabUtils.pinnedLinks.pin(site, pinIndex);
       }
     }
     // clear out the cache, we'll fetch and re-render
     this._sites = null;
     this._sitesDirty.clear();
     this.update();
   },
+
   _linkFromNode: function _linkFromNode(aNode) {
     return {
       url: aNode.getAttribute("value"),
       title: aNode.getAttribute("label")
     };
   }
 };
 
--- a/browser/metro/base/content/browser-scripts.js
+++ b/browser/metro/base/content/browser-scripts.js
@@ -11,16 +11,19 @@ Cu.import("resource://gre/modules/Servic
  */
 
 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
                                   "resource://gre/modules/Downloads.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FormHistory",
                                   "resource://gre/modules/FormHistory.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
+                                  "resource://gre/modules/PageThumbs.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
                                   "resource://gre/modules/PluralForm.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -1,15 +1,14 @@
 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
 /* 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";
 
-Cu.import("resource://gre/modules/PageThumbs.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-server.jsm")
 
 /**
  * Constants
  */
 
 // Devtools Messages
 const debugServerStateChanged = "devtools.debugger.remote-enabled";
@@ -103,16 +102,17 @@ var BrowserUI = {
 
     Services.prefs.addObserver("browser.cache.disk_cache_ssl", this, false);
 
     // Init core UI modules
     ContextUI.init();
     PanelUI.init();
     FlyoutPanelsUI.init();
     PageThumbs.init();
+    NewTabUtils.init();
     SettingsCharm.init();
     NavButtonSlider.init();
 
     // We can delay some initialization until after startup.  We wait until
     // the first page is shown, then dispatch a UIReadyDelayed event.
     messageManager.addMessageListener("pageshow", function onPageShow() {
       if (getBrowser().currentURI.spec == "about:blank")
         return;
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -419,16 +419,17 @@
 #if MOZ_UPDATE_CHANNEL != release
 #ifdef MOZ_UPDATER
       <description class="text-blurb" id="currentChannelText">&channel.description.start;<label id="currentChannel"/>&channel.description.end;</description>
 #endif
 #endif
       <label id="about-policy-label"
             onclick="FlyoutPanelsUI.AboutFlyoutPanel.onPolicyClick(event);"
             class="text-link" value="&aboutHeader.policy.label;"/>
+      <spacer class="flyoutpanel-hack"/>
     </flyoutpanel>
 
 #ifdef MOZ_SERVICES_SYNC
     <flyoutpanel id="sync-flyoutpanel" class="flyout-narrow" headertext="&sync.flyout.title;">
 
       <vbox id="sync-presetup-container" collapsed="true">
         <description>&sync.flyout.presetup.description1;</description>
         <separator />
@@ -677,19 +678,22 @@
       </settings>
       <settings id="prefs-telemetry" label="&optionsHeader.telemetry.title;">
         <setting pref="toolkit.telemetry.enabled" type="bool" title="&optionsHeader.telemetry.label;"/>
       </settings>
       <settings id="prefs-dnt" label="&doNotTrack.title;">
         <description>&doNotTrack.desc;</description>
         <setting id="prefs-dnt-value" pref="privacy.donottrackheader.value" type="radio" >
           <radiogroup id="prefs-dnt-options">
-            <radio id="prefs-dnt-notrack" label="&doNotTrack.options.trackingNotOkay;" value="1"/>
-            <radio id="prefs-dnt-nopref" label="&doNotTrack.options.noPreference;" value="-1"/>
-            <radio id="prefs-dnt-oktrack" label="&doNotTrack.options.trackingOkay;" value="0"/>
+            <radio id="prefs-dnt-notrack" class="flyoutpanel-hack"
+                   label="&doNotTrack.options.trackingNotOkay;" value="1"/>
+            <radio id="prefs-dnt-nopref" class="flyoutpanel-hack"
+                   label="&doNotTrack.options.noPreference;" value="-1"/>
+            <radio id="prefs-dnt-oktrack" class="flyoutpanel-hack"
+                   label="&doNotTrack.options.trackingOkay;" value="0"/>
           </radiogroup>
         </setting>
       </settings>
     </flyoutpanel>
 
     <!-- Chrome touch selection overlay -->
     <box class="selection-overlay-hidden" id="chrome-selection-overlay"/>
 
--- a/browser/metro/base/content/startui/TopSitesView.js
+++ b/browser/metro/base/content/startui/TopSitesView.js
@@ -16,17 +16,16 @@ function TopSitesView(aGrid, aMaxSites) 
   this._topSitesMax = aMaxSites;
 
   // clean up state when the appbar closes
   StartUI.chromeWin.addEventListener('MozAppbarDismissing', this, false);
   let history = Cc["@mozilla.org/browser/nav-history-service;1"].
                 getService(Ci.nsINavHistoryService);
   history.addObserver(this, false);
 
-  PageThumbs.addExpirationFilter(this);
   Services.obs.addObserver(this, "Metro:RefreshTopsiteThumbnail", false);
 
   NewTabUtils.allPages.register(this);
   TopSites.prepareCache().then(function(){
     this.populateGrid();
   }.bind(this));
 }
 
@@ -35,17 +34,16 @@ TopSitesView.prototype = Util.extend(Obj
   _topSitesMax: null,
   // _lastSelectedSites used to temporarily store blocked/removed sites for undo/restore-ing
   _lastSelectedSites: null,
   // isUpdating used only for testing currently
   isUpdating: false,
 
   destruct: function destruct() {
     Services.obs.removeObserver(this, "Metro:RefreshTopsiteThumbnail");
-    PageThumbs.removeExpirationFilter(this);
     NewTabUtils.allPages.unregister(this);
     if (StartUI.chromeWin) {
       StartUI.chromeWin.removeEventListener('MozAppbarDismissing', this, false);
     }
     View.prototype.destruct.call(this);
   },
 
   handleItemClick: function tabview_handleItemClick(aItem) {
@@ -211,20 +209,16 @@ TopSitesView.prototype = Util.extend(Obj
     let nodes = this._set.querySelectorAll('richgriditem[value="'+url+'"]');
     for (let item of nodes) {
       if ("isBound" in item && item.isBound) {
         item.refreshBackgroundImage();
       }
     }
   },
 
-  filterForThumbnailExpiration: function filterForThumbnailExpiration(aCallback) {
-    aCallback([item.getAttribute("value") for (item of this._set.children)]);
-  },
-
   isFirstRun: function isFirstRun() {
     return prefs.getBoolPref("browser.firstrun.show.localepicker");
   },
 
   _adjustDOMforViewState: function _adjustDOMforViewState(aState) {
     if (!this._set)
       return;
     if (!aState)
--- a/browser/metro/theme/flyoutpanel.css
+++ b/browser/metro/theme/flyoutpanel.css
@@ -81,12 +81,8 @@ flyoutpanel[visible] {
 
 .flyout-close-button:hover {
   -moz-image-region: rect(0 64px 32px 32px);
 }
 
 .flyout-close-button:active {
   -moz-image-region: rect(0 96px 32px 64px);
 }
-
-.flyout-narrow {
-  width: 346px;
-}
--- a/browser/metro/theme/platform.css
+++ b/browser/metro/theme/platform.css
@@ -835,12 +835,19 @@ appbar toolbar[labelled] toolbarbutton >
 }
 
 /* Secondary sprite format: one sprite for everything */
 
 .appbar-secondary {
   list-style-image: url(chrome://browser/skin/images/appbar-icons.png);
 }
 
-.flyout-narrow description,
-.flyout-narrow label {
-  max-width: 266px; /* Accounts for a 40px padding on each side of the flyout */
+/* Flyout panels (sidebars) ------------------------------------------------- */
+
+.flyout-narrow {
+  width: 346px;
 }
+
+/* Some elements don't resize to fit their container properly for some reason.
+ * Setting max-width on the element or a child fixes it. */
+.flyout-narrow .flyoutpanel-hack {
+  max-width: calc(346px - 2 * 40px);
+}
--- a/browser/metro/theme/tiles.css
+++ b/browser/metro/theme/tiles.css
@@ -106,17 +106,16 @@ richgriditem:not([tiletype="thumbnail"])
   height: 16px;
   list-style-image: url("chrome://browser/skin/images/identity-icons-generic.png");
 }
 
 /* for larger favicons (which includes the fallback icon) */
 richgriditem:not([iconURI]) .tile-icon-box,
 richgriditem[iconURI=""] .tile-icon-box,
 richgriditem[iconsize="large"] .tile-icon-box {
-  background-color: transparent!important;
   border-color: transparent!important;
   padding: 4px;
 }
 
 richgriditem[iconsize="large"] .tile-icon-box > image,
 .tile-icon-box > image[src=""] {
   width: 24px;
   height: 24px;
@@ -124,16 +123,17 @@ richgriditem[iconsize="large"] .tile-ico
 
 .tile-desc {
   display: block;
   position: absolute;
   top: 6px;
   left: 52px; /* label goes to the right of the favicon */
   right: 0;
   padding: 1em 6px 6px 12px;
+  background: white;
   color: #333;
   margin: 0;
   -moz-margin-start: 0;
   display: block;
   font-size: 16px;
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
deleted file mode 100644
--- a/mobile/android/base/background/announcements/AnnouncementsStartReceiver.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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/. */
-
-package org.mozilla.gecko.background.announcements;
-
-import org.mozilla.gecko.background.BackgroundService;
-import org.mozilla.gecko.background.common.log.Logger;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Start the announcements service when instructed by the {@link android.app.AlarmManager}.
- */
-public class AnnouncementsStartReceiver extends BroadcastReceiver {
-
-  private static final String LOG_TAG = "AnnounceStartRec";
-
-  @Override
-  public void onReceive(Context context, Intent intent) {
-    if (AnnouncementsConstants.DISABLED) {
-      return;
-    }
-
-    Logger.debug(LOG_TAG, "AnnouncementsStartReceiver.onReceive().");
-    BackgroundService.runIntentInService(context, intent, AnnouncementsService.class);
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/healthreport/upload/HealthReportBroadcastReceiver.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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/. */
-
-package org.mozilla.gecko.background.healthreport.upload;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.background.healthreport.HealthReportConstants;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Watch for notifications to start the Health Report background upload service.
- *
- * Some observations:
- *
- * From the Android documentation: "Also note that as of Android 3.0 the user
- * needs to have started the application at least once before your application
- * can receive android.intent.action.BOOT_COMPLETED events."
- *
- * We really do want to launch on BOOT_COMPLETED, since it's possible for a user
- * to run Firefox, shut down the phone, then power it on again on the same day.
- * We want to submit a health report in this case, even though they haven't
- * launched Firefox since boot.
- */
-public class HealthReportBroadcastReceiver extends BroadcastReceiver {
-  public static final String LOG_TAG = HealthReportBroadcastReceiver.class.getSimpleName();
-
-  /**
-   * Forward the intent to an IntentService to do background processing.
-   */
-  @Override
-  public void onReceive(Context context, Intent intent) {
-    if (HealthReportConstants.UPLOAD_FEATURE_DISABLED) {
-      Logger.debug(LOG_TAG, "Health report upload feature is compile-time disabled; not forwarding intent.");
-      return;
-    }
-
-    Logger.debug(LOG_TAG, "Health report upload feature is compile-time enabled; forwarding intent.");
-    Intent service = new Intent(context, HealthReportBroadcastService.class);
-    service.putExtras(intent);
-    service.setAction(intent.getAction());
-    context.startService(service);
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/healthreport/upload/HealthReportBroadcastService.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/* 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/. */
-
-package org.mozilla.gecko.background.healthreport.upload;
-
-import org.mozilla.gecko.background.BackgroundService;
-import org.mozilla.gecko.background.common.GlobalConstants;
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.background.healthreport.HealthReportConstants;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-
-/**
- * A service which listens to broadcast intents from the system and from the
- * browser, registering or unregistering the main
- * {@link HealthReportUploadStartReceiver} with the {@link AlarmManager}.
- */
-public class HealthReportBroadcastService extends BackgroundService {
-  public static final String LOG_TAG = HealthReportBroadcastService.class.getSimpleName();
-  public static final String WORKER_THREAD_NAME = LOG_TAG + "Worker";
-
-  public HealthReportBroadcastService() {
-    super(WORKER_THREAD_NAME);
-  }
-
-  protected SharedPreferences getSharedPreferences() {
-    return this.getSharedPreferences(HealthReportConstants.PREFS_BRANCH, GlobalConstants.SHARED_PREFERENCES_MODE);
-  }
-
-  public long getPollInterval() {
-    return getSharedPreferences().getLong(HealthReportConstants.PREF_SUBMISSION_INTENT_INTERVAL_MSEC, HealthReportConstants.DEFAULT_SUBMISSION_INTENT_INTERVAL_MSEC);
-  }
-
-  public void setPollInterval(long interval) {
-    getSharedPreferences().edit().putLong(HealthReportConstants.PREF_SUBMISSION_INTENT_INTERVAL_MSEC, interval).commit();
-  }
-
-  /**
-   * Set or cancel an alarm to submit data for a profile.
-   *
-   * @param context
-   *          Android context.
-   * @param profileName
-   *          to submit data for.
-   * @param profilePath
-   *          to submit data for.
-   * @param enabled
-   *          whether the user has enabled submitting health report data for
-   *          this profile.
-   * @param serviceEnabled
-   *          whether submitting should be scheduled. If the user turns off
-   *          submitting, <code>enabled</code> could be false but we could need
-   *          to delete so <code>serviceEnabled</code> could be true.
-   */
-  protected void toggleAlarm(final Context context, String profileName, String profilePath, boolean enabled, boolean serviceEnabled) {
-    Logger.info(LOG_TAG, (serviceEnabled ? "R" : "Unr") + "egistering health report start broadcast receiver.");
-
-    // PendingIntents are compared without reference to their extras. Therefore
-    // even though we pass the profile details to the action, different
-    // profiles will share the *same* pending intent. In a multi-profile future,
-    // this will need to be addressed.  See Bug 882182.
-    final Intent service = new Intent(context, HealthReportUploadStartReceiver.class);
-    service.setAction("upload"); // PendingIntents "lose" their extras if no action is set.
-    service.putExtra("uploadEnabled", enabled);
-    service.putExtra("profileName", profileName);
-    service.putExtra("profilePath", profilePath);
-    final PendingIntent pending = PendingIntent.getBroadcast(context, 0, service, PendingIntent.FLAG_CANCEL_CURRENT);
-
-    if (!serviceEnabled) {
-      cancelAlarm(pending);
-      return;
-    }
-
-    final long pollInterval = getPollInterval();
-    scheduleAlarm(pollInterval, pending);
-  }
-
-  @Override
-  protected void onHandleIntent(Intent intent) {
-    Logger.setThreadLogTag(HealthReportConstants.GLOBAL_LOG_TAG);
-
-    if (HealthReportConstants.UPLOAD_FEATURE_DISABLED) {
-      Logger.debug(LOG_TAG, "Health report upload feature is compile-time disabled; not handling intent.");
-      return;
-    }
-
-    final String action = intent.getAction();
-    Logger.debug(LOG_TAG, "Health report upload feature is compile-time enabled; handling intent with action " + action + ".");
-
-    if (HealthReportConstants.ACTION_HEALTHREPORT_UPLOAD_PREF.equals(action)) {
-      handlePrefIntent(intent);
-      return;
-    }
-
-    if (Intent.ACTION_BOOT_COMPLETED.equals(action) ||
-        Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
-      BackgroundService.reflectContextToFennec(this,
-          GlobalConstants.GECKO_PREFERENCES_CLASS,
-          GlobalConstants.GECKO_BROADCAST_HEALTHREPORT_UPLOAD_PREF_METHOD);
-      return;
-    }
-
-    // Failure case.
-    Logger.warn(LOG_TAG, "Unknown intent " + action + ".");
-  }
-
-  /**
-   * Handle the intent sent by the browser when it wishes to notify us
-   * of the value of the user preference. Look at the value and toggle the
-   * alarm service accordingly.
-   */
-  protected void handlePrefIntent(Intent intent) {
-    if (!intent.hasExtra("enabled")) {
-      Logger.warn(LOG_TAG, "Got " + HealthReportConstants.ACTION_HEALTHREPORT_UPLOAD_PREF + " intent without enabled. Ignoring.");
-      return;
-    }
-
-    final boolean enabled = intent.getBooleanExtra("enabled", true);
-    Logger.debug(LOG_TAG, intent.getStringExtra("branch") + "/" +
-                          intent.getStringExtra("pref")   + " = " +
-                          (intent.hasExtra("enabled") ? enabled : ""));
-
-    String profileName = intent.getStringExtra("profileName");
-    String profilePath = intent.getStringExtra("profilePath");
-
-    if (profileName == null || profilePath == null) {
-      Logger.warn(LOG_TAG, "Got " + HealthReportConstants.ACTION_HEALTHREPORT_UPLOAD_PREF + " intent without profilePath or profileName. Ignoring.");
-      return;
-    }
-
-    Logger.pii(LOG_TAG, "Updating health report alarm for profile " + profileName + " at " + profilePath + ".");
-
-    final SharedPreferences sharedPrefs = getSharedPreferences();
-    final ObsoleteDocumentTracker tracker = new ObsoleteDocumentTracker(sharedPrefs);
-    final boolean hasObsoleteIds = tracker.hasObsoleteIds();
-
-    if (!enabled) {
-      final Editor editor = sharedPrefs.edit();
-      editor.remove(HealthReportConstants.PREF_LAST_UPLOAD_DOCUMENT_ID);
-
-      if (hasObsoleteIds) {
-        Logger.debug(LOG_TAG, "Health report upload disabled; scheduling deletion of " + tracker.numberOfObsoleteIds() + " documents.");
-        tracker.limitObsoleteIds();
-      } else {
-        // Primarily intended for debugging and testing.
-        Logger.debug(LOG_TAG, "Health report upload disabled and no deletes to schedule: clearing prefs.");
-        editor.remove(HealthReportConstants.PREF_FIRST_RUN);
-        editor.remove(HealthReportConstants.PREF_NEXT_SUBMISSION);
-      }
-
-      editor.commit();
-    }
-
-    // The user can toggle us off or on, or we can have obsolete documents to
-    // remove.
-    final boolean serviceEnabled = hasObsoleteIds || enabled;
-    toggleAlarm(this, profileName, profilePath, enabled, serviceEnabled);
-  }
-}
deleted file mode 100644
--- a/mobile/android/base/background/healthreport/upload/HealthReportUploadStartReceiver.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/* 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/. */
-
-package org.mozilla.gecko.background.healthreport.upload;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.background.healthreport.HealthReportConstants;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Start the Health Report background upload service when instructed by the
- * {@link android.app.AlarmManager}.
- */
-public class HealthReportUploadStartReceiver extends BroadcastReceiver {
-  public static final String LOG_TAG = HealthReportUploadStartReceiver.class.getSimpleName();
-
-  @Override
-  public void onReceive(Context context, Intent intent) {
-    if (HealthReportConstants.UPLOAD_FEATURE_DISABLED) {
-      Logger.debug(LOG_TAG, "Health report upload feature is compile-time disabled; not starting background upload service.");
-      return;
-    }
-
-    Logger.debug(LOG_TAG, "Health report upload feature is compile-time enabled; starting background upload service.");
-    Intent service = new Intent(context, HealthReportUploadService.class);
-    service.setAction(intent.getAction());
-    service.putExtras(intent); // profileName, profilePath, uploadEnabled are in the extras.
-    context.startService(service);
-  }
-}