diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index f19577f8bcab..b5f472421125 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,9 +15,9 @@ - + - + @@ -151,7 +151,7 @@ - + - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 53ebf28b7d78..e38194c8136d 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,9 +15,9 @@ - + - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index f49fe4cb869f..039a73f98db8 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,11 +19,11 @@ - - + + - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 1aa761f86a1f..e2f36f800706 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,8 +17,8 @@ - - + + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index b050fb49dc5c..397d71a0c22a 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,9 +15,9 @@ - + - + @@ -129,7 +129,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 2ed87626e430..105d64fe7c52 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,9 +15,9 @@ - + - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index f49fe4cb869f..039a73f98db8 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,11 +19,11 @@ - - + + - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 3186b003bf05..b0a89ee124a8 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,9 +15,9 @@ - + - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 518a597eed19..dca9635f3afd 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "ea27c4ed5b6083c9e21d233d4804372ac4d5d353", + "git_revision": "31ef8deec7a04a988eb92309178b87cc0bde8220", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "4ba0821dc786dd00cbb5b3cc0ce997d00e7963be", + "revision": "7ede26b2954bae2861dccff4f92adc1e9897fef3", "repo_path": "integration/gaia-central" } diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 2ca9b0af85ed..2a623f330711 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,8 +17,8 @@ - - + + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 26426028b803..959b3cfc64af 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,9 +15,9 @@ - + - + diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js index a823cf9158a8..88a638cefecd 100644 --- a/browser/base/content/browser-addons.js +++ b/browser/base/content/browser-addons.js @@ -123,8 +123,7 @@ const gXPInstallObserver = { } }; - options.learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + - "find-and-install-add-ons"; + options.learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); let messageString; let notification = document.getElementById("addon-install-confirmation-notification"); @@ -132,17 +131,20 @@ const gXPInstallObserver = { // None of the add-ons are verified messageString = gNavigatorBundle.getString("addonConfirmInstallUnsigned.message"); notification.setAttribute("warning", "true"); + options.learnMoreURL += "unsigned-addons"; } else if (unsigned.length == 0) { // All add-ons are verified or don't need to be verified messageString = gNavigatorBundle.getString("addonConfirmInstall.message"); notification.removeAttribute("warning"); + options.learnMoreURL += "find-and-install-add-ons"; } else { // Some of the add-ons are unverified, the list of names will indicate // which messageString = gNavigatorBundle.getString("addonConfirmInstallSomeUnsigned.message"); notification.setAttribute("warning", "true"); + options.learnMoreURL += "unsigned-addons"; } let brandBundle = document.getElementById("bundle_brand"); @@ -310,8 +312,7 @@ const gXPInstallObserver = { // Add Learn More link when refusing to install an unsigned add-on if (install.error == AddonManager.ERROR_SIGNEDSTATE_REQUIRED) { - options.learnMoreURL = - Services.prefs.getCharPref("xpinstall.signatures.infoURL"); + options.learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; } messageString = gNavigatorBundle.getFormattedString(error, args); diff --git a/browser/components/places/tests/browser/browser_bookmarkProperties_addKeywordForThisSearch.js b/browser/components/places/tests/browser/browser_bookmarkProperties_addKeywordForThisSearch.js index ca954314dc46..1bcebcd293de 100644 --- a/browser/components/places/tests/browser/browser_bookmarkProperties_addKeywordForThisSearch.js +++ b/browser/components/places/tests/browser/browser_bookmarkProperties_addKeywordForThisSearch.js @@ -10,9 +10,7 @@ add_task(function* () { // We must wait for the context menu code to build metadata. yield openContextMenuForContentSelector(browser, 'form > input[name="search"]'); - yield withBookmarksDialog(function*() { - AddKeywordForSearchField(); - }, function* (dialogWin) { + yield withBookmarksDialog(AddKeywordForSearchField, function* (dialogWin) { let acceptBtn = dialogWin.document.documentElement.getButton("accept"); ok(acceptBtn.disabled, "Accept button is disabled"); diff --git a/browser/components/places/tests/browser/head.js b/browser/components/places/tests/browser/head.js index d8c14a05a92e..e5722d653722 100644 --- a/browser/components/places/tests/browser/head.js +++ b/browser/components/places/tests/browser/head.js @@ -310,7 +310,9 @@ let withBookmarksDialog = Task.async(function* (openFn, taskFn) { }); info("withBookmarksDialog: opening the dialog"); - yield openFn(); + // The dialog might be modal and could block our events loop, so executeSoon. + executeSoon(openFn); + info("withBookmarksDialog: waiting for the dialog"); let dialogWin = yield dialogPromise; diff --git a/browser/devtools/framework/test/browser.ini b/browser/devtools/framework/test/browser.ini index 8a1c783d528a..f5b6871c23ea 100644 --- a/browser/devtools/framework/test/browser.ini +++ b/browser/devtools/framework/test/browser.ini @@ -32,6 +32,7 @@ support-files = [browser_toolbox_highlight.js] [browser_toolbox_hosts.js] [browser_toolbox_hosts_size.js] +[browser_toolbox_minimize.js] [browser_toolbox_options.js] [browser_toolbox_options_disable_buttons.js] [browser_toolbox_options_disable_cache-01.js] diff --git a/browser/devtools/framework/test/browser_toolbox_minimize.js b/browser/devtools/framework/test/browser_toolbox_minimize.js new file mode 100644 index 000000000000..e213fcfa2978 --- /dev/null +++ b/browser/devtools/framework/test/browser_toolbox_minimize.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that when the toolbox is displayed in a bottom host, that host can be +// minimized to just the tabbar height, and maximized again. +// Also test that while minimized, switching to a tool, clicking on the +// settings, or clicking on the selected tool's tab maximizes the toolbox again. +// Finally test that the minimize button doesn't exist in other host types. + +const URL = "data:text/html;charset=utf8,test page"; + +add_task(function*() { + info("Create a test tab and open the toolbox"); + let tab = yield addTab(URL); + let target = TargetFactory.forTab(tab); + let toolbox = yield gDevTools.showToolbox(target, "webconsole"); + + let button = toolbox.doc.querySelector("#toolbox-dock-bottom-minimize"); + ok(button, "The minimize button exists in the default bottom host"); + + info("Try to minimize the toolbox"); + yield minimize(toolbox); + ok(parseInt(toolbox._host.frame.style.marginBottom, 10) < 0, + "The toolbox host has been hidden away with a negative-margin"); + + info("Try to maximize again the toolbox"); + yield maximize(toolbox); + ok(parseInt(toolbox._host.frame.style.marginBottom, 10) == 0, + "The toolbox host is shown again"); + + info("Minimize again and switch to another tool"); + yield minimize(toolbox); + let onMaximized = toolbox._host.once("maximized"); + yield toolbox.selectTool("inspector"); + yield onMaximized; + + info("Minimize again and click on the tab of the current tool"); + yield minimize(toolbox); + onMaximized = toolbox._host.once("maximized"); + let tabButton = toolbox.doc.querySelector("#toolbox-tab-inspector"); + EventUtils.synthesizeMouseAtCenter(tabButton, {}, toolbox.doc.defaultView); + yield onMaximized; + + info("Minimize again and click on the settings tab"); + yield minimize(toolbox); + onMaximized = toolbox._host.once("maximized"); + let settingsButton = toolbox.doc.querySelector("#toolbox-tab-options"); + EventUtils.synthesizeMouseAtCenter(settingsButton, {}, toolbox.doc.defaultView); + yield onMaximized; + + info("Switch to a different host"); + yield toolbox.switchHost(devtools.Toolbox.HostType.SIDE); + button = toolbox.doc.querySelector("#toolbox-dock-bottom-minimize"); + ok(!button, "The minimize button doesn't exist in the side host"); + + Services.prefs.clearUserPref("devtools.toolbox.host"); + yield toolbox.destroy(); + gBrowser.removeCurrentTab(); +}); + +function* minimize(toolbox) { + let button = toolbox.doc.querySelector("#toolbox-dock-bottom-minimize"); + let onMinimized = toolbox._host.once("minimized"); + EventUtils.synthesizeMouseAtCenter(button, {}, toolbox.doc.defaultView); + yield onMinimized; +} + +function* maximize(toolbox) { + let button = toolbox.doc.querySelector("#toolbox-dock-bottom-minimize"); + let onMaximized = toolbox._host.once("maximized"); + EventUtils.synthesizeMouseAtCenter(button, {}, toolbox.doc.defaultView); + yield onMaximized; +} diff --git a/browser/devtools/framework/toolbox-hosts.js b/browser/devtools/framework/toolbox-hosts.js index 83ca259bdd5c..c8996df91848 100644 --- a/browser/devtools/framework/toolbox-hosts.js +++ b/browser/devtools/framework/toolbox-hosts.js @@ -1,6 +1,7 @@ /* 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/. */ +/* globals DOMHelpers, Services */ "use strict"; @@ -49,7 +50,7 @@ BottomHost.prototype = { /** * Create a box at the bottom of the host tab. */ - create: function BH_create() { + create: function() { let deferred = promise.defer(); let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser; @@ -90,21 +91,69 @@ BottomHost.prototype = { /** * Raise the host. */ - raise: function BH_raise() { + raise: function() { focusTab(this.hostTab); }, /** - * Set the toolbox title. + * Minimize this host so that only the toolbox tabbar remains visible. + * @param {Number} height The height to minimize to. Defaults to 0, which + * means that the toolbox won't be visible at all once minimized. */ - setTitle: function BH_setTitle(title) { - // Nothing to do for this host type. + minimize: function(height=0) { + if (this.isMinimized) { + return; + } + this.isMinimized = true; + + this.frame.style.marginBottom = -this.frame.height + height + "px"; + this._splitter.classList.add("disabled"); + + let onTransitionEnd = () => { + this.frame.removeEventListener("transitionend", onTransitionEnd); + this.emit("minimized"); + }; + this.frame.addEventListener("transitionend", onTransitionEnd); }, + /** + * If the host was minimized before, maximize it again (the host will be + * maximized to the height it previously had). + */ + maximize: function() { + if (!this.isMinimized) { + return; + } + this.isMinimized = false; + + this.frame.style.marginBottom = "0"; + this._splitter.classList.remove("disabled"); + + let onTransitionEnd = () => { + this.frame.removeEventListener("transitionend", onTransitionEnd); + this.emit("maximized"); + }; + this.frame.addEventListener("transitionend", onTransitionEnd); + }, + + /** + * Toggle the minimize mode. + * @param {Number} minHeight The height to minimize to. + */ + toggleMinimizeMode: function(minHeight) { + this.isMinimized ? this.maximize() : this.minimize(minHeight); + }, + + /** + * Set the toolbox title. + * Nothing to do for this host type. + */ + setTitle: function() {}, + /** * Destroy the bottom dock. */ - destroy: function BH_destroy() { + destroy: function() { if (!this._destroyed) { this._destroyed = true; @@ -115,8 +164,7 @@ BottomHost.prototype = { return promise.resolve(null); } -} - +}; /** * Host object for the in-browser sidebar @@ -135,7 +183,7 @@ SidebarHost.prototype = { /** * Create a box in the sidebar of the host tab. */ - create: function SH_create() { + create: function() { let deferred = promise.defer(); let gBrowser = this.hostTab.ownerDocument.defaultView.gBrowser; @@ -175,21 +223,20 @@ SidebarHost.prototype = { /** * Raise the host. */ - raise: function SH_raise() { + raise: function() { focusTab(this.hostTab); }, /** * Set the toolbox title. + * Nothing to do for this host type. */ - setTitle: function SH_setTitle(title) { - // Nothing to do for this host type. - }, + setTitle: function() {}, /** * Destroy the sidebar. */ - destroy: function SH_destroy() { + destroy: function() { if (!this._destroyed) { this._destroyed = true; @@ -200,7 +247,7 @@ SidebarHost.prototype = { return promise.resolve(null); } -} +}; /** * Host object for the toolbox in a separate window @@ -219,14 +266,14 @@ WindowHost.prototype = { /** * Create a new xul window to contain the toolbox. */ - create: function WH_create() { + create: function() { let deferred = promise.defer(); let flags = "chrome,centerscreen,resizable,dialog=no"; let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank", flags, null); - let frameLoad = (event) => { + let frameLoad = () => { win.removeEventListener("load", frameLoad, true); win.focus(); this.frame = win.document.getElementById("toolbox-iframe"); @@ -258,21 +305,21 @@ WindowHost.prototype = { /** * Raise the host. */ - raise: function RH_raise() { + raise: function() { this._window.focus(); }, /** * Set the toolbox title. */ - setTitle: function WH_setTitle(title) { + setTitle: function(title) { this._window.document.title = title; }, /** * Destroy the window. */ - destroy: function WH_destroy() { + destroy: function() { if (!this._destroyed) { this._destroyed = true; @@ -296,14 +343,14 @@ function CustomHost(hostTab, options) { CustomHost.prototype = { type: "custom", - _sendMessageToTopWindow: function CH__sendMessageToTopWindow(msg, data) { + _sendMessageToTopWindow: function(msg, data) { // It's up to the custom frame owner (parent window) to honor // "close" or "raise" instructions. let topWindow = this.frame.ownerDocument.defaultView; if (!topWindow) { return; } - let json = {name:"toolbox-" + msg, uid: this.uid}; + let json = {name: "toolbox-" + msg, uid: this.uid}; if (data) { json.data = data; } @@ -313,35 +360,35 @@ CustomHost.prototype = { /** * Create a new xul window to contain the toolbox. */ - create: function CH_create() { + create: function() { return promise.resolve(this.frame); }, /** * Raise the host. */ - raise: function CH_raise() { + raise: function() { this._sendMessageToTopWindow("raise"); }, /** * Set the toolbox title. */ - setTitle: function CH_setTitle(title) { + setTitle: function(title) { this._sendMessageToTopWindow("title", { value: title }); }, /** * Destroy the window. */ - destroy: function WH_destroy() { + destroy: function() { if (!this._destroyed) { this._destroyed = true; this._sendMessageToTopWindow("close"); } return promise.resolve(null); } -} +}; /** * Switch to the given tab in a browser and focus the browser window diff --git a/browser/devtools/framework/toolbox.js b/browser/devtools/framework/toolbox.js index de1d382ff879..4e6c0e1ed29b 100644 --- a/browser/devtools/framework/toolbox.js +++ b/browser/devtools/framework/toolbox.js @@ -1,6 +1,9 @@ /* 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/. */ +/* globals gDevTools, DOMHelpers, toolboxStrings, InspectorFront, Selection, + getPerformanceActorsConnection, CommandUtils, DevToolsUtils, screenManager, + oscpu, Hosts, is64Bit */ "use strict"; @@ -128,6 +131,10 @@ function Toolbox(target, selectedTool, hostType, hostOptions) { this._onFocus = this._onFocus.bind(this); this._showDevEditionPromo = this._showDevEditionPromo.bind(this); this._updateTextboxMenuItems = this._updateTextboxMenuItems.bind(this); + this._onBottomHostMinimized = this._onBottomHostMinimized.bind(this); + this._onBottomHostMaximized = this._onBottomHostMaximized.bind(this); + this._onToolSelectWhileMinimized = this._onToolSelectWhileMinimized.bind(this); + this._onBottomHostWillChange = this._onBottomHostWillChange.bind(this); this._target.on("close", this.destroy); @@ -314,7 +321,7 @@ Toolbox.prototype = { /** * Open the toolbox */ - open: function () { + open: function() { return Task.spawn(function*() { let iframe = yield this._host.create(); let domReady = promise.defer(); @@ -391,13 +398,15 @@ Toolbox.prototype = { ]); // Lazily connect to the profiler here and don't wait for it to complete, - // used to intercept console.profile calls before the performance tools are open. + // used to intercept console.profile calls before the performance tools + // are open. let profilerReady = this._connectProfiler(); - // However, while testing, we must wait for the performance connection to finish, - // as most tests shut down without waiting for a toolbox destruction event, - // resulting in the shared profiler connection being opened and closed - // outside of the test that originally opened the toolbox. + // However, while testing, we must wait for the performance connection to + // finish, as most tests shut down without waiting for a toolbox + // destruction event, resulting in the shared profiler connection being + // opened and closed outside of the test that originally opened the + // toolbox. if (gDevTools.testing) { yield profilerReady; } @@ -429,13 +438,13 @@ Toolbox.prototype = { * } */ _prefChanged: function(event, data) { - switch(data.pref) { - case "devtools.cache.disabled": - this._applyCacheSettings(); - break; - case "devtools.serviceWorkers.testing.enabled": - this._applyServiceWorkersTestingSettings(); - break; + switch (data.pref) { + case "devtools.cache.disabled": + this._applyCacheSettings(); + break; + case "devtools.serviceWorkers.testing.enabled": + this._applyServiceWorkersTestingSettings(); + break; } }, @@ -628,7 +637,8 @@ Toolbox.prototype = { } key.setAttribute("modifiers", toolDefinition.modifiers); - key.setAttribute("oncommand", "void(0);"); // needed. See bug 371900 + // needed. See bug 371900 + key.setAttribute("oncommand", "void(0);"); key.addEventListener("command", () => { this.selectTool(toolId).then(() => this.fireCustomKey(toolId)); }, true); @@ -642,7 +652,8 @@ Toolbox.prototype = { key.setAttribute("key", toolboxStrings("browserConsoleCmd.commandkey")); key.setAttribute("modifiers", "accel,shift"); - key.setAttribute("oncommand", "void(0)"); // needed. See bug 371900 + // needed. See bug 371900 + key.setAttribute("oncommand", "void(0)"); key.addEventListener("command", () => { HUDService.toggleBrowserConsole(); }, true); @@ -651,9 +662,10 @@ Toolbox.prototype = { }, /** - * 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) + * 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(toolId) { let toolDefinition = gDevTools.getToolDefinition(toolId); @@ -680,6 +692,32 @@ Toolbox.prototype = { return; } + // Bottom-type host can be minimized, add a button for this. + if (this.hostType == Toolbox.HostType.BOTTOM) { + let minimizeBtn = this.doc.createElement("toolbarbutton"); + minimizeBtn.id = "toolbox-dock-bottom-minimize"; + minimizeBtn.className = "maximized"; + minimizeBtn.setAttribute("tooltiptext", + toolboxStrings("toolboxDockButtons.bottom.minimize")); + // Calculate the height to which the host should be minimized so the + // tabbar is still visible. + let toolbarHeight = this.doc.querySelector(".devtools-tabbar") + .getBoxQuads({box: "content"})[0] + .bounds.height; + minimizeBtn.addEventListener("command", () => { + this._host.toggleMinimizeMode(toolbarHeight); + }); + dockBox.appendChild(minimizeBtn); + + // Update the label and icon when the state changes. + this._host.on("minimized", this._onBottomHostMinimized); + this._host.on("maximized", this._onBottomHostMaximized); + // Maximize again when a tool gets selected. + this.on("before-select", this._onToolSelectWhileMinimized); + // Maximize and stop listening before the host type changes. + this.once("host-will-change", this._onBottomHostWillChange); + } + if (this.hostType == Toolbox.HostType.WINDOW) { this.closeButton.setAttribute("hidden", "true"); } else { @@ -709,6 +747,32 @@ Toolbox.prototype = { } }, + _onBottomHostMinimized: function() { + let btn = this.doc.querySelector("#toolbox-dock-bottom-minimize"); + btn.className = "minimized"; + btn.setAttribute("tooltiptext", + toolboxStrings("toolboxDockButtons.bottom.maximize")); + }, + + _onBottomHostMaximized: function() { + let btn = this.doc.querySelector("#toolbox-dock-bottom-minimize"); + btn.className = "maximized"; + btn.setAttribute("tooltiptext", + toolboxStrings("toolboxDockButtons.bottom.minimize")); + }, + + _onToolSelectWhileMinimized: function() { + this._host.maximize(); + }, + + _onBottomHostWillChange: function() { + this._host.maximize(); + + this._host.off("minimized", this._onBottomHostMinimized); + this._host.off("maximized", this._onBottomHostMaximized); + this.off("before-select", this._onToolSelectWhileMinimized); + }, + /** * Add tabs to the toolbox UI for registered tools */ @@ -835,8 +899,9 @@ Toolbox.prototype = { button: button, label: button.getAttribute("tooltiptext"), visibilityswitch: "devtools." + options.id + ".enabled", - isTargetSupported: options.isTargetSupported ? options.isTargetSupported - : target => target.isLocalTab + isTargetSupported: options.isTargetSupported + ? options.isTargetSupported + : target => target.isLocalTab }; }).filter(button=>button); }, @@ -847,7 +912,7 @@ Toolbox.prototype = { */ setToolboxButtonsVisibility: function() { this.toolboxButtons.forEach(buttonSpec => { - let { visibilityswitch, id, button, isTargetSupported } = buttonSpec; + let { visibilityswitch, button, isTargetSupported } = buttonSpec; let on = true; try { on = Services.prefs.getBoolPref(visibilityswitch); @@ -939,7 +1004,7 @@ Toolbox.prototype = { if (toolDefinition.label && !toolDefinition.iconOnly) { let label = this.doc.createElement("label"); - label.setAttribute("value", toolDefinition.label) + label.setAttribute("value", toolDefinition.label); label.setAttribute("crop", "end"); label.setAttribute("flex", "1"); radio.appendChild(label); @@ -1018,7 +1083,7 @@ Toolbox.prototype = { let definition = gDevTools.getToolDefinition(id); if (!definition) { - deferred.reject(new Error("no such tool id "+id)); + deferred.reject(new Error("no such tool id " + id)); return deferred.promise; } @@ -1112,7 +1177,7 @@ Toolbox.prototype = { let callback = () => { iframe.removeEventListener("DOMContentLoaded", callback); onLoad(); - } + }; iframe.addEventListener("DOMContentLoaded", callback); } @@ -1126,6 +1191,8 @@ Toolbox.prototype = { * The id of the tool to switch to */ selectTool: function(id) { + this.emit("before-select", id); + let selected = this.doc.querySelector(".devtools-tab[selected]"); if (selected) { selected.removeAttribute("selected"); @@ -1364,7 +1431,7 @@ Toolbox.prototype = { this._host.setTitle(title); }, - _listFrames: function (event) { + _listFrames: function(event) { if (!this._target.activeTab || !this._target.activeTab.traits.frames) { // We are not targetting a regular TabActor // it can be either an addon or browser toolbox actor @@ -1379,7 +1446,7 @@ Toolbox.prototype = { }); }, - selectFrame: function (event) { + selectFrame: function(event) { let windowId = event.target.getAttribute("data-window-id"); let packet = { to: this._target.form.actor, @@ -1390,7 +1457,7 @@ Toolbox.prototype = { // Wait for frameUpdate event to update the UI }, - _updateFrames: function (event, data) { + _updateFrames: function(event, data) { if (!Services.prefs.getBoolPref("devtools.command-button-frames.enabled")) { return; } @@ -1420,7 +1487,7 @@ Toolbox.prototype = { menu.removeAttribute("checked"); } // Uncheck the previously selected frame - let selected = menu.querySelector("menuitem[checked=true]") + let selected = menu.querySelector("menuitem[checked=true]"); if (selected) { selected.removeAttribute("checked"); } @@ -1458,8 +1525,8 @@ Toolbox.prototype = { * Create a host object based on the given host type. * * Warning: some hosts require that the toolbox target provides a reference to - * the attached tab. Not all Targets have a tab property - make sure you correctly - * mix and match hosts and targets. + * the attached tab. Not all Targets have a tab property - make sure you + * correctly mix and match hosts and targets. * * @param {string} hostType * The host type of the new host object @@ -1490,6 +1557,8 @@ Toolbox.prototype = { return null; } + this.emit("host-will-change", hostType); + let newHost = this._createHost(hostType); return newHost.create().then(iframe => { // change toolbox document's parent to the new host @@ -1670,32 +1739,72 @@ Toolbox.prototype = { screenManager.primaryScreen.GetRect({}, {}, width, height); let dims = width.value + "x" + height.value; - if (width.value < 800 || height.value < 600) return 0; - if (dims === "800x600") return 1; - if (dims === "1024x768") return 2; - if (dims === "1280x800") return 3; - if (dims === "1280x1024") return 4; - if (dims === "1366x768") return 5; - if (dims === "1440x900") return 6; - if (dims === "1920x1080") return 7; - if (dims === "2560×1440") return 8; - if (dims === "2560×1600") return 9; - if (dims === "2880x1800") return 10; - if (width.value > 2880 || height.value > 1800) return 12; + if (width.value < 800 || height.value < 600) { + return 0; + } + if (dims === "800x600") { + return 1; + } + if (dims === "1024x768") { + return 2; + } + if (dims === "1280x800") { + return 3; + } + if (dims === "1280x1024") { + return 4; + } + if (dims === "1366x768") { + return 5; + } + if (dims === "1440x900") { + return 6; + } + if (dims === "1920x1080") { + return 7; + } + if (dims === "2560×1440") { + return 8; + } + if (dims === "2560×1600") { + return 9; + } + if (dims === "2880x1800") { + return 10; + } + if (width.value > 2880 || height.value > 1800) { + return 12; + } - return 11; // Other dimension such as a VM. + // Other dimension such as a VM. + return 11; }, _getOsCpu: function() { - if (oscpu.includes("NT 5.1") || oscpu.includes("NT 5.2")) return 0; - if (oscpu.includes("NT 6.0")) return 1; - if (oscpu.includes("NT 6.1")) return 2; - if (oscpu.includes("NT 6.2")) return 3; - if (oscpu.includes("NT 6.3")) return 4; - if (oscpu.includes("OS X")) return 5; - if (oscpu.includes("Linux")) return 6; + if (oscpu.includes("NT 5.1") || oscpu.includes("NT 5.2")) { + return 0; + } + if (oscpu.includes("NT 6.0")) { + return 1; + } + if (oscpu.includes("NT 6.1")) { + return 2; + } + if (oscpu.includes("NT 6.2")) { + return 3; + } + if (oscpu.includes("NT 6.3")) { + return 4; + } + if (oscpu.includes("OS X")) { + return 5; + } + if (oscpu.includes("Linux")) { + return 6; + } - return 12; // Other OS. + // Other OS. + return 12; }, /** @@ -1869,8 +1978,8 @@ Toolbox.prototype = { */ _updateTextboxMenuItems: function() { let window = this.doc.defaultView; - ['cmd_undo', 'cmd_delete', 'cmd_cut', - 'cmd_copy', 'cmd_paste','cmd_selectAll'].forEach(window.goUpdateCommand); + ["cmd_undo", "cmd_delete", "cmd_cut", + "cmd_copy", "cmd_paste", "cmd_selectAll"].forEach(window.goUpdateCommand); }, getPerformanceActorsConnection: function() { @@ -1920,7 +2029,7 @@ Toolbox.prototype = { * Opens source in style editor. Falls back to plain "view-source:". * @see browser/devtools/shared/source-utils.js */ - viewSourceInStyleEditor: function (sourceURL, sourceLine) { + viewSourceInStyleEditor: function(sourceURL, sourceLine) { return sourceUtils.viewSourceInStyleEditor(this, sourceURL, sourceLine); }, @@ -1928,7 +2037,7 @@ Toolbox.prototype = { * Opens source in debugger. Falls back to plain "view-source:". * @see browser/devtools/shared/source-utils.js */ - viewSourceInDebugger: function (sourceURL, sourceLine) { + viewSourceInDebugger: function(sourceURL, sourceLine) { return sourceUtils.viewSourceInDebugger(this, sourceURL, sourceLine); }, @@ -1941,7 +2050,7 @@ Toolbox.prototype = { * * @see browser/devtools/shared/source-utils.js */ - viewSourceInScratchpad: function (sourceURL, sourceLine) { + viewSourceInScratchpad: function(sourceURL, sourceLine) { return sourceUtils.viewSourceInScratchpad(sourceURL, sourceLine); }, @@ -1949,7 +2058,7 @@ Toolbox.prototype = { * Opens source in plain "view-source:". * @see browser/devtools/shared/source-utils.js */ - viewSource: function (sourceURL, sourceLine) { + viewSource: function(sourceURL, sourceLine) { return sourceUtils.viewSource(this, sourceURL, sourceLine); }, }; diff --git a/browser/locales/en-US/chrome/browser/devtools/toolbox.properties b/browser/locales/en-US/chrome/browser/devtools/toolbox.properties index c11f5015734f..671537e658fd 100644 --- a/browser/locales/en-US/chrome/browser/devtools/toolbox.properties +++ b/browser/locales/en-US/chrome/browser/devtools/toolbox.properties @@ -6,6 +6,20 @@ toolboxDockButtons.bottom.tooltip=Dock to bottom of browser window toolboxDockButtons.side.tooltip=Dock to side of browser window toolboxDockButtons.window.tooltip=Show in separate window +# LOCALIZATION NOTE (toolboxDockButtons.bottom.minimize): This string is shown +# as a tooltip that appears in the toolbox when it is in "bottom host" mode and +# when hovering over the minimize button in the toolbar. When clicked, the +# button minimizes the toolbox so that just the toolbar is visible at the +# bottom. +toolboxDockButtons.bottom.minimize=Minimize the toolbox + +# LOCALIZATION NOTE (toolboxDockButtons.bottom.maximize): This string is shown +# as a tooltip that appears in the toolbox when it is in "bottom host" mode and +# when hovering over the maximize button in the toolbar. When clicked, the +# button maximizes the toolbox again (if it had been minimized before) so that +# the whole toolbox is visible again. +toolboxDockButtons.bottom.maximize=Maximize the toolbox + # LOCALIZATION NOTE (toolboxToggleButton.errors): Semi-colon list of plural # forms. # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index 563cba601b2b..d08b9486ba18 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -377,6 +377,8 @@ browser.jar: skin/classic/browser/devtools/toggle-tools.png (../shared/devtools/images/toggle-tools.png) skin/classic/browser/devtools/toggle-tools@2x.png (../shared/devtools/images/toggle-tools@2x.png) skin/classic/browser/devtools/dock-bottom@2x.png (../shared/devtools/images/dock-bottom@2x.png) + skin/classic/browser/devtools/dock-bottom-minimize@2x.png (../shared/devtools/images/dock-bottom-minimize@2x.png) + skin/classic/browser/devtools/dock-bottom-maximize@2x.png (../shared/devtools/images/dock-bottom-maximize@2x.png) skin/classic/browser/devtools/dock-side@2x.png (../shared/devtools/images/dock-side@2x.png) skin/classic/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css) skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css) diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index b15957b6bdf8..af5be5a64272 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -495,6 +495,8 @@ browser.jar: skin/classic/browser/devtools/toggle-tools.png (../shared/devtools/images/toggle-tools.png) skin/classic/browser/devtools/toggle-tools@2x.png (../shared/devtools/images/toggle-tools@2x.png) skin/classic/browser/devtools/dock-bottom@2x.png (../shared/devtools/images/dock-bottom@2x.png) + skin/classic/browser/devtools/dock-bottom-minimize@2x.png (../shared/devtools/images/dock-bottom-minimize@2x.png) + skin/classic/browser/devtools/dock-bottom-maximize@2x.png (../shared/devtools/images/dock-bottom-maximize@2x.png) skin/classic/browser/devtools/dock-side@2x.png (../shared/devtools/images/dock-side@2x.png) * skin/classic/browser/devtools/inspector.css (../shared/devtools/inspector.css) skin/classic/browser/devtools/profiler-stopwatch.svg (../shared/devtools/images/profiler-stopwatch.svg) diff --git a/browser/themes/shared/devtools/common.css b/browser/themes/shared/devtools/common.css index 9465cd913c70..c96a9e352463 100644 --- a/browser/themes/shared/devtools/common.css +++ b/browser/themes/shared/devtools/common.css @@ -22,6 +22,11 @@ %endif } +/* Bottom-docked toolbox minimize transition */ +.devtools-toolbox-bottom-iframe { + transition: margin-bottom .1s; +} + /* Splitters */ .devtools-horizontal-splitter { -moz-appearance: none; @@ -48,6 +53,11 @@ cursor: e-resize; } +.devtools-horizontal-splitter.disabled, +.devtools-side-splitter.disabled { + pointer-events: none; +} + .devtools-toolbox-side-iframe { min-width: 465px; } diff --git a/browser/themes/shared/devtools/images/dock-bottom-maximize@2x.png b/browser/themes/shared/devtools/images/dock-bottom-maximize@2x.png new file mode 100644 index 000000000000..feb4d78eeca6 Binary files /dev/null and b/browser/themes/shared/devtools/images/dock-bottom-maximize@2x.png differ diff --git a/browser/themes/shared/devtools/images/dock-bottom-minimize@2x.png b/browser/themes/shared/devtools/images/dock-bottom-minimize@2x.png new file mode 100644 index 000000000000..a82983c9fe70 Binary files /dev/null and b/browser/themes/shared/devtools/images/dock-bottom-minimize@2x.png differ diff --git a/browser/themes/shared/devtools/toolbars.inc.css b/browser/themes/shared/devtools/toolbars.inc.css index 1d3c66ac1f81..f38e5ac94d8a 100644 --- a/browser/themes/shared/devtools/toolbars.inc.css +++ b/browser/themes/shared/devtools/toolbars.inc.css @@ -657,6 +657,14 @@ background-image: url("chrome://browser/skin/devtools/undock@2x.png"); } +#toolbox-dock-bottom-minimize > image { + background-image: url("chrome://browser/skin/devtools/dock-bottom-minimize@2x.png"); +} + +#toolbox-dock-bottom-minimize.minimized > image { + background-image: url("chrome://browser/skin/devtools/dock-bottom-maximize@2x.png"); +} + #toolbox-dock-window, #toolbox-dock-bottom, #toolbox-dock-side { diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index 5633e7beda5d..5567e4be2983 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -467,6 +467,8 @@ browser.jar: skin/classic/browser/devtools/toggle-tools.png (../shared/devtools/images/toggle-tools.png) skin/classic/browser/devtools/toggle-tools@2x.png (../shared/devtools/images/toggle-tools@2x.png) skin/classic/browser/devtools/dock-bottom@2x.png (../shared/devtools/images/dock-bottom@2x.png) + skin/classic/browser/devtools/dock-bottom-minimize@2x.png (../shared/devtools/images/dock-bottom-minimize@2x.png) + skin/classic/browser/devtools/dock-bottom-maximize@2x.png (../shared/devtools/images/dock-bottom-maximize@2x.png) skin/classic/browser/devtools/dock-side@2x.png (../shared/devtools/images/dock-side@2x.png) skin/classic/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css) skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css) diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 9a1eb52a0c75..19bda025ab71 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -4289,6 +4289,21 @@ WorkerDebugger::GetIsFrozen(bool* aResult) return NS_OK; } +NS_IMETHODIMP +WorkerDebugger::GetIsInitialized(bool* aResult) +{ + AssertIsOnMainThread(); + + MutexAutoLock lock(mMutex); + + if (!mWorkerPrivate) { + return NS_ERROR_UNEXPECTED; + } + + *aResult = mIsInitialized; + return NS_OK; +} + NS_IMETHODIMP WorkerDebugger::GetParent(nsIWorkerDebugger** aResult) { diff --git a/dom/workers/nsIWorkerDebugger.idl b/dom/workers/nsIWorkerDebugger.idl index e8052b226d33..9055116a1735 100644 --- a/dom/workers/nsIWorkerDebugger.idl +++ b/dom/workers/nsIWorkerDebugger.idl @@ -17,7 +17,7 @@ interface nsIWorkerDebuggerListener : nsISupports void onThaw(); }; -[scriptable, builtinclass, uuid(d7c73e54-3c41-4393-9d13-fa2ed4Ba6764)] +[scriptable, builtinclass, uuid(bdcaf96f-916a-4b24-bb53-165c1785668b)] interface nsIWorkerDebugger : nsISupports { const unsigned long TYPE_DEDICATED = 0; @@ -30,6 +30,8 @@ interface nsIWorkerDebugger : nsISupports readonly attribute bool isFrozen; + readonly attribute bool isInitialized; + readonly attribute nsIWorkerDebugger parent; readonly attribute unsigned long type; diff --git a/ipc/bluetooth/BluetoothDaemonConnection.cpp b/ipc/bluetooth/BluetoothDaemonConnection.cpp index 42c949ca1ca1..722f1fb4d0c7 100644 --- a/ipc/bluetooth/BluetoothDaemonConnection.cpp +++ b/ipc/bluetooth/BluetoothDaemonConnection.cpp @@ -42,10 +42,14 @@ static const char sBluetoothdSocketName[] = "bluez_hal_socket"; BluetoothDaemonPDU::BluetoothDaemonPDU(uint8_t aService, uint8_t aOpcode, uint16_t aPayloadSize) - : UnixSocketIOBuffer(HEADER_SIZE + aPayloadSize) - , mConsumer(nullptr) + : mConsumer(nullptr) , mUserData(nullptr) { + // Allocate memory + size_t availableSpace = HEADER_SIZE + aPayloadSize; + ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); + + // Reserve PDU header uint8_t* data = Append(HEADER_SIZE); MOZ_ASSERT(data); @@ -56,10 +60,18 @@ BluetoothDaemonPDU::BluetoothDaemonPDU(uint8_t aService, uint8_t aOpcode, } BluetoothDaemonPDU::BluetoothDaemonPDU(size_t aPayloadSize) - : UnixSocketIOBuffer(HEADER_SIZE + aPayloadSize) - , mConsumer(nullptr) + : mConsumer(nullptr) , mUserData(nullptr) -{ } +{ + size_t availableSpace = HEADER_SIZE + aPayloadSize; + ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); +} + +BluetoothDaemonPDU::~BluetoothDaemonPDU() +{ + nsAutoArrayPtr data(GetBuffer()); + ResetBuffer(nullptr, 0, 0, 0); +} void BluetoothDaemonPDU::GetHeader(uint8_t& aService, uint8_t& aOpcode, diff --git a/ipc/bluetooth/BluetoothDaemonConnection.h b/ipc/bluetooth/BluetoothDaemonConnection.h index 96481c9d3dfc..894723f2fdbe 100644 --- a/ipc/bluetooth/BluetoothDaemonConnection.h +++ b/ipc/bluetooth/BluetoothDaemonConnection.h @@ -56,6 +56,7 @@ public: BluetoothDaemonPDU(uint8_t aService, uint8_t aOpcode, uint16_t aPayloadSize); BluetoothDaemonPDU(size_t aPayloadSize); + ~BluetoothDaemonPDU(); void SetConsumer(BluetoothDaemonPDUConsumer* aConsumer) { diff --git a/ipc/unixsocket/SocketBase.cpp b/ipc/unixsocket/SocketBase.cpp index f14e469fc672..4d23997a81ac 100644 --- a/ipc/unixsocket/SocketBase.cpp +++ b/ipc/unixsocket/SocketBase.cpp @@ -18,27 +18,18 @@ namespace ipc { // UnixSocketIOBuffer // -UnixSocketBuffer::UnixSocketBuffer(const void* aData, size_t aSize) - : mSize(aSize) - , mOffset(0) - , mAvailableSpace(aSize) -{ - MOZ_ASSERT(aData || !mSize); - - mData = new uint8_t[mAvailableSpace]; - memcpy(mData, aData, mSize); -} - -UnixSocketBuffer::UnixSocketBuffer(size_t aAvailableSpace) +UnixSocketBuffer::UnixSocketBuffer() : mSize(0) , mOffset(0) - , mAvailableSpace(aAvailableSpace) -{ - mData = new uint8_t[mAvailableSpace]; -} + , mAvailableSpace(0) + , mData(nullptr) +{ } UnixSocketBuffer::~UnixSocketBuffer() -{ } +{ + // Make sure that the caller released the buffer's memory. + MOZ_ASSERT(!GetBuffer()); +} const uint8_t* UnixSocketBuffer::Consume(size_t aLen) @@ -105,14 +96,6 @@ UnixSocketBuffer::CleanupLeadingSpace() // UnixSocketIOBuffer // -UnixSocketIOBuffer::UnixSocketIOBuffer(const void* aData, size_t aSize) - : UnixSocketBuffer(aData, aSize) -{ } - -UnixSocketIOBuffer::UnixSocketIOBuffer(size_t aAvailableSpace) - : UnixSocketBuffer(aAvailableSpace) -{ } - UnixSocketIOBuffer::~UnixSocketIOBuffer() { } @@ -121,12 +104,23 @@ UnixSocketIOBuffer::~UnixSocketIOBuffer() // UnixSocketRawData::UnixSocketRawData(const void* aData, size_t aSize) -: UnixSocketIOBuffer(aData, aSize) -{ } +{ + MOZ_ASSERT(aData || !aSize); + + ResetBuffer(static_cast(memcpy(new uint8_t[aSize], aData, aSize)), + 0, aSize, aSize); +} UnixSocketRawData::UnixSocketRawData(size_t aSize) -: UnixSocketIOBuffer(aSize) -{ } +{ + ResetBuffer(new uint8_t[aSize], 0, 0, aSize); +} + +UnixSocketRawData::~UnixSocketRawData() +{ + nsAutoArrayPtr data(GetBuffer()); + ResetBuffer(nullptr, 0, 0, 0); +} ssize_t UnixSocketRawData::Receive(int aFd) diff --git a/ipc/unixsocket/SocketBase.h b/ipc/unixsocket/SocketBase.h index b684ca87bf5d..a34cb8a59eb0 100644 --- a/ipc/unixsocket/SocketBase.h +++ b/ipc/unixsocket/SocketBase.h @@ -109,15 +109,38 @@ public: } protected: + UnixSocketBuffer(); - /* This constructor copies aData of aSize bytes length into the - * new instance of |UnixSocketBuffer|. + /** + * Sets the raw memory. The caller is responsible for freeing + * this memory. + * + * @param aData A pointer to the buffer's raw memory. + * @param aOffset The start of valid bytes in |aData|. + * @param aSize The number of valid bytes in |aData|. + * @param aAvailableSpace The number of bytes in |aData|. */ - UnixSocketBuffer(const void* aData, size_t aSize); + void ResetBuffer(uint8_t* aData, + size_t aOffset, size_t aSize, size_t aAvailableSpace) + { + MOZ_ASSERT(aData || !aAvailableSpace); + MOZ_ASSERT((aOffset + aSize) <= aAvailableSpace); - /* This constructor reserves aAvailableSpace bytes of space. + mOffset = aOffset; + mSize = aSize; + mAvailableSpace = aAvailableSpace; + mData = aData; + } + + /** + * Retrieves the memory buffer. + * + * @return A pointer to the buffer's raw memory. */ - UnixSocketBuffer(size_t aAvailableSpace); + uint8_t* GetBuffer() + { + return mData; + } size_t GetLeadingSpace() const { @@ -160,7 +183,7 @@ private: size_t mSize; size_t mOffset; size_t mAvailableSpace; - nsAutoArrayPtr mData; + uint8_t* mData; }; // @@ -190,17 +213,6 @@ public: * is the number of bytes written, or a negative value on error. */ virtual ssize_t Send(int aFd) = 0; - -protected: - - /* This constructor copies aData of aSize bytes length into the - * new instance of |UnixSocketIOBuffer|. - */ - UnixSocketIOBuffer(const void* aData, size_t aSize); - - /* This constructor reserves aAvailableSpace bytes of space. - */ - UnixSocketIOBuffer(size_t aAvailableSpace); }; // @@ -210,16 +222,28 @@ protected: class UnixSocketRawData final : public UnixSocketIOBuffer { public: - /* This constructor copies aData of aSize bytes length into the + /** + * This constructor copies aData of aSize bytes length into the * new instance of |UnixSocketRawData|. + * + * @param aData The buffer to copy. + * @param aSize The number of bytes in |aData|. */ UnixSocketRawData(const void* aData, size_t aSize); - /* This constructor reserves aSize bytes of space. Currently + /** + * This constructor reserves aSize bytes of space. Currently * it's only possible to fill this buffer by calling |Receive|. + * + * @param aSize The number of bytes to allocate. */ UnixSocketRawData(size_t aSize); + /** + * The destructor releases the buffer's raw memory. + */ + ~UnixSocketRawData(); + /** * Receives data from aFd at the end of the buffer. The returned value * is the number of newly received bytes, or 0 if the peer shut down diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 31e2753cbe72..156cf2231e13 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -4545,7 +4545,7 @@ Tab.prototype = { // or pageshow event, but we'll still want to update the reader view button to account for this change. // This mirrors the desktop logic in TabsProgressListener. if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) { - this.browser.messageManager.sendAsyncMessage("Reader:PushState", {isArticle: gBrowser.selectedBrowser.isArticle}); + this.browser.messageManager.sendAsyncMessage("Reader:PushState", {isArticle: this.browser.isArticle}); } // Reset state of click-to-play plugin notifications. diff --git a/mobile/android/gradle/base/build.gradle b/mobile/android/gradle/base/build.gradle index a30d60751eba..84e40d0747b1 100644 --- a/mobile/android/gradle/base/build.gradle +++ b/mobile/android/gradle/base/build.gradle @@ -47,11 +47,11 @@ android { } dependencies { - compile 'com.android.support:support-v4:22.+' + compile 'com.android.support:support-v4:22.2.0' if (mozconfig.substs.MOZ_NATIVE_DEVICES) { - compile 'com.android.support:appcompat-v7:22.+' - compile 'com.android.support:mediarouter-v7:22.+' + compile 'com.android.support:appcompat-v7:22.2.0' + compile 'com.android.support:mediarouter-v7:22.2.0' compile 'com.google.android.gms:play-services-base:6.5.+' compile 'com.google.android.gms:play-services-cast:6.5.+' } diff --git a/mobile/android/gradle/thirdparty/build.gradle b/mobile/android/gradle/thirdparty/build.gradle index a99033eb2f5c..e85e8ab5e7a1 100644 --- a/mobile/android/gradle/thirdparty/build.gradle +++ b/mobile/android/gradle/thirdparty/build.gradle @@ -29,5 +29,5 @@ android { } dependencies { - compile 'com.android.support:support-v4:22.+' + compile 'com.android.support:support-v4:22.2.0' } diff --git a/mobile/android/gradle/thirdparty_adjust_sdk/build.gradle b/mobile/android/gradle/thirdparty_adjust_sdk/build.gradle index c56fa9444dd5..cc9b25fdee37 100644 --- a/mobile/android/gradle/thirdparty_adjust_sdk/build.gradle +++ b/mobile/android/gradle/thirdparty_adjust_sdk/build.gradle @@ -28,5 +28,5 @@ android { } dependencies { - compile 'com.android.support:support-v4:22.+' + compile 'com.android.support:support-v4:22.2.0' } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 03a86a176012..4f2007334a0a 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4297,7 +4297,6 @@ pref("browser.history.maxStateObjectSize", 655360); pref("xpinstall.whitelist.required", true); // Only Firefox requires add-on signatures pref("xpinstall.signatures.required", false); -pref("xpinstall.signatures.infoURL", "https://wiki.mozilla.org/Addons/Extension_Signing"); pref("extensions.alwaysUnpack", false); pref("extensions.minCompatiblePlatformVersion", "2.0"); diff --git a/testing/mozharness/mozharness.json b/testing/mozharness/mozharness.json index 53ce03658aee..6f00dd88b192 100644 --- a/testing/mozharness/mozharness.json +++ b/testing/mozharness/mozharness.json @@ -1,4 +1,4 @@ { "repo": "https://hg.mozilla.org/build/mozharness", - "revision": "5c70071f150e" + "revision": "1a041ea00cf3" } diff --git a/toolkit/components/moz.build b/toolkit/components/moz.build index a9325294e699..2d6d28d316a2 100644 --- a/toolkit/components/moz.build +++ b/toolkit/components/moz.build @@ -51,12 +51,17 @@ DIRS += [ 'typeaheadfind', 'urlformatter', 'viewconfig', - 'viewsource', 'workerloader', 'workerlz4', 'xulstore' ] +if CONFIG['MOZ_BUILD_APP'] != 'mobile/android': + DIRS += ['viewsource']; + + if CONFIG['NS_PRINTING']: + DIRS += ['printing'] + if CONFIG['MOZ_CRASHREPORTER']: DIRS += ['crashes'] @@ -72,9 +77,6 @@ if CONFIG['MOZ_FEEDS']: if CONFIG['MOZ_HELP_VIEWER']: DIRS += ['help'] -if CONFIG['NS_PRINTING']: - DIRS += ['printing'] - if CONFIG['MOZ_XUL']: DIRS += ['autocomplete', 'satchel'] diff --git a/toolkit/components/telemetry/TelemetrySend.jsm b/toolkit/components/telemetry/TelemetrySend.jsm index dac97691ef17..17d324b3d261 100644 --- a/toolkit/components/telemetry/TelemetrySend.jsm +++ b/toolkit/components/telemetry/TelemetrySend.jsm @@ -53,8 +53,6 @@ const IS_UNIFIED_TELEMETRY = Preferences.get(PREF_UNIFIED, false); const PING_FORMAT_VERSION = 4; -// For midnight fuzzing we want to affect pings around midnight with this tolerance. -const MIDNIGHT_TOLERANCE_FUZZ_MS = 5 * 60 * 1000; // We try to spread "midnight" pings out over this interval. const MIDNIGHT_FUZZING_INTERVAL_MS = 60 * 60 * 1000; // We delay sending "midnight" pings on this client by this interval. @@ -432,39 +430,28 @@ let TelemetrySendImpl = { /** * This helper calculates the next time that we can send pings at. - * Currently this mostly redistributes ping sends around midnight to avoid submission - * spikes around local midnight for daily pings. + * Currently this mostly redistributes ping sends from midnight until one hour after + * to avoid submission spikes around local midnight for daily pings. * * @param now Date The current time. * @return Number The next time (ms from UNIX epoch) when we can send pings. */ _getNextPingSendTime: function(now) { - // 1. First we check if the time is between 11pm and 1am. If it's not, we send + // 1. First we check if the time is between 0am and 1am. If it's not, we send // immediately. - // 2. If we confirmed the time is indeed between 11pm and 1am in step 1, we - // then check if the time is also 11:55pm or later. If it's not, we send - // immediately. - // 3. Finally, if the time is between 11:55pm and 1am, we disallow sending - // before (midnight + fuzzing delay), which is a random time between 12am-1am + // 2. If we confirmed the time is indeed between 0am and 1am in step 1, we disallow + // sending before (midnight + fuzzing delay), which is a random time between 0am-1am // (decided at startup). - const midnightDate = Utils.getNearestMidnight(now, MIDNIGHT_FUZZING_INTERVAL_MS); - - // Don't delay ping if we are not close to midnight. - if (!midnightDate) { + const midnight = Utils.truncateToDays(now); + // Don't delay pings if we are not within the fuzzing interval. + if ((now.getTime() - midnight.getTime()) > MIDNIGHT_FUZZING_INTERVAL_MS) { return now.getTime(); } // Delay ping send if we are within the midnight fuzzing range. - // This is from: |midnight - MIDNIGHT_TOLERANCE_FUZZ_MS| - // to: |midnight + MIDNIGHT_FUZZING_INTERVAL_MS| - const midnightRangeStart = midnightDate.getTime() - MIDNIGHT_TOLERANCE_FUZZ_MS; - if (now.getTime() >= midnightRangeStart) { - // We spread those ping sends out between |midnight| and |midnight + midnightPingFuzzingDelay|. - return midnightDate.getTime() + Policy.midnightPingFuzzingDelay(); - } - - return now.getTime(); + // We spread those ping sends out between |midnight| and |midnight + midnightPingFuzzingDelay|. + return midnight.getTime() + Policy.midnightPingFuzzingDelay(); }, /** diff --git a/toolkit/components/telemetry/TelemetrySession.jsm b/toolkit/components/telemetry/TelemetrySession.jsm index 6e5db9d4f214..d4a16cd2aaa5 100644 --- a/toolkit/components/telemetry/TelemetrySession.jsm +++ b/toolkit/components/telemetry/TelemetrySession.jsm @@ -439,11 +439,8 @@ let TelemetryScheduler = { _sentDailyPingToday: function(nowDate) { // This is today's date and also the previous midnight (0:00). const todayDate = Utils.truncateToDays(nowDate); - const nearestMidnight = Utils.getNearestMidnight(nowDate, SCHEDULER_MIDNIGHT_TOLERANCE_MS); - // If we are close to midnight, we check against that, otherwise against the last midnight. - const checkDate = nearestMidnight || todayDate; - // We consider a ping sent for today if it occured after midnight, or prior within the tolerance. - return (this._lastDailyPingTime >= (checkDate.getTime() - SCHEDULER_MIDNIGHT_TOLERANCE_MS)); + // We consider a ping sent for today if it occured after or at 00:00 today. + return (this._lastDailyPingTime >= todayDate.getTime()); }, /** @@ -452,21 +449,12 @@ let TelemetryScheduler = { * @return {Boolean} True if we can send the daily ping, false otherwise. */ _isDailyPingDue: function(nowDate) { - const sentPingToday = this._sentDailyPingToday(nowDate); - // The daily ping is not due if we already sent one today. - if (sentPingToday) { + if (this._sentDailyPingToday(nowDate)) { this._log.trace("_isDailyPingDue - already sent one today"); return false; } - const nearestMidnight = Utils.getNearestMidnight(nowDate, SCHEDULER_MIDNIGHT_TOLERANCE_MS); - if (!sentPingToday && !nearestMidnight) { - // Computer must have gone to sleep, the daily ping is overdue. - this._log.trace("_isDailyPingDue - daily ping is overdue... computer went to sleep?"); - return true; - } - // Avoid overly short sessions. const timeSinceLastDaily = nowDate.getTime() - this._lastDailyPingTime; if (timeSinceLastDaily < MIN_SUBSESSION_LENGTH_MS) { @@ -474,13 +462,6 @@ let TelemetryScheduler = { return false; } - // To fight jank, we allow daily pings to be collected on user idle before midnight - // within the tolerance interval. - if (!this._isUserIdle && (nowDate.getTime() < nearestMidnight.getTime())) { - this._log.trace("_isDailyPingDue - waiting for user idle period"); - return false; - } - this._log.trace("_isDailyPingDue - is due"); return true; }, diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetryController.js b/toolkit/components/telemetry/tests/unit/test_TelemetryController.js index d1a913e7dfc8..4d6b46ae3ee8 100644 --- a/toolkit/components/telemetry/tests/unit/test_TelemetryController.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetryController.js @@ -283,19 +283,18 @@ add_task(function* test_midnightPingSendFuzzing() { gRequestIterator = Iterator(new Request()); yield TelemetryController.reset(); - // A ping submitted shortly before midnight should not get sent yet. - now = new Date(2030, 5, 1, 23, 55, 0); + // A ping after midnight within the fuzzing delay should not get sent. + now = new Date(2030, 5, 2, 0, 40, 0); fakeNow(now); registerPingHandler((req, res) => { Assert.ok(false, "No ping should be received yet."); }); yield sendPing(true, true); - Assert.ok(!!pingSendTimerCallback); Assert.deepEqual(futureDate(now, pingSendTimeout), new Date(2030, 5, 2, 1, 0, 0)); - // A ping after midnight within the fuzzing delay should also not get sent. - now = new Date(2030, 5, 2, 0, 40, 0); + // A ping just before the end of the fuzzing delay should not get sent. + now = new Date(2030, 5, 2, 0, 59, 59); fakeNow(now); pingSendTimeout = null; yield sendPing(true, true); @@ -324,6 +323,13 @@ add_task(function* test_midnightPingSendFuzzing() { let ping = decodeRequestPayload(request); checkPingFormat(ping, TEST_PING_TYPE, true, true); + // Check that pings shortly before midnight are immediately sent. + now = fakeNow(2030, 5, 3, 23, 59, 0); + yield sendPing(true, true); + request = yield gRequestIterator.next(); + ping = decodeRequestPayload(request); + checkPingFormat(ping, TEST_PING_TYPE, true, true); + // Clean-up. fakeMidnightPingFuzzingDelay(0); fakePingSendTimer(() => {}, () => {}); diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js index b0b588dd1da9..a666a8fae969 100644 --- a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js @@ -1706,61 +1706,6 @@ add_task(function* test_schedulerUserIdle() { yield TelemetrySession.shutdown(); }); -add_task(function* test_sendDailyOnIdle() { - if (gIsAndroid || gIsGonk) { - // We don't have the aborted session or the daily ping here. - return; - } - - let now = new Date(2040, 1, 1, 11, 0, 0); - fakeNow(now); - - let schedulerTickCallback = 0; - fakeSchedulerTimer((callback, timeout) => { - schedulerTickCallback = callback; - }, () => {}); - - yield TelemetrySession.reset(); - yield clearPendingPings(); - - // Make sure we are not sending a daily before midnight when active. - now = new Date(2040, 1, 1, 23, 55, 0); - fakeNow(now); - registerPingHandler((req, res) => { - Assert.ok(false, "No daily ping should be received yet when the user is active."); - }); - yield fakeIdleNotification("active"); - - // The Request constructor restores the previous ping handler. - gRequestIterator = Iterator(new Request()); - - // We should receive a daily ping after midnight. - now = new Date(2040, 1, 2, 0, 05, 0); - fakeNow(now); - yield schedulerTickCallback(); - - let request = yield gRequestIterator.next(); - Assert.ok(!!request); - let ping = decodeRequestPayload(request); - - Assert.equal(ping.type, PING_TYPE_MAIN); - Assert.equal(ping.payload.info.reason, REASON_DAILY); - - // We should also trigger a ping when going idle shortly before next midnight. - now = new Date(2040, 1, 2, 23, 54, 0); - fakeNow(now); - yield fakeIdleNotification("idle"); - - request = yield gRequestIterator.next(); - Assert.ok(!!request); - ping = decodeRequestPayload(request); - - Assert.equal(ping.type, PING_TYPE_MAIN); - Assert.equal(ping.payload.info.reason, REASON_DAILY); - - yield TelemetrySession.shutdown(); -}); - add_task(function* stopServer(){ gHttpServer.stop(do_test_finished); }); diff --git a/toolkit/devtools/gcli/commands/tools.js b/toolkit/devtools/gcli/commands/tools.js index 89f1f9f556f0..961a9c96b85d 100644 --- a/toolkit/devtools/gcli/commands/tools.js +++ b/toolkit/devtools/gcli/commands/tools.js @@ -57,8 +57,7 @@ exports.items = [ Ci.nsISupportsString, str); devtools.reload(); - let msg = l10n.lookupFormat("toolsSrcdirReloaded", [ args.srcdir ]); - throw new Error(msg); + return l10n.lookupFormat("toolsSrcdirReloaded", [ args.srcdir ]); } return l10n.lookupFormat("toolsSrcdirNotFound", [ args.srcdir ]); diff --git a/toolkit/locales/en-US/chrome/global/devtools/gclicommands.properties b/toolkit/locales/en-US/chrome/global/devtools/gclicommands.properties index 09b37fb151a1..2d103bde585d 100644 --- a/toolkit/locales/en-US/chrome/global/devtools/gclicommands.properties +++ b/toolkit/locales/en-US/chrome/global/devtools/gclicommands.properties @@ -963,11 +963,11 @@ toolsSrcdirDesc=Load tools from a mozilla-central checkout # LOCALIZATION NOTE (toolsSrcdirNotFound) Shown when the 'tools srcdir' command was handed # an invalid srcdir. -toolsSrcdirNotFound=%1$s does not exist or is not a mozilla-central checkout. +toolsSrcdirNotFound=%1$S does not exist or is not a mozilla-central checkout. # LOCALIZATION NOTE (toolsSrcdirReloaded) Displayed when tools have been reloaded by the # 'tools srcdir' command. -toolsSrcdirReloaded=Tools loaded from %1$s. +toolsSrcdirReloaded=Tools loaded from %1$S. # LOCALIZATION NOTE (toolsSrcdirManual2) A full description of the 'tools srcdir' # command. The argument (%1$S) is the browser name. diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 933f54fb8502..949e5c41ac1d 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -3147,7 +3147,7 @@ var gDetailView = { ); var infoLink = document.getElementById("detail-" + msgType + "-link"); infoLink.value = gStrings.ext.GetStringFromName("details.notification.unsigned.link"); - infoLink.href = Services.prefs.getCharPref("xpinstall.signatures.infoURL"); + infoLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; infoLink.hidden = false; } else if (!this._addon.isCompatible && (AddonManager.checkCompatibility || (this._addon.blocklistState != Ci.nsIBlocklistService.STATE_SOFTBLOCKED))) { diff --git a/toolkit/mozapps/extensions/content/extensions.xml b/toolkit/mozapps/extensions/content/extensions.xml index 8b15554e2408..2fdee155ec2f 100644 --- a/toolkit/mozapps/extensions/content/extensions.xml +++ b/toolkit/mozapps/extensions/content/extensions.xml @@ -1257,7 +1257,7 @@ ); let infoLink = this.mAddon.appDisabled ? this._errorLink : this._warningLink; infoLink.value = gStrings.ext.GetStringFromName("notification.unsigned.link"); - infoLink.href = Services.prefs.getCharPref("xpinstall.signatures.infoURL"); + infoLink.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; infoLink.hidden = false; } else if ((!isUpgrade && !this.mAddon.isCompatible) && (AddonManager.checkCompatibility || (this.mAddon.blocklistState != Ci.nsIBlocklistService.STATE_SOFTBLOCKED))) { diff --git a/toolkit/mozapps/extensions/test/browser/browser_details.js b/toolkit/mozapps/extensions/test/browser/browser_details.js index 489d26011c55..4ae40cfa9c87 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_details.js +++ b/toolkit/mozapps/extensions/test/browser/browser_details.js @@ -18,6 +18,7 @@ var gVersion = Services.appinfo.version; var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL"); var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url"); var gDate = new Date(2010, 7, 1); +let infoURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; function open_details(aId, aType, aCallback) { requestLongerTimeout(2); @@ -712,7 +713,7 @@ add_test(function() { is(get("detail-warning").textContent, "Test add-on 9 could not be verified for use in " + gApp + ". Proceed with caution.", "Warning message should be correct"); is_element_visible(get("detail-warning-link"), "Warning link should be visible"); is(get("detail-warning-link").value, "More Information", "Warning link text should be correct"); - is(get("detail-warning-link").href, Services.prefs.getCharPref("xpinstall.signatures.infoURL"), "Warning link should be correct"); + is(get("detail-warning-link").href, infoURL, "Warning link should be correct"); is_element_hidden(get("detail-pending"), "Pending message should be hidden"); run_next_test(); @@ -735,7 +736,7 @@ add_test(function() { is(get("detail-error").textContent, "Test add-on 10 could not be verified for use in " + gApp + " and has been disabled.", "Error message should be correct"); is_element_visible(get("detail-error-link"), "Error link should be visible"); is(get("detail-error-link").value, "More Information", "Error link text should be correct"); - is(get("detail-error-link").href, Services.prefs.getCharPref("xpinstall.signatures.infoURL"), "Error link should be correct"); + is(get("detail-error-link").href, infoURL, "Error link should be correct"); is_element_hidden(get("detail-pending"), "Pending message should be hidden"); run_next_test(); diff --git a/toolkit/mozapps/extensions/test/browser/browser_list.js b/toolkit/mozapps/extensions/test/browser/browser_list.js index e70f52b86df4..4c36cd62d68b 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_list.js +++ b/toolkit/mozapps/extensions/test/browser/browser_list.js @@ -8,7 +8,6 @@ let tempScope = {}; Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope); let LightweightThemeManager = tempScope.LightweightThemeManager; - var gProvider; var gManagerWindow; var gCategoryUtilities; @@ -18,6 +17,7 @@ var gVersion = Services.appinfo.version; var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL"); var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url"); var gDate = new Date(2010, 7, 16); +let infoURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons"; var gLWTheme = { id: "4", @@ -412,7 +412,7 @@ add_test(function() { is(get_node(addon, "warning").textContent, "Test add-on 10 could not be verified for use in " + gApp + ". Proceed with caution.", "Warning message should be correct"); is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible"); is(get_node(addon, "warning-link").value, "More Information", "Warning link text should be correct"); - is(get_node(addon, "warning-link").href, Services.prefs.getCharPref("xpinstall.signatures.infoURL"), "Warning link should be correct"); + is(get_node(addon, "warning-link").href, infoURL, "Warning link should be correct"); is_element_hidden(get_node(addon, "error"), "Error message should be hidden"); is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden"); is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); @@ -433,7 +433,7 @@ add_test(function() { is(get_node(addon, "error").textContent, "Test add-on 11 could not be verified for use in " + gApp + " and has been disabled.", "Error message should be correct"); is_element_visible(get_node(addon, "error-link"), "Error link should be visible"); is(get_node(addon, "error-link").value, "More Information", "Error link text should be correct"); - is(get_node(addon, "error-link").href, Services.prefs.getCharPref("xpinstall.signatures.infoURL"), "Error link should be correct"); + is(get_node(addon, "error-link").href, infoURL, "Error link should be correct"); is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden"); info("Filter for disabled unsigned extensions");