author | Wes Kocher <wkocher@mozilla.com> |
Wed, 25 Sep 2013 20:43:35 -0700 | |
changeset 148736 | e85b0372cece1bb73a37bd89a8c053971021c835 |
parent 148727 | 902ae6cd5fa1c2d58f3df5d93ab053a2885cddb9 (current diff) |
parent 148735 | 851e6aed858aa95386bb3e16d0fdc3093e3d1541 (diff) |
child 148764 | 87b26cec9ee1b84075a24ef5b180221577458b93 |
child 148774 | 0b43f32e0af7e93128e64c36f830e965119663d1 |
child 148782 | 160ec7af5cb95369a0d5338ae035999f89563ee6 |
child 155802 | 91a937dfb947145bbc2250fbff2cd58b6f4833eb |
push id | 25354 |
push user | kwierso@gmail.com |
push date | Thu, 26 Sep 2013 03:43:55 +0000 |
treeherder | mozilla-central@e85b0372cece [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 27.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
27.0a1
/
20130926030207
/
pushlog to previous
nightly linux64
27.0a1
/
20130926030207
/
pushlog to previous
nightly mac
27.0a1
/
20130926030207
/
pushlog to previous
nightly win32
27.0a1
/
20130926030207
/
pushlog to previous
nightly win64
27.0a1
/
20130926030207
/
pushlog to previous
|
--- 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); - } -}