mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c. a=merge
This commit is contained in:
commit
a9bba531ba
@ -8,7 +8,7 @@
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/devtools-browser.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/controlcenter/panel.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUIOverlay.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
|
@ -189,7 +189,7 @@ ident:
|
||||
merge-%:
|
||||
ifdef LOCALE_MERGEDIR
|
||||
$(RM) -rf $(LOCALE_MERGEDIR)
|
||||
MACOSX_DEPLOYMENT_TARGET= compare-locales -m $(LOCALE_MERGEDIR) $(srcdir)/l10n.ini $(L10NBASEDIR) $*
|
||||
$(topsrcdir)/mach compare-locales --merge-dir $(LOCALE_MERGEDIR) $*
|
||||
endif
|
||||
@echo
|
||||
|
||||
|
@ -12,7 +12,7 @@ clientSuperShortname=Hello
|
||||
## LOCALIZATION_NOTE(loopMenuItem_label): Label of the menu item that is placed
|
||||
## inside the browser 'Tools' menu. Use the unicode ellipsis char, \u2026, or
|
||||
## use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
loopMenuItem_label=Start a conversation…
|
||||
loopMenuItem_label=Start a Conversation…
|
||||
loopMenuItem_accesskey=t
|
||||
|
||||
## LOCALIZATION_NOTE(sign_in_again_title_line_one, sign_in_again_title_line_two2):
|
||||
|
4
devtools/bootstrap.js
vendored
4
devtools/bootstrap.js
vendored
@ -80,6 +80,10 @@ function reload(event) {
|
||||
// Ask the loader to update itself and reopen the toolbox if needed
|
||||
const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
devtools.reload(reloadToolbox);
|
||||
|
||||
// Also tells gDevTools to reload its dependencies
|
||||
const {gDevTools} = Cu.import("resource://devtools/client/framework/gDevTools.jsm", {});
|
||||
gDevTools.reload();
|
||||
}
|
||||
|
||||
let listener;
|
||||
|
@ -326,6 +326,8 @@ skip-if = e10s && debug
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_parser-10.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_parser-11.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_pause-exceptions-01.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_pause-exceptions-02.js]
|
||||
|
@ -0,0 +1,39 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Checks if self-closing <script/> tags are parsed by Parser.jsm
|
||||
*/
|
||||
|
||||
function test() {
|
||||
let { Parser } = Cu.import("resource://devtools/shared/Parser.jsm", {});
|
||||
|
||||
let source = [
|
||||
'<script type="text/javascript" src="chrome://foo.js"/>',
|
||||
'<script type="application/javascript;version=1.8" src="chrome://baz.js"/>',
|
||||
'<script async defer src="chrome://foobar.js"/>',
|
||||
'<script type="application/javascript"/>"hello third"',
|
||||
'<script type="application/javascript">"hello fourth"</script>',
|
||||
].join("\n");
|
||||
let parser = new Parser();
|
||||
let parsed = parser.get(source);
|
||||
|
||||
is(parser.errors.length, 0,
|
||||
"There should be no errors logged when parsing.");
|
||||
is(parsed.scriptCount, 5,
|
||||
"There should be 5 scripts parsed in the parent HTML source.");
|
||||
|
||||
is(parsed.getScriptInfo(source.indexOf("foo.js\"/>") + 1).toSource(), "({start:-1, length:-1, index:-1})",
|
||||
"the first script is empty");
|
||||
is(parsed.getScriptInfo(source.indexOf("baz.js\"/>") + 1).toSource(), "({start:-1, length:-1, index:-1})",
|
||||
"the second script is empty");
|
||||
is(parsed.getScriptInfo(source.indexOf("foobar.js\"/>") + 1).toSource(), "({start:-1, length:-1, index:-1})",
|
||||
"the third script is empty");
|
||||
|
||||
is(parsed.getScriptInfo(source.indexOf("hello third!")).toSource(), "({start:-1, length:-1, index:-1})",
|
||||
"Inline script on self-closing tag not considered a script");
|
||||
is(parsed.getScriptInfo(source.indexOf("hello fourth")).toSource(), "({start:267, length:14, index:4})",
|
||||
"The fourth script was located correctly.");
|
||||
|
||||
finish();
|
||||
}
|
@ -9,7 +9,10 @@
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/eyedropper.css" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
no-theme="true">
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
<commandset id="eyedropper-commandset">
|
||||
<command id="eyedropper-cmd-close"
|
||||
oncommand="void(0);"/>
|
||||
|
@ -10,8 +10,17 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
const { require, loader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const promise = require("promise");
|
||||
|
||||
// Make most dependencies be reloadable so that the reload addon
|
||||
// can update all of them while keeping gDevTools.jsm as-is
|
||||
// Bug 1188405 is going to refactor this JSM into a commonjs module
|
||||
// so that it can be reloaded as other modules.
|
||||
let require, loader, promise, DefaultTools, DefaultThemes;
|
||||
let loadDependencies = () => {
|
||||
let l = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
require = l.require;
|
||||
loader = l.loader;
|
||||
promise = require("promise");
|
||||
// Load target and toolbox lazily as they need gDevTools to be fully initialized
|
||||
loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
|
||||
loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true);
|
||||
@ -23,8 +32,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
|
||||
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
|
||||
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true);
|
||||
|
||||
const {defaultTools: DefaultTools, defaultThemes: DefaultThemes} =
|
||||
require("devtools/client/definitions");
|
||||
let d = require("devtools/client/definitions");
|
||||
DefaultTools = d.defaultTools;
|
||||
DefaultThemes = d.defaultThemes;
|
||||
};
|
||||
loadDependencies();
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
const {JsonView} = require("devtools/client/jsonview/main");
|
||||
@ -511,6 +524,11 @@ DevTools.prototype = {
|
||||
// Is taken care of by the gDevToolsBrowser.forgetBrowserWindow
|
||||
},
|
||||
|
||||
// Force reloading dependencies if the loader happens to have reloaded
|
||||
reload() {
|
||||
loadDependencies();
|
||||
},
|
||||
|
||||
/**
|
||||
* Iterator that yields each of the toolboxes.
|
||||
*/
|
||||
|
@ -356,7 +356,7 @@ Toolbox.prototype = {
|
||||
iframe.setAttribute("src", this._URL);
|
||||
iframe.setAttribute("aria-label", toolboxStrings("toolbox.label"));
|
||||
let domHelper = new DOMHelpers(iframe.contentWindow);
|
||||
domHelper.onceDOMReady(() => domReady.resolve());
|
||||
domHelper.onceDOMReady(() => domReady.resolve(), this._URL);
|
||||
// Optimization: fire up a few other things before waiting on
|
||||
// the iframe being ready (makes startup faster)
|
||||
|
||||
@ -365,7 +365,6 @@ Toolbox.prototype = {
|
||||
|
||||
// Attach the thread
|
||||
this._threadClient = yield attachThread(this);
|
||||
|
||||
yield domReady.promise;
|
||||
|
||||
this.isReady = true;
|
||||
|
@ -1,51 +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/. */
|
||||
|
||||
.dim > #root,
|
||||
.font:not(.has-code) .font-css-code,
|
||||
.font-is-local,
|
||||
.font-is-remote,
|
||||
.font.is-local .font-format-url,
|
||||
#template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.font.is-remote .font-is-remote,
|
||||
.font.is-local .font-is-local {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.font-format::before {
|
||||
content: "(";
|
||||
}
|
||||
|
||||
.font-format::after {
|
||||
content: ")";
|
||||
}
|
||||
|
||||
.preview-input-toolbar {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.font-preview-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#preview-text-input {
|
||||
font: inherit;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
overflow: auto;
|
||||
}
|
@ -11,7 +11,6 @@
|
||||
<head>
|
||||
<title>&title;</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="fonts.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/fonts.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
|
@ -1,118 +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/. */
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#ruleview-container {
|
||||
-moz-user-select: text;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#ruleview-container.non-interactive {
|
||||
pointer-events: none;
|
||||
visibility: collapse;
|
||||
transition: visibility 0.25s;
|
||||
}
|
||||
|
||||
.devtools-toolbar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#pseudo-class-panel {
|
||||
position: relative;
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
overflow-y: hidden;
|
||||
max-height: 24px;
|
||||
outline: 0 !important;
|
||||
transition-property: max-height;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
#pseudo-class-panel[hidden] {
|
||||
max-height: 0px;
|
||||
}
|
||||
|
||||
#pseudo-class-panel > label {
|
||||
-moz-user-select: none;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ruleview {
|
||||
overflow: auto;
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
.ruleview-code {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.ruleview-property:not(:hover) > .ruleview-enableproperty {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.ruleview-propertyvaluecontainer {
|
||||
cursor: text;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.ruleview-propertyvaluecontainer a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ruleview-computedlist,
|
||||
.ruleview-overridden-rule-filter[hidden],
|
||||
.ruleview-warning[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ruleview-computedlist[user-open],
|
||||
.ruleview-computedlist[filter-open] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ruleview-expandable-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.show-expandable-container + .ruleview-expandable-container {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ruleview .ruleview-expander {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ruleview-header {
|
||||
vertical-align: middle;
|
||||
min-height: 1.5em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.ruleview-header.ruleview-expandable-header {
|
||||
cursor: pointer;
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
<title>&ruleViewTitle;</title>
|
||||
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/content/inspector/rules/rules.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/rules.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
<script type="application/javascript;version=1.8">
|
||||
@ -52,7 +51,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ruleview-container" class="ruleview devtools-monospace">
|
||||
<div id="ruleview-container" class="devtools-monospace">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -27,14 +27,12 @@ devtools.jar:
|
||||
content/styleeditor/styleeditor.css (styleeditor/styleeditor.css)
|
||||
content/storage/storage.xul (storage/storage.xul)
|
||||
content/inspector/computed/computed.xhtml (inspector/computed/computed.xhtml)
|
||||
content/inspector/fonts/fonts.css (inspector/fonts/fonts.css)
|
||||
content/inspector/fonts/fonts.js (inspector/fonts/fonts.js)
|
||||
content/inspector/fonts/fonts.xhtml (inspector/fonts/fonts.xhtml)
|
||||
content/inspector/layout/layout.js (inspector/layout/layout.js)
|
||||
content/inspector/layout/layout.xhtml (inspector/layout/layout.xhtml)
|
||||
content/inspector/markup/markup.css (inspector/markup/markup.css)
|
||||
content/inspector/markup/markup.xhtml (inspector/markup/markup.xhtml)
|
||||
content/inspector/rules/rules.css (inspector/rules/rules.css)
|
||||
content/inspector/rules/rules.xhtml (inspector/rules/rules.xhtml)
|
||||
content/animationinspector/animation-controller.js (animationinspector/animation-controller.js)
|
||||
content/animationinspector/animation-panel.js (animationinspector/animation-panel.js)
|
||||
@ -148,7 +146,9 @@ devtools.jar:
|
||||
content/aboutdebugging/aboutdebugging.css (aboutdebugging/aboutdebugging.css)
|
||||
content/aboutdebugging/aboutdebugging.js (aboutdebugging/aboutdebugging.js)
|
||||
% skin devtools classic/1.0 %skin/
|
||||
* skin/common.css (themes/common.css)
|
||||
skin/devtools-browser.css (themes/devtools-browser.css)
|
||||
skin/common.css (themes/common.css)
|
||||
skin/splitters.css (themes/splitters.css)
|
||||
skin/dark-theme.css (themes/dark-theme.css)
|
||||
skin/light-theme.css (themes/light-theme.css)
|
||||
skin/toolbars.css (themes/toolbars.css)
|
||||
|
@ -11,11 +11,6 @@
|
||||
<!ENTITY window.title "Web Console">
|
||||
<!ENTITY browserConsole.title "Browser Console">
|
||||
|
||||
<!-- LOCALIZATION NOTE (saveBodies.label): You can see this string in the Web
|
||||
- Console context menu. -->
|
||||
<!ENTITY saveBodies.label "Log Request and Response Bodies">
|
||||
<!ENTITY saveBodies.accesskey "L">
|
||||
|
||||
<!-- LOCALIZATION NOTE (openURL.label): You can see this string in the Web
|
||||
- Console context menu. -->
|
||||
<!ENTITY openURL.label "Open URL in New Tab">
|
||||
|
@ -73,11 +73,8 @@ var HarAutomation = Class({
|
||||
this.tabClient = this.toolbox.target.activeTab;
|
||||
this.webConsoleClient = this.toolbox.target.activeConsole;
|
||||
|
||||
let netPrefs = { "NetworkMonitor.saveRequestAndResponseBodies": true };
|
||||
this.webConsoleClient.setPreferences(netPrefs, () => {
|
||||
this.tabWatcher = new TabWatcher(this.toolbox, this);
|
||||
this.tabWatcher.connect();
|
||||
});
|
||||
},
|
||||
|
||||
pageLoadBegin: function(aResponse) {
|
||||
|
@ -10,7 +10,6 @@ var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
const NET_STRINGS_URI = "chrome://devtools/locale/netmonitor.properties";
|
||||
const PKI_STRINGS_URI = "chrome://pippki/locale/pippki.properties";
|
||||
const LISTENERS = [ "NetworkActivity" ];
|
||||
const NET_PREFS = { "NetworkMonitor.saveRequestAndResponseBodies": true };
|
||||
|
||||
// The panel's window global is an EventEmitter firing the following events:
|
||||
const EVENTS = {
|
||||
@ -223,13 +222,6 @@ var NetMonitorController = {
|
||||
this.tabClient = this._target.activeTab;
|
||||
}
|
||||
|
||||
let connectWebConsole = () => {
|
||||
let deferred = promise.defer();
|
||||
this.webConsoleClient = this._target.activeConsole;
|
||||
this.webConsoleClient.setPreferences(NET_PREFS, deferred.resolve);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
let connectTimeline = () => {
|
||||
// Don't start up waiting for timeline markers if the server isn't
|
||||
// recent enough to emit the markers we're interested in.
|
||||
@ -239,7 +231,7 @@ var NetMonitorController = {
|
||||
}
|
||||
};
|
||||
|
||||
yield connectWebConsole();
|
||||
this.webConsoleClient = this._target.activeConsole;
|
||||
yield connectTimeline();
|
||||
|
||||
this.TargetEventsHandler.connect();
|
||||
|
@ -74,6 +74,7 @@ skip-if = e10s # Bug 1091596
|
||||
[browser_net_html-preview.js]
|
||||
[browser_net_icon-preview.js]
|
||||
[browser_net_image-tooltip.js]
|
||||
skip-if = (os == "win" && os_version == "6.2" && bits == 64) # Bug 1234341
|
||||
[browser_net_json-long.js]
|
||||
[browser_net_json-malformed.js]
|
||||
[browser_net_json_custom_mime.js]
|
||||
|
@ -137,7 +137,7 @@ DOMHelpers.prototype = {
|
||||
* chrome iframes are loaded in content docshells (in Firefox
|
||||
* tabs for example).
|
||||
*/
|
||||
onceDOMReady: function Helpers_onLocationChange(callback) {
|
||||
onceDOMReady: function Helpers_onLocationChange(callback, targetURL) {
|
||||
let window = this.window;
|
||||
let docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
@ -151,6 +151,12 @@ DOMHelpers.prototype = {
|
||||
Services.tm.mainThread.dispatch(callback, 0);
|
||||
}
|
||||
}
|
||||
if ((window.document.readyState == "complete" ||
|
||||
window.document.readyState == "interactive") &&
|
||||
window.location.href == targetURL) {
|
||||
Services.tm.mainThread.dispatch(callback, 0);
|
||||
} else {
|
||||
docShell.chromeEventHandler.addEventListener("DOMContentLoaded", onReady, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -82,6 +82,9 @@ exports.getTestActorWithoutToolbox = Task.async(function* (tab) {
|
||||
client.connect(deferred.resolve);
|
||||
yield deferred.promise;
|
||||
|
||||
// We also need to make sure the test actor is registered on the server.
|
||||
yield registerTestActor(client);
|
||||
|
||||
return getTestActor(client, tab);
|
||||
});
|
||||
|
||||
|
@ -5,6 +5,25 @@
|
||||
(function() {
|
||||
const SCROLLBARS_URL = "chrome://devtools/skin/floating-scrollbars-light.css";
|
||||
let documentElement = document.documentElement;
|
||||
|
||||
let os;
|
||||
let platform = navigator.platform;
|
||||
if (platform.startsWith("Win")) {
|
||||
os = "win";
|
||||
} else if (platform.startsWith("Mac")) {
|
||||
os = "mac";
|
||||
} else {
|
||||
os = "linux";
|
||||
}
|
||||
|
||||
documentElement.setAttribute("platform", os);
|
||||
|
||||
// no-theme attributes allows to just est the platform attribute
|
||||
// to have per-platform CSS working correctly.
|
||||
if (documentElement.getAttribute("no-theme") === "true") {
|
||||
return;
|
||||
}
|
||||
|
||||
let devtoolsStyleSheets = new WeakMap();
|
||||
|
||||
function forceStyle() {
|
||||
@ -144,17 +163,6 @@
|
||||
const {require} = Components.utils.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const StylesheetUtils = require("sdk/stylesheet/utils");
|
||||
|
||||
let os;
|
||||
let platform = navigator.platform;
|
||||
if (platform.startsWith("Win")) {
|
||||
os = "win";
|
||||
} else if (platform.startsWith("Mac")) {
|
||||
os = "mac";
|
||||
} else {
|
||||
os = "linux";
|
||||
}
|
||||
documentElement.setAttribute("platform", os);
|
||||
|
||||
if (documentElement.hasAttribute("force-theme")) {
|
||||
switchTheme(documentElement.getAttribute("force-theme"));
|
||||
} else {
|
||||
|
@ -1,66 +1,33 @@
|
||||
%if 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/. */
|
||||
%endif
|
||||
|
||||
@import url("splitters.css");
|
||||
|
||||
:root {
|
||||
font: message-box;
|
||||
%ifdef XP_MACOSX
|
||||
}
|
||||
|
||||
:root[platform="mac"] {
|
||||
--monospace-font-family: Menlo, monospace;
|
||||
%elifdef XP_WIN
|
||||
}
|
||||
|
||||
:root[platform="win"] {
|
||||
--monospace-font-family: Consolas, monospace;
|
||||
%else
|
||||
}
|
||||
|
||||
:root[platform="linux"] {
|
||||
--monospace-font-family: monospace;
|
||||
%endif
|
||||
}
|
||||
|
||||
.devtools-monospace {
|
||||
font-family: var(--monospace-font-family);
|
||||
%if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
|
||||
}
|
||||
|
||||
:root[platform="linux"] .devtools-monospace {
|
||||
font-size: 80%;
|
||||
%endif
|
||||
}
|
||||
|
||||
/* Bottom-docked toolbox minimize transition */
|
||||
.devtools-toolbox-bottom-iframe {
|
||||
transition: margin-bottom .1s;
|
||||
}
|
||||
|
||||
/* Splitters */
|
||||
.devtools-horizontal-splitter {
|
||||
-moz-appearance: none;
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
border-bottom: 1px solid rgba(118, 121, 125, .5);
|
||||
min-height: 3px;
|
||||
height: 3px;
|
||||
margin-top: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.devtools-side-splitter {
|
||||
-moz-appearance: none;
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
-moz-border-end: 1px solid rgba(118, 121, 125, .5);
|
||||
min-width: 3px;
|
||||
width: 3px;
|
||||
-moz-margin-start: -3px;
|
||||
position: relative;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.devtools-horizontal-splitter.disabled,
|
||||
.devtools-side-splitter.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.devtools-toolbox-side-iframe {
|
||||
min-width: 465px;
|
||||
}
|
||||
|
||||
/* Autocomplete Popup */
|
||||
/* Dark and light theme */
|
||||
@ -71,11 +38,11 @@
|
||||
background-color: transparent;
|
||||
border-radius: 3px;
|
||||
overflow-x: hidden;
|
||||
%if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
|
||||
max-height: 32rem;
|
||||
%else
|
||||
max-height: 40rem;
|
||||
%endif
|
||||
}
|
||||
|
||||
:root[platform="linux"] .devtools-autocomplete-popup {
|
||||
max-height: 32rem;
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox {
|
||||
@ -248,17 +215,6 @@
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Eyedropper Widget */
|
||||
|
||||
.devtools-eyedropper-panel {
|
||||
pointer-events: none;
|
||||
-moz-appearance: none;
|
||||
width: 156px;
|
||||
height: 120px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* links to source code, like displaying `myfile.js:45` */
|
||||
|
||||
.devtools-source-link {
|
||||
|
27
devtools/client/themes/devtools-browser.css
Normal file
27
devtools/client/themes/devtools-browser.css
Normal file
@ -0,0 +1,27 @@
|
||||
/* 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/. */
|
||||
|
||||
@import url("splitters.css");
|
||||
|
||||
/* Bottom-docked toolbox minimize transition */
|
||||
.devtools-toolbox-bottom-iframe {
|
||||
transition: margin-bottom .1s;
|
||||
}
|
||||
|
||||
.devtools-toolbox-side-iframe {
|
||||
min-width: 465px;
|
||||
}
|
||||
|
||||
/* Eyedropper Widget */
|
||||
/* <panel> added to mainPopupSet */
|
||||
|
||||
.devtools-eyedropper-panel {
|
||||
pointer-events: none;
|
||||
-moz-appearance: none;
|
||||
width: 156px;
|
||||
height: 120px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
@ -1,7 +1,15 @@
|
||||
/* 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/. */
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -10,6 +18,10 @@ body {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
#root {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#all-fonts {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@ -25,6 +37,46 @@ body {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.dim > #root,
|
||||
.font:not(.has-code) .font-css-code,
|
||||
.font-is-local,
|
||||
.font-is-remote,
|
||||
.font.is-local .font-format-url,
|
||||
#template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.font.is-remote .font-is-remote,
|
||||
.font.is-local .font-is-local {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.font-format::before {
|
||||
content: "(";
|
||||
}
|
||||
|
||||
.font-format::after {
|
||||
content: ")";
|
||||
}
|
||||
|
||||
.preview-input-toolbar {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.font-preview-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#preview-text-input {
|
||||
font: inherit;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.font {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
@ -72,6 +72,14 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.event-header:first-child {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.event-header:not(:first-child) {
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
|
||||
.event-tooltip-event-type,
|
||||
.event-tooltip-filename,
|
||||
.event-tooltip-attributes {
|
||||
@ -105,8 +113,15 @@
|
||||
|
||||
.event-tooltip-content-box {
|
||||
display: none;
|
||||
overflow: auto;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
-moz-margin-end: 0;
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
|
||||
.event-toolbox-content-box iframe {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.event-tooltip-content-box[open] {
|
||||
|
@ -13,10 +13,103 @@
|
||||
--rule-filter-icon: url(images/magnifying-glass.png);
|
||||
}
|
||||
|
||||
.ruleview {
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#ruleview-container {
|
||||
-moz-user-select: text;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#ruleview-container.non-interactive {
|
||||
pointer-events: none;
|
||||
visibility: collapse;
|
||||
transition: visibility 0.25s;
|
||||
}
|
||||
|
||||
.devtools-toolbar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#pseudo-class-panel {
|
||||
position: relative;
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
overflow-y: hidden;
|
||||
max-height: 24px;
|
||||
outline: 0 !important;
|
||||
transition-property: max-height;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
#pseudo-class-panel[hidden] {
|
||||
max-height: 0px;
|
||||
}
|
||||
|
||||
#pseudo-class-panel > label {
|
||||
-moz-user-select: none;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ruleview-code {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.ruleview-property:not(:hover) > .ruleview-enableproperty {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ruleview-expandable-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.show-expandable-container + .ruleview-expandable-container {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ruleview-namecontainer {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.ruleview-propertyvaluecontainer {
|
||||
cursor: text;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.ruleview-propertyvaluecontainer a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ruleview-computedlist,
|
||||
.ruleview-overridden-rule-filter[hidden],
|
||||
.ruleview-warning[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ruleview-computedlist[user-open],
|
||||
.ruleview-computedlist[filter-open] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ruleview-rule-source {
|
||||
text-align: end;
|
||||
float: right;
|
||||
@ -46,6 +139,9 @@
|
||||
padding: 1px 4px;
|
||||
-moz-user-select: none;
|
||||
word-wrap: break-word;
|
||||
vertical-align: middle;
|
||||
min-height: 1.5em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
:root[platform="win"] .ruleview-header,
|
||||
@ -53,6 +149,10 @@
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.ruleview-header.ruleview-expandable-header {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ruleview-rule-pseudo-element {
|
||||
padding-left:20px;
|
||||
border-left: solid 10px;
|
||||
@ -148,6 +248,7 @@
|
||||
}
|
||||
|
||||
.ruleview-expander {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
34
devtools/client/themes/splitters.css
Normal file
34
devtools/client/themes/splitters.css
Normal file
@ -0,0 +1,34 @@
|
||||
/* 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/. */
|
||||
|
||||
/* Splitters */
|
||||
.devtools-horizontal-splitter {
|
||||
-moz-appearance: none;
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
border-bottom: 1px solid rgba(118, 121, 125, .5);
|
||||
min-height: 3px;
|
||||
height: 3px;
|
||||
margin-top: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.devtools-side-splitter {
|
||||
-moz-appearance: none;
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
-moz-border-end: 1px solid rgba(118, 121, 125, .5);
|
||||
min-width: 3px;
|
||||
width: 3px;
|
||||
-moz-margin-start: -3px;
|
||||
position: relative;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.devtools-horizontal-splitter.disabled,
|
||||
.devtools-side-splitter.disabled {
|
||||
pointer-events: none;
|
||||
}
|
@ -171,6 +171,7 @@ skip-if = buildapp == 'mulet' || e10s # Bug 1042253 - webconsole e10s tests
|
||||
[browser_console_log_inspectable_object.js]
|
||||
[browser_console_native_getters.js]
|
||||
[browser_console_navigation_marker.js]
|
||||
[browser_console_netlogging.js]
|
||||
[browser_console_nsiconsolemessage.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_console_optimized_out_vars.js]
|
||||
@ -300,7 +301,6 @@ skip-if = os != "mac"
|
||||
[browser_webconsole_bug_817834_add_edited_input_to_history.js]
|
||||
[browser_webconsole_bug_837351_securityerrors.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_webconsole_bug_915141_toggle_response_logging_with_keyboard.js]
|
||||
[browser_webconsole_filter_buttons_contextmenu.js]
|
||||
[browser_webconsole_bug_1006027_message_timestamps_incorrect.js]
|
||||
skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug intermittent)
|
||||
|
@ -0,0 +1,50 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* 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/. */
|
||||
|
||||
// Tests that network log messages bring up the network panel.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,Web Console network " +
|
||||
"logging tests";
|
||||
|
||||
const TEST_NETWORK_REQUEST_URI =
|
||||
"http://example.com/browser/devtools/client/webconsole/test/" +
|
||||
"test-network-request.html";
|
||||
|
||||
var hud;
|
||||
|
||||
function test() {
|
||||
loadTab(TEST_URI).then((tab) => {
|
||||
HUDService.openBrowserConsoleOrFocus().then(aHud => {
|
||||
hud = aHud;
|
||||
HUDService.lastFinishedRequest.callback = testResponse;
|
||||
BrowserTestUtils.loadURI(gBrowser.selectedBrowser,
|
||||
TEST_NETWORK_REQUEST_URI);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testResponse(request) {
|
||||
hud.ui.webConsoleClient.getResponseContent(request.actor,
|
||||
function(contentPacket) {
|
||||
hud.ui.webConsoleClient.getRequestPostData(request.actor,
|
||||
function(postDataPacket) {
|
||||
// Check if page load was logged correctly.
|
||||
ok(request, "Page load was logged");
|
||||
|
||||
is(request.request.url, TEST_NETWORK_REQUEST_URI,
|
||||
"Logged network entry is page load");
|
||||
is(request.request.method, "GET", "Method is correct");
|
||||
ok(!postDataPacket.postData.text, "No request body was stored");
|
||||
ok(postDataPacket.postDataDiscarded, "Request body was discarded");
|
||||
ok(!contentPacket.content.text, "No response body was stored");
|
||||
ok(contentPacket.contentDiscarded || request.fromCache,
|
||||
"Response body was discarded or response came from the cache");
|
||||
|
||||
executeSoon(finishTest);
|
||||
});
|
||||
});
|
||||
}
|
@ -54,11 +54,6 @@ add_task(function* () {
|
||||
|
||||
let hud = yield openConsole();
|
||||
|
||||
yield hud.ui.setSaveRequestAndResponseBodies(true);
|
||||
|
||||
ok(hud.ui._saveRequestAndResponseBodies,
|
||||
"The saveRequestAndResponseBodies property was successfully set.");
|
||||
|
||||
let gotLastRequest = waitForRequest();
|
||||
|
||||
let loaded = loadBrowser(browser);
|
||||
|
@ -33,10 +33,6 @@ function consoleOpened(hud) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
webConsoleClient = hud.ui.webConsoleClient;
|
||||
hud.ui.setSaveRequestAndResponseBodies(true).then(() => {
|
||||
ok(hud.ui._saveRequestAndResponseBodies,
|
||||
"The saveRequestAndResponseBodies property was successfully set.");
|
||||
|
||||
HUDService.lastFinishedRequest.callback = (aHttpRequest) => {
|
||||
let status = aHttpRequest.response.status;
|
||||
lastFinishedRequests[status] = aHttpRequest;
|
||||
@ -46,7 +42,6 @@ function consoleOpened(hud) {
|
||||
}
|
||||
};
|
||||
content.location = TEST_URI2;
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -1,124 +0,0 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that the 'Log Request and Response Bodies' buttons can be toggled
|
||||
// with keyboard.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
|
||||
"bug 915141: Toggle log response bodies with keyboard";
|
||||
var hud;
|
||||
|
||||
function test() {
|
||||
let saveBodiesMenuItem;
|
||||
let saveBodiesContextMenuItem;
|
||||
|
||||
loadTab(TEST_URI).then(({tab: tab}) => {
|
||||
return openConsole(tab);
|
||||
})
|
||||
.then((aHud) => {
|
||||
hud = aHud;
|
||||
saveBodiesMenuItem = hud.ui.rootElement.querySelector("#saveBodies");
|
||||
saveBodiesContextMenuItem = hud.ui.rootElement.querySelector("#saveBodiesContextMenu");
|
||||
|
||||
// Test the context menu action.
|
||||
info("Testing 'Log Request and Response Bodies' menuitem of right click " +
|
||||
"context menu.");
|
||||
|
||||
return openPopup(saveBodiesContextMenuItem);
|
||||
})
|
||||
.then(() => {
|
||||
is(saveBodiesContextMenuItem.getAttribute("checked"), "false",
|
||||
"Context menu: 'log responses' is not checked before action.");
|
||||
is(hud.ui._saveRequestAndResponseBodies, false,
|
||||
"Context menu: Responses are not logged before action.");
|
||||
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
|
||||
return waitForUpdate(saveBodiesContextMenuItem);
|
||||
})
|
||||
.then(() => {
|
||||
is(saveBodiesContextMenuItem.getAttribute("checked"), "true",
|
||||
"Context menu: 'log responses' is checked after menuitem was selected " +
|
||||
"with keyboard.");
|
||||
is(hud.ui._saveRequestAndResponseBodies, true,
|
||||
"Context menu: Responses are saved after menuitem was selected with " +
|
||||
"keyboard.");
|
||||
|
||||
return openPopup(saveBodiesMenuItem);
|
||||
})
|
||||
.then(() => {
|
||||
// Test the 'Net' menu item.
|
||||
info("Testing 'Log Request and Response Bodies' menuitem of 'Net' menu " +
|
||||
"in the console.");
|
||||
// 'Log Request and Response Bodies' should be selected due to previous
|
||||
// test.
|
||||
|
||||
is(saveBodiesMenuItem.getAttribute("checked"), "true",
|
||||
"Console net menu: 'log responses' is checked before action.");
|
||||
is(hud.ui._saveRequestAndResponseBodies, true,
|
||||
"Console net menu: Responses are logged before action.");
|
||||
|
||||
// The correct item is the last one in the menu.
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
|
||||
return waitForUpdate(saveBodiesMenuItem);
|
||||
})
|
||||
.then(() => {
|
||||
is(saveBodiesMenuItem.getAttribute("checked"), "false",
|
||||
"Console net menu: 'log responses' is NOT checked after menuitem was " +
|
||||
"selected with keyboard.");
|
||||
is(hud.ui._saveRequestAndResponseBodies, false,
|
||||
"Responses are NOT saved after menuitem was selected with keyboard.");
|
||||
hud = null;
|
||||
})
|
||||
.then(finishTest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens and waits for the menu containing menuItem to open.
|
||||
* @param menuItem MenuItem
|
||||
* A MenuItem in a menu that should be opened.
|
||||
* @return A promise that's resolved once menu is open.
|
||||
*/
|
||||
function openPopup(menuItem) {
|
||||
let menu = menuItem.parentNode;
|
||||
|
||||
let menuOpened = promise.defer();
|
||||
let uiUpdated = promise.defer();
|
||||
// The checkbox menuitem is updated asynchronously on 'popupshowing' event so
|
||||
// it's better to wait for both the update to happen and the menu to open
|
||||
// before continuing or the test might fail due to a race between menu being
|
||||
// shown and the item updated to have the correct state.
|
||||
hud.ui.once("save-bodies-ui-toggled", uiUpdated.resolve);
|
||||
menu.addEventListener("popupshown", function onPopup() {
|
||||
menu.removeEventListener("popupshown", onPopup);
|
||||
menuOpened.resolve();
|
||||
});
|
||||
|
||||
menu.openPopup();
|
||||
return Promise.all([menuOpened.promise, uiUpdated.promise]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the settings and menu containing menuItem to update.
|
||||
* @param menuItem MenuItem
|
||||
* The menuitem that should be updated.
|
||||
* @return A promise that's resolved once the settings and menus are updated.
|
||||
*/
|
||||
function waitForUpdate(menuItem) {
|
||||
info("Waiting for settings update to complete.");
|
||||
let deferred = promise.defer();
|
||||
hud.ui.once("save-bodies-pref-reversed", function() {
|
||||
hud.ui.once("save-bodies-ui-toggled", deferred.resolve);
|
||||
// The checked state is only updated once the popup is shown.
|
||||
menuItem.parentNode.openPopup();
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
@ -74,58 +74,16 @@ function testPageLoad() {
|
||||
"Logged network entry is page load");
|
||||
is(lastRequest.request.method, "GET", "Method is correct");
|
||||
ok(!lastRequest.request.postData.text, "No request body was stored");
|
||||
ok(lastRequest.discardRequestBody, "Request body was discarded");
|
||||
ok(!lastRequest.response.content.text, "No response body was stored");
|
||||
ok(lastRequest.discardResponseBody || lastRequest.fromCache,
|
||||
"Response body was discarded or response came from the cache");
|
||||
|
||||
lastRequest = null;
|
||||
requestCallback = null;
|
||||
executeSoon(testPageLoadBody);
|
||||
};
|
||||
|
||||
content.location = TEST_NETWORK_REQUEST_URI;
|
||||
}
|
||||
|
||||
function testPageLoadBody() {
|
||||
// Turn on logging of request bodies and check again.
|
||||
hud.ui.setSaveRequestAndResponseBodies(true).then(() => {
|
||||
ok(hud.ui._saveRequestAndResponseBodies,
|
||||
"The saveRequestAndResponseBodies property was successfully set.");
|
||||
|
||||
testPageLoadBodyAfterSettingUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
function testPageLoadBodyAfterSettingUpdate() {
|
||||
let loaded = false;
|
||||
let requestCallbackInvoked = false;
|
||||
|
||||
requestCallback = function() {
|
||||
ok(lastRequest, "Page load was logged again");
|
||||
ok(!lastRequest.discardResponseBody, "Response body was not discarded");
|
||||
ok(!lastRequest.discardRequestBody, "Request body was not discarded");
|
||||
is(lastRequest.response.content.text.indexOf("<!DOCTYPE HTML>"), 0,
|
||||
"Response body's beginning is okay");
|
||||
|
||||
lastRequest = null;
|
||||
requestCallback = null;
|
||||
requestCallbackInvoked = true;
|
||||
|
||||
if (loaded) {
|
||||
executeSoon(testXhrGet);
|
||||
}
|
||||
};
|
||||
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
loaded = true;
|
||||
|
||||
if (requestCallbackInvoked) {
|
||||
executeSoon(testXhrGet);
|
||||
}
|
||||
}, true);
|
||||
|
||||
content.location.reload();
|
||||
content.location = TEST_NETWORK_REQUEST_URI;
|
||||
}
|
||||
|
||||
function testXhrGet() {
|
||||
|
@ -367,42 +367,13 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
_destroyer: null,
|
||||
|
||||
// Used in tests.
|
||||
_saveRequestAndResponseBodies: false,
|
||||
_saveRequestAndResponseBodies: true,
|
||||
|
||||
// Chevron width at the starting of Web Console's input box.
|
||||
_chevronWidth: 0,
|
||||
// Width of the monospace characters in Web Console's input box.
|
||||
_inputCharWidth: 0,
|
||||
|
||||
/**
|
||||
* Tells whether to save the bodies of network requests and responses.
|
||||
* Disabled by default to save memory.
|
||||
*
|
||||
* @return boolean
|
||||
* The saveRequestAndResponseBodies pref value.
|
||||
*/
|
||||
getSaveRequestAndResponseBodies:
|
||||
function WCF_getSaveRequestAndResponseBodies() {
|
||||
let deferred = promise.defer();
|
||||
let toGet = [
|
||||
"NetworkMonitor.saveRequestAndResponseBodies"
|
||||
];
|
||||
|
||||
// Make sure the web console client connection is established first.
|
||||
this.webConsoleClient.getPreferences(toGet, response => {
|
||||
if (!response.error) {
|
||||
this._saveRequestAndResponseBodies = response.preferences[toGet[0]];
|
||||
deferred.resolve(this._saveRequestAndResponseBodies);
|
||||
}
|
||||
else {
|
||||
deferred.reject(response.error);
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Setter for saving of network request and response bodies.
|
||||
*
|
||||
@ -560,47 +531,6 @@ WebConsoleFrame.prototype = {
|
||||
// calculations.
|
||||
this._updateCharSize();
|
||||
|
||||
let updateSaveBodiesPrefUI = (element) => {
|
||||
this.getSaveRequestAndResponseBodies().then(value => {
|
||||
element.setAttribute("checked", value);
|
||||
this.emit("save-bodies-ui-toggled");
|
||||
});
|
||||
}
|
||||
|
||||
let reverseSaveBodiesPref = ({ target: element }) => {
|
||||
this.getSaveRequestAndResponseBodies().then(value => {
|
||||
this.setSaveRequestAndResponseBodies(!value);
|
||||
element.setAttribute("checked", value);
|
||||
this.emit("save-bodies-pref-reversed");
|
||||
});
|
||||
}
|
||||
|
||||
let saveBodiesDisabled = !this.getFilterState("networkinfo") &&
|
||||
!this.getFilterState("netxhr") &&
|
||||
!this.getFilterState("network");
|
||||
|
||||
let saveBodies = doc.getElementById("saveBodies");
|
||||
saveBodies.addEventListener("command", reverseSaveBodiesPref);
|
||||
saveBodies.disabled = saveBodiesDisabled;
|
||||
|
||||
let saveBodiesContextMenu = doc.getElementById("saveBodiesContextMenu");
|
||||
saveBodiesContextMenu.addEventListener("command", reverseSaveBodiesPref);
|
||||
saveBodiesContextMenu.disabled = saveBodiesDisabled;
|
||||
|
||||
saveBodies.parentNode.addEventListener("popupshowing", () => {
|
||||
updateSaveBodiesPrefUI(saveBodies);
|
||||
saveBodies.disabled = !this.getFilterState("networkinfo") &&
|
||||
!this.getFilterState("netxhr") &&
|
||||
!this.getFilterState("network");
|
||||
});
|
||||
|
||||
saveBodiesContextMenu.parentNode.addEventListener("popupshowing", () => {
|
||||
updateSaveBodiesPrefUI(saveBodiesContextMenu);
|
||||
saveBodiesContextMenu.disabled = !this.getFilterState("networkinfo") &&
|
||||
!this.getFilterState("netxhr") &&
|
||||
!this.getFilterState("network");
|
||||
});
|
||||
|
||||
let clearButton = doc.getElementsByClassName("webconsole-clear-console-button")[0];
|
||||
clearButton.addEventListener("command", () => {
|
||||
this.owner._onClearButton();
|
||||
@ -951,15 +881,6 @@ WebConsoleFrame.prototype = {
|
||||
let prefKey = target.getAttribute("prefKey");
|
||||
this.setFilterState(prefKey, state);
|
||||
|
||||
// Disable the log response and request body if network logging is off.
|
||||
if (prefKey == "networkinfo" || prefKey == "netxhr" || prefKey == "network") {
|
||||
let checkState = !this.getFilterState("networkinfo") &&
|
||||
!this.getFilterState("netxhr") &&
|
||||
!this.getFilterState("network");
|
||||
this.document.getElementById("saveBodies").disabled = checkState;
|
||||
this.document.getElementById("saveBodiesContextMenu").disabled = checkState;
|
||||
}
|
||||
|
||||
// Adjust the state of the button appropriately.
|
||||
let menuPopup = target.parentNode;
|
||||
|
||||
@ -5089,8 +5010,13 @@ WebConsoleConnectionProxy.prototype = {
|
||||
}
|
||||
|
||||
this.webConsoleClient = webConsoleClient;
|
||||
|
||||
this._hasNativeConsoleAPI = response.nativeConsoleAPI;
|
||||
|
||||
// There is no way to view response bodies from the Browser Console, so do
|
||||
// not waste the memory.
|
||||
let saveBodies = !this.webConsoleFrame.owner._browserConsole;
|
||||
this.webConsoleFrame.setSaveRequestAndResponseBodies(saveBodies);
|
||||
|
||||
this.webConsoleClient.on("networkEvent", this._onNetworkEvent);
|
||||
this.webConsoleClient.on("networkEventUpdate", this._onNetworkEventUpdate);
|
||||
|
||||
|
@ -72,8 +72,6 @@ function goUpdateConsoleCommands() {
|
||||
|
||||
<popupset id="mainPopupSet">
|
||||
<menupopup id="output-contextmenu" onpopupshowing="goUpdateGlobalEditMenuItems()">
|
||||
<menuitem id="saveBodiesContextMenu" type="checkbox" label="&saveBodies.label;"
|
||||
accesskey="&saveBodies.accesskey;"/>
|
||||
<menuitem id="menu_openURL" label="&openURL.label;"
|
||||
accesskey="&openURL.accesskey;" command="consoleCmd_openURL"
|
||||
selection="network" selectionType="single"/>
|
||||
@ -110,9 +108,6 @@ function goUpdateConsoleCommands() {
|
||||
prefKey="netxhr"/>
|
||||
<menuitem label="&btnConsoleLog;" type="checkbox" autocheck="false"
|
||||
prefKey="networkinfo"/>
|
||||
<menuseparator id="saveBodiesSeparator" />
|
||||
<menuitem id="saveBodies" type="checkbox" label="&saveBodies.label;"
|
||||
accesskey="&saveBodies.accesskey;"/>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
<toolbarbutton label="&btnPageCSS.label;" type="menu-button"
|
||||
|
201
devtools/docs/memory-panel.md
Normal file
201
devtools/docs/memory-panel.md
Normal file
@ -0,0 +1,201 @@
|
||||
# Memory Tool Architecture
|
||||
|
||||
The memory tool is built of three main elements:
|
||||
|
||||
1. `JS::ubi::Node` provides an interface to either the live heap graph, or a
|
||||
serialized, offline snapshot of some heap graph from a previous moment in
|
||||
time. Our various heap analyses (census, dominator trees, shortest paths,
|
||||
etc) run on top of `JS::ubi::Node` graphs.
|
||||
|
||||
2. The `HeapAnalysesWorker` runs in a worker thread, performing analyses on
|
||||
snapshots and translating the results into something the frontend can render
|
||||
simply and quickly.
|
||||
|
||||
3. Finally, the last element is the frontend that renders data received from the
|
||||
`HeapAnalysesClient` to the DOM and translates user input into requests for
|
||||
new data with the `HeapAnalysesClient`.
|
||||
|
||||
Unlike other tools (such as the JavaScript debugger), the memory tool makes very
|
||||
little use of the Remote Debugger Server and the actors that reside in it. Use
|
||||
of the [`MemoryActor`](devtools/server/actors/memory.js) is limited to toggling
|
||||
allocation stack recording on and off, and transferring heap snapshots from the
|
||||
debuggee (which is on the server) to the `HeapAnalysesWorker` (which is on the
|
||||
client). A nice benefit that naturally emerges, is that supporting "legacy"
|
||||
servers (eg, using Firefox Developer Edition as a client to remote debug a
|
||||
release Firefox for Android server) is a no-op. As we add new analyses, we can
|
||||
run them on snapshots taken on old servers no problem. The only requirement is
|
||||
that changes to the snapshot format itself remain backwards compatible.
|
||||
|
||||
## `JS::ubi::Node`
|
||||
|
||||
`JS::ubi::Node` itself is very well documented in the `js/public/UbiNode.h`
|
||||
header. I suggest you at least skim that documentation before continuing.
|
||||
|
||||
A "heap snapshot" is a representation of the heap graph at some particular past
|
||||
instance in time.
|
||||
|
||||
A "heap analysis" is an algorithm that runs on a `JS::ubi::Node` heap
|
||||
graph. That's it. Generally, analyses can run on either the live heap graph or a
|
||||
deserialized snapshot. Example analyses include "census", which aggregates and
|
||||
counts nodes into various user-specified buckets; "dominator trees", which
|
||||
compute the "dominates" relation and retained size for all nodes in the heap
|
||||
graph; and "shortest paths" which finds the shortest paths from the GC roots to
|
||||
some subset of nodes.
|
||||
|
||||
### Saving Heap Snapshots
|
||||
|
||||
Saving a heap snapshot has a few requirements:
|
||||
|
||||
1. The binary format must remain backwards compatible and future extensible.
|
||||
|
||||
2. The live heap graph must not mutate while we are in the process of
|
||||
serializing it.
|
||||
|
||||
3. The act of saving a heap snapshot should impose as little memory overhead as
|
||||
possible. If we are taking a snapshot to debug frequent out-of-memory errors,
|
||||
we don't want to trigger an OOM ourselves!
|
||||
|
||||
To solve (1), we use the protobuf message format. The message definitions
|
||||
themselves are in `devtools/shared/heapsnapshot/CoreDump.proto`. We always use
|
||||
`optional` fields so we can change our mind about what fields are required
|
||||
sometime in the future. Deserialization checks the semantic integrity of
|
||||
deserialized protobuf messages.
|
||||
|
||||
For (2), we rely on SpiderMonkey's GC rooting hazard static analysis and the
|
||||
`AutoCheckCannotGC` dynamic analysis to ensure that neither JS nor GC runs and
|
||||
modifies objects or moves them from one address in memory to another. There is
|
||||
no equivalent suppression and static analysis technique for the
|
||||
[cycle collector](https://developer.mozilla.org/en/docs/Interfacing_with_the_XPCOM_cycle_collector),
|
||||
so care must be taken not to invoke methods that could start cycle collection or
|
||||
mutate the heap graph from the cycle collector's perspective. At the time of
|
||||
writing, we don't yet support saving the cycle collector's portion of the heap
|
||||
graph in snapshots, but that work is deemed Very Important and Very High
|
||||
Priority.
|
||||
|
||||
Finally, (3) imposes upon us that we do not build the serialized heap snapshot
|
||||
binary blob in memory, but instead stream it out to disk while generating it.
|
||||
|
||||
Once all of that is accounted for, saving snapshots becomes pretty straight
|
||||
forward. We traverse the live heap graph with `JS::ubi::Node` and
|
||||
`JS::ubi::BreadthFirst`, create a protobuf message for each node and each node's
|
||||
edges, and write these messages to disk before continuing the traversal to the
|
||||
next node.
|
||||
|
||||
This functionality is exposed to chrome JavaScript as the
|
||||
`[ThreadSafe]ChromeUtils.saveHeapSnapshot` function. See
|
||||
`dom/webidl/ThreadSafeChromeUtils.webidl` for API documentation.
|
||||
|
||||
### Reading Heap Snapshots
|
||||
|
||||
Reading heap snapshots has less restrictions than saving heap snapshots. The
|
||||
protobuf messages that make up the core dump are deserialized one by one, stored
|
||||
as a set of `DeserializedNode`s and a set of `DeserializedEdge`s, and the result
|
||||
is a `HeapSnapshot` instance.
|
||||
|
||||
The `DeserializedNode` and `DeserializedEdge` classes implement the
|
||||
`JS::ubi::Node` interface. Analyses running on offline heap snapshots rather
|
||||
than the live heap graph operate on these classes (unknowingly, of course).
|
||||
|
||||
For more details, see the
|
||||
[`mozilla::devtools::HeapSnapshot`](devtools/shared/heapsnapshot/HeapSnapshot.cpp)
|
||||
and
|
||||
[`mozilla::devtools::Deserialized{Node,Edge}`](devtools/shared/heapsnapshot/DeserializedNode.h)
|
||||
classes.
|
||||
|
||||
### Heap Analyses
|
||||
|
||||
Heap analyses operate on `JS::ubi::Node` graphs without knowledge of whether
|
||||
that graph is backed by the live heap graph or an offline heap snapshot. They
|
||||
must make sure never to allocate GC things or modify the live heap graph.
|
||||
|
||||
In general, analyses are implemented in their own `js/public/UbiFooBar.h` header
|
||||
(eg `js/public/UbiCensus.h`), and are exposed to chrome JavaScript code via a
|
||||
method on the [`HeapSnapshot`](dom/webidl/HeapSnapshot.webidl) webidl
|
||||
interface.
|
||||
|
||||
For each analysis we expose to chrome JavaScript on the `HeapSnapshot` webidl
|
||||
interface, there is a small amount of glue code in Gecko. The
|
||||
[`mozilla::devtools::HeapSnapshot`](devtools/shared/heapsnapshot/HeapSnapshot.h)
|
||||
C++ class implements the webidl interface. The analyses methods (eg
|
||||
`ComputeDominatorTree`) take the deserialized nodes and edges from the heap
|
||||
snapshot, create `JS::ubi::Node`s from them, call the analyses from
|
||||
`js/public/Ubi*.h`, and wrap the results in something that can be represented in
|
||||
JavaScript.
|
||||
|
||||
For API documentation on running specific analyses, see the
|
||||
[`HeapSnapshot`](dom/webidl/HeapSnapshot.webidl) webidl interface.
|
||||
|
||||
### Testing `JS::ubi::Node`, Snapshots, and Analyses
|
||||
|
||||
The majority of the tests reside within `devtools/shared/heapsnapshot/tests/**`.
|
||||
For reading and saving heap snapshots, most tests are gtests. The gtests can be
|
||||
run with the `mach gtest DevTools.*` command. The rest are integration sanity
|
||||
tests to make sure we can read and save snapshots in various environments, such
|
||||
as xpcshell or workers. These can be run with the usual `mach test $PATH`
|
||||
commands.
|
||||
|
||||
There are also `JS::ubi::Node` related unit tests in
|
||||
`js/src/jit-test/tests/heap-analysis/*`, `js/src/jit-test/tests/debug/Memory-*`,
|
||||
and `js/src/jsapi-tests/testUbiNode.cpp`. See
|
||||
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Running_Automated_JavaScript_Tests#Running_jit-tests
|
||||
for running the JIT tests.
|
||||
|
||||
## `HeapAnalysesWorker`
|
||||
|
||||
The `HeapAnalysesWorker` orchestrates running specific analyses on snapshots and
|
||||
transforming the results into something that can simply and quickly be rendered
|
||||
by the frontend. The analyses can take some time to run (sometimes on the order
|
||||
of seconds), so doing them in a worker thread allows the interface to stay
|
||||
responsive. The `HeapAnalysisClient` provides the main thread's interface to the
|
||||
worker.
|
||||
|
||||
The `HeapAnalysesWorker` doesn't actually do much itself; mostly just shuffling
|
||||
data and transforming it from one representation to another or calling utility
|
||||
functions that do those things. Most of these are implemented as traversals of
|
||||
the resulting census or dominator trees.
|
||||
|
||||
See the
|
||||
`devtools/shared/heapsnapshot/{CensusUtils,CensusTreeNode,DominatorTreeNode}.js`
|
||||
files for details on the various data transformations and shuffling that the
|
||||
`HeapAnalysesWorker` delegates to.
|
||||
|
||||
### Testing the `HeapAnalysesWorker` and `HeapAnalysesClient`
|
||||
|
||||
Tests for the `HeapAnalysesWorker` and `HeapAnalysesClient` reside in
|
||||
`devtools/shared/heapsnapshot/tests/**` and can be run with the usual `mach test
|
||||
$PATH` command.
|
||||
|
||||
## Frontend
|
||||
|
||||
The frontend of the memory tool is built with React and Redux.
|
||||
|
||||
[React has thorough documentation.](https://facebook.github.io/react/)
|
||||
|
||||
[Redux has thorough documentation.](http://rackt.org/redux/index.html)
|
||||
|
||||
We have React components in `devtools/client/memory/components/*`.
|
||||
|
||||
We have Redux reducers in `devtools/client/memory/reducers/*`.
|
||||
|
||||
We have Redux actions and action-creating tasks in
|
||||
`devtools/client/memory/actions/*`.
|
||||
|
||||
React components should be pure functions from their props to the rendered
|
||||
(virtual) DOM. Redux reducers should also be observably pure.
|
||||
|
||||
Impurity within the frontend is confined to the tasks that are creating and
|
||||
dispatching actions. All communication with the outside world (such as the
|
||||
`HeapAnalysesWorker`, the Remote Debugger Server, or the file system) is
|
||||
restricted to within these tasks.
|
||||
|
||||
### Testing the Frontend
|
||||
|
||||
Unit tests for React components are in `devtools/client/memory/test/chrome/*`.
|
||||
|
||||
Unit tests for actions, reducers, and state changes are in
|
||||
`devtools/client/memory/test/unit/*`.
|
||||
|
||||
Holistic integration tests for the frontend and the whole memory tool are in
|
||||
`devtools/client/memory/test/browser/*`.
|
||||
|
||||
All tests can be run with the usual `mach test $PATH` command.
|
@ -46,7 +46,7 @@ Parser.prototype = {
|
||||
// all the scripts. Fastest/easiest way is with a regular expression.
|
||||
// Don't worry, the rules of using a <script> tag are really strict,
|
||||
// this will work.
|
||||
let regexp = /<script[^>]*>([^]*?)<\/script\s*>/gim;
|
||||
let regexp = /<script[^>]*?(?:>([^]*?)<\/script\s*>|\/>)/gim;
|
||||
let syntaxTrees = [];
|
||||
let scriptMatches = [];
|
||||
let scriptMatch;
|
||||
@ -54,7 +54,9 @@ Parser.prototype = {
|
||||
if (aSource.match(/^\s*</)) {
|
||||
// First non whitespace character is <, so most definitely HTML.
|
||||
while (scriptMatch = regexp.exec(aSource)) {
|
||||
scriptMatches.push(scriptMatch[1]); // Contents are captured at index 1.
|
||||
// Contents are captured at index 1 or nothing: Self-closing scripts
|
||||
// won't capture code content
|
||||
scriptMatches.push(scriptMatch[1] || "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,11 +524,10 @@ NetworkMonitor.prototype = {
|
||||
owner: null,
|
||||
|
||||
/**
|
||||
* Whether to save the bodies of network requests and responses. Disabled by
|
||||
* default to save memory.
|
||||
* Whether to save the bodies of network requests and responses.
|
||||
* @type boolean
|
||||
*/
|
||||
saveRequestAndResponseBodies: false,
|
||||
saveRequestAndResponseBodies: true,
|
||||
|
||||
/**
|
||||
* Object that holds the HTTP activity objects for ongoing requests.
|
||||
@ -1243,7 +1242,7 @@ NetworkMonitorChild.prototype = {
|
||||
appId: null,
|
||||
owner: null,
|
||||
_netEvents: null,
|
||||
_saveRequestAndResponseBodies: false,
|
||||
_saveRequestAndResponseBodies: true,
|
||||
|
||||
get saveRequestAndResponseBodies() {
|
||||
return this._saveRequestAndResponseBodies;
|
||||
|
@ -87,7 +87,7 @@ function onNetworkEventUpdate(aState, aType, aPacket)
|
||||
status: "200",
|
||||
statusText: "OK",
|
||||
headersSize: /^\d+$/,
|
||||
discardResponseBody: true,
|
||||
discardResponseBody: false,
|
||||
},
|
||||
};
|
||||
break;
|
||||
@ -104,8 +104,8 @@ function onNetworkEventUpdate(aState, aType, aPacket)
|
||||
case "responseContent":
|
||||
expectedPacket = {
|
||||
mimeType: "application/json",
|
||||
contentSize: 0,
|
||||
discardResponseBody: true,
|
||||
contentSize: 1070,
|
||||
discardResponseBody: false,
|
||||
};
|
||||
break;
|
||||
case "eventTimings":
|
||||
@ -180,7 +180,7 @@ function onRequestPostData(aState, aResponse)
|
||||
info("checking request POST data");
|
||||
|
||||
ok(!aResponse.postData.text, "no request POST data");
|
||||
ok(aResponse.postDataDiscarded, "request POST data was discarded");
|
||||
ok(!aResponse.postDataDiscarded, "request POST data was not discarded");
|
||||
|
||||
onResponseHeaders = onResponseHeaders.bind(null, aState);
|
||||
aState.client.getResponseHeaders(aState.netActor,
|
||||
@ -225,8 +225,8 @@ function onResponseContent(aState, aResponse)
|
||||
{
|
||||
info("checking response content");
|
||||
|
||||
ok(!aResponse.content.text, "no response content");
|
||||
ok(aResponse.contentDiscarded, "response content was discarded");
|
||||
ok(aResponse.content.text, "response content text");
|
||||
ok(!aResponse.contentDiscarded, "response content was not discarded");
|
||||
|
||||
onEventTimings = onEventTimings.bind(null, aState);
|
||||
aState.client.getEventTimings(aState.netActor,
|
||||
|
@ -25,7 +25,7 @@ function startTest()
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
info("enable network request and response body logging");
|
||||
info("set long string length");
|
||||
|
||||
window.ORIGINAL_LONG_STRING_LENGTH = DebuggerServer.LONG_STRING_LENGTH;
|
||||
window.ORIGINAL_LONG_STRING_INITIAL_LENGTH =
|
||||
@ -34,18 +34,6 @@ function onAttach(aState, aResponse)
|
||||
DebuggerServer.LONG_STRING_LENGTH = 400;
|
||||
DebuggerServer.LONG_STRING_INITIAL_LENGTH = 400;
|
||||
|
||||
onSetPreferences = onSetPreferences.bind(null, aState);
|
||||
aState.client.setPreferences({
|
||||
"NetworkMonitor.saveRequestAndResponseBodies": true,
|
||||
}, onSetPreferences);
|
||||
}
|
||||
|
||||
function onSetPreferences(aState, aResponse)
|
||||
{
|
||||
is(aResponse.updated.length, 1, "updated prefs length");
|
||||
is(aResponse.updated[0], "NetworkMonitor.saveRequestAndResponseBodies",
|
||||
"updated prefs length");
|
||||
|
||||
info("test network POST request");
|
||||
|
||||
onNetworkEvent = onNetworkEvent.bind(null, aState);
|
||||
|
@ -25,20 +25,6 @@ function startTest()
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
info("enable network request and response body logging");
|
||||
|
||||
onSetPreferences = onSetPreferences.bind(null, aState);
|
||||
aState.client.setPreferences({
|
||||
"NetworkMonitor.saveRequestAndResponseBodies": true,
|
||||
}, onSetPreferences);
|
||||
}
|
||||
|
||||
function onSetPreferences(aState, aResponse)
|
||||
{
|
||||
is(aResponse.updated.length, 1, "updated prefs length");
|
||||
is(aResponse.updated[0], "NetworkMonitor.saveRequestAndResponseBodies",
|
||||
"updated prefs length");
|
||||
|
||||
info("test network POST request");
|
||||
|
||||
onNetworkEvent = onNetworkEvent.bind(null, aState);
|
||||
|
@ -403,7 +403,7 @@ public class BrowserApp extends GeckoApp
|
||||
// This flow is from the option menu which has check to see if a bookmark was already added.
|
||||
// So, it is safe here to show the snackbar that bookmark_added without any checks.
|
||||
|
||||
final SnackbarCallback callback = new SnackbarCallback() {
|
||||
final SnackbarHelper.SnackbarCallback callback = new SnackbarHelper.SnackbarCallback() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.TOAST, "bookmark_options");
|
||||
@ -411,18 +411,19 @@ public class BrowserApp extends GeckoApp
|
||||
}
|
||||
};
|
||||
|
||||
showSnackbar(getResources().getString(R.string.bookmark_added),
|
||||
SnackbarHelper.showSnackbarWithAction(this,
|
||||
getResources().getString(R.string.bookmark_added),
|
||||
Snackbar.LENGTH_LONG,
|
||||
getResources().getString(R.string.bookmark_options),
|
||||
callback);
|
||||
}
|
||||
|
||||
private void showBookmarkRemovedSnackbar() {
|
||||
showSnackbar(getResources().getString(R.string.bookmark_removed), Snackbar.LENGTH_SHORT, null, null);
|
||||
SnackbarHelper.showSnackbar(this, getResources().getString(R.string.bookmark_removed), Snackbar.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
private void showSwitchToReadingListSnackbar(String message) {
|
||||
final SnackbarCallback callback = new SnackbarCallback() {
|
||||
final SnackbarHelper.SnackbarCallback callback = new SnackbarHelper.SnackbarCallback() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.TOAST, "reading_list");
|
||||
@ -432,7 +433,11 @@ public class BrowserApp extends GeckoApp
|
||||
}
|
||||
};
|
||||
|
||||
showSnackbar(message, Snackbar.LENGTH_LONG, getResources().getString(R.string.switch_button_message), callback);
|
||||
SnackbarHelper.showSnackbarWithAction(this,
|
||||
message,
|
||||
Snackbar.LENGTH_LONG,
|
||||
getResources().getString(R.string.switch_button_message),
|
||||
callback);
|
||||
}
|
||||
|
||||
public void onAddedToReadingList(String url) {
|
||||
@ -444,7 +449,9 @@ public class BrowserApp extends GeckoApp
|
||||
}
|
||||
|
||||
public void onRemovedFromReadingList(String url) {
|
||||
showSnackbar(getResources().getString(R.string.reading_list_removed), Snackbar.LENGTH_SHORT, null, null);
|
||||
SnackbarHelper.showSnackbar(this,
|
||||
getResources().getString(R.string.reading_list_removed),
|
||||
Snackbar.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2726,10 +2733,8 @@ public class BrowserApp extends GeckoApp
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(View view, MotionEvent event) {
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN
|
||||
&& mSnackbar != null
|
||||
&& mSnackbar.isShown()) {
|
||||
mSnackbar.dismiss();
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
SnackbarHelper.dismissCurrentSnackbar();
|
||||
}
|
||||
|
||||
// Only try to hide the button toast if it's already inflated and if we are starting a tap action.
|
||||
@ -3731,7 +3736,7 @@ public class BrowserApp extends GeckoApp
|
||||
// hold a reference to the Tab itself in the anonymous listener class.
|
||||
final int newTabId = newTab.getId();
|
||||
|
||||
final SnackbarCallback callback = new SnackbarCallback() {
|
||||
final SnackbarHelper.SnackbarCallback callback = new SnackbarHelper.SnackbarCallback() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.TOAST, "switchtab");
|
||||
@ -3745,7 +3750,7 @@ public class BrowserApp extends GeckoApp
|
||||
getResources().getString(R.string.new_tab_opened);
|
||||
final String buttonMessage = getResources().getString(R.string.switch_button_message);
|
||||
|
||||
showSnackbar(message, Snackbar.LENGTH_LONG, buttonMessage, callback);
|
||||
SnackbarHelper.showSnackbarWithAction(this, message, Snackbar.LENGTH_LONG, buttonMessage, callback);
|
||||
}
|
||||
|
||||
// BrowserSearch.OnSearchListener
|
||||
|
@ -217,8 +217,9 @@ public class EditBookmarkDialog {
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Void result) {
|
||||
View view = ((Activity)context).findViewById(android.R.id.content);
|
||||
Snackbar.make(view, R.string.bookmark_updated, Snackbar.LENGTH_SHORT).show();
|
||||
SnackbarHelper.showSnackbar((Activity) context,
|
||||
context.getString(R.string.bookmark_updated),
|
||||
Snackbar.LENGTH_SHORT);
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import org.mozilla.gecko.AppConstants.Versions;
|
||||
@ -50,7 +49,6 @@ import org.mozilla.gecko.widget.ButtonToast;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
@ -76,9 +74,7 @@ import android.os.Process;
|
||||
import android.os.StrictMode;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.MediaStore.Images.Media;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Base64;
|
||||
@ -196,7 +192,6 @@ public abstract class GeckoApp
|
||||
protected DoorHangerPopup mDoorHangerPopup;
|
||||
protected FormAssistPopup mFormAssistPopup;
|
||||
protected ButtonToast mToast;
|
||||
protected Snackbar mSnackbar;
|
||||
|
||||
protected LayerView mLayerView;
|
||||
private AbsoluteLayout mPluginContainer;
|
||||
@ -579,7 +574,7 @@ public abstract class GeckoApp
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showSnackbar(getString(resId), Snackbar.LENGTH_SHORT, null, null);
|
||||
SnackbarHelper.showSnackbar(GeckoApp.this, getString(resId), Snackbar.LENGTH_SHORT);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -651,17 +646,7 @@ public abstract class GeckoApp
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHARE, TelemetryContract.Method.LIST, "text");
|
||||
|
||||
} else if ("Snackbar:Show".equals(event)) {
|
||||
final String msg = message.getString("message");
|
||||
final int duration = message.getInt("duration");
|
||||
|
||||
NativeJSObject action = message.optObject("action", null);
|
||||
|
||||
final SnackbarEventCallback snackbarCallback = new SnackbarEventCallback(callback);
|
||||
|
||||
showSnackbar(msg,
|
||||
duration,
|
||||
action != null ? action.optString("label", null) : null,
|
||||
snackbarCallback);
|
||||
SnackbarHelper.showSnackbar(this, message, callback);
|
||||
} else if ("SystemUI:Visibility".equals(event)) {
|
||||
setSystemUiVisible(message.getBoolean("visible"));
|
||||
|
||||
@ -844,58 +829,6 @@ public abstract class GeckoApp
|
||||
return mToast;
|
||||
}
|
||||
|
||||
void showSnackbar(final String message, final int duration, @Nullable final String action,
|
||||
final @Nullable SnackbarCallback callback) {
|
||||
final Snackbar snackbar = Snackbar.make(mRootLayout, message, duration);
|
||||
|
||||
if (callback != null && !TextUtils.isEmpty(action)) {
|
||||
snackbar.setAction(action, callback);
|
||||
snackbar.setActionTextColor(ContextCompat.getColor(this, R.color.fennec_ui_orange));
|
||||
snackbar.setCallback(callback);
|
||||
}
|
||||
|
||||
snackbar.show();
|
||||
|
||||
this.mSnackbar = snackbar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combined interface for handling all callbacks from a snackbar because anonymous classes can only extend one
|
||||
* interface or class.
|
||||
*/
|
||||
public static abstract class SnackbarCallback extends Snackbar.Callback implements View.OnClickListener {};
|
||||
|
||||
/**
|
||||
* SnackbarCallback implementation for delegating snackbar events to an EventCallback.
|
||||
*/
|
||||
private static class SnackbarEventCallback extends SnackbarCallback {
|
||||
private EventCallback callback;
|
||||
|
||||
public SnackbarEventCallback(EventCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onClick(View view) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback.sendSuccess(null);
|
||||
callback = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDismissed(Snackbar snackbar, int event) {
|
||||
if (callback == null || event == Snackbar.Callback.DISMISS_EVENT_ACTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback.sendError(null);
|
||||
callback = null;
|
||||
}
|
||||
}
|
||||
|
||||
void showButtonToast(final String message, final String duration,
|
||||
final String buttonText, final String buttonIcon,
|
||||
final String buttonId) {
|
||||
@ -1061,12 +994,12 @@ public abstract class GeckoApp
|
||||
File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
|
||||
|
||||
if (!dcimDir.mkdirs() && !dcimDir.isDirectory()) {
|
||||
showSnackbar(getString(R.string.set_image_path_fail), Snackbar.LENGTH_SHORT, null, null);
|
||||
SnackbarHelper.showSnackbar(this, getString(R.string.set_image_path_fail), Snackbar.LENGTH_SHORT);
|
||||
return;
|
||||
}
|
||||
String path = Media.insertImage(getContentResolver(),image, null, null);
|
||||
if (path == null) {
|
||||
showSnackbar(getString(R.string.set_image_path_fail), Snackbar.LENGTH_SHORT, null, null);
|
||||
SnackbarHelper.showSnackbar(this, getString(R.string.set_image_path_fail), Snackbar.LENGTH_SHORT);
|
||||
return;
|
||||
}
|
||||
final Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
|
||||
@ -1083,7 +1016,7 @@ public abstract class GeckoApp
|
||||
};
|
||||
ActivityHandlerHelper.startIntentForActivity(this, chooser, handler);
|
||||
} else {
|
||||
showSnackbar(getString(R.string.set_image_fail), Snackbar.LENGTH_SHORT, null, null);
|
||||
SnackbarHelper.showSnackbar(this, getString(R.string.set_image_fail), Snackbar.LENGTH_SHORT);
|
||||
}
|
||||
} catch(OutOfMemoryError ome) {
|
||||
Log.e(LOGTAG, "Out of Memory when converting to byte array", ome);
|
||||
|
@ -2673,8 +2673,10 @@ public class GeckoAppShell
|
||||
|
||||
// Don't fail silently, tell the user that we weren't able to share the image
|
||||
private static final void showImageShareFailureSnackbar() {
|
||||
View rootView = ((Activity)getContext()).findViewById(android.R.id.content);
|
||||
Snackbar.make(rootView, R.string.share_image_failed, Snackbar.LENGTH_SHORT).show();
|
||||
SnackbarHelper.showSnackbar((Activity) getContext(),
|
||||
getApplicationContext().getString(R.string.share_image_failed),
|
||||
Snackbar.LENGTH_SHORT
|
||||
);
|
||||
}
|
||||
|
||||
@WrapForJNI(allowMultithread = true)
|
||||
|
143
mobile/android/base/java/org/mozilla/gecko/SnackbarHelper.java
Normal file
143
mobile/android/base/java/org/mozilla/gecko/SnackbarHelper.java
Normal file
@ -0,0 +1,143 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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;
|
||||
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Helper class for creating and dismissing snackbars. Use this class to guarantee a consistent style and behavior
|
||||
* across the app.
|
||||
*/
|
||||
public class SnackbarHelper {
|
||||
/**
|
||||
* Combined interface for handling all callbacks from a snackbar because anonymous classes can only extend one
|
||||
* interface or class.
|
||||
*/
|
||||
public static abstract class SnackbarCallback extends Snackbar.Callback implements View.OnClickListener {}
|
||||
|
||||
/**
|
||||
* SnackbarCallback implementation for delegating snackbar events to an EventCallback.
|
||||
*/
|
||||
private static class SnackbarEventCallback extends SnackbarCallback {
|
||||
private EventCallback callback;
|
||||
|
||||
public SnackbarEventCallback(EventCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onClick(View view) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback.sendSuccess(null);
|
||||
callback = null; // Releasing reference. We only want to execute the callback once.
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDismissed(Snackbar snackbar, int event) {
|
||||
if (callback == null || event == Snackbar.Callback.DISMISS_EVENT_ACTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback.sendError(null);
|
||||
callback = null; // Releasing reference. We only want to execute the callback once.
|
||||
}
|
||||
}
|
||||
|
||||
private static final Object currentSnackbarLock = new Object();
|
||||
private static WeakReference<Snackbar> currentSnackbar = new WeakReference<>(null); // Guarded by 'currentSnackbarLock'
|
||||
|
||||
/**
|
||||
* Show a snackbar to display a message.
|
||||
*
|
||||
* @param activity Activity to show the snackbar in.
|
||||
* @param message The text to show. Can be formatted text.
|
||||
* @param duration How long to display the message.
|
||||
*/
|
||||
public static void showSnackbar(Activity activity, String message, int duration) {
|
||||
showSnackbarWithAction(activity, message, duration, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and show a snackbar from a Gecko Snackbar:Show event.
|
||||
*/
|
||||
public static void showSnackbar(Activity activity, final NativeJSObject object, final EventCallback callback) {
|
||||
final String message = object.getString("message");
|
||||
final int duration = object.getInt("duration");
|
||||
|
||||
NativeJSObject action = object.optObject("action", null);
|
||||
|
||||
showSnackbarWithAction(activity,
|
||||
message,
|
||||
duration,
|
||||
action != null ? action.optString("label", null) : null,
|
||||
new SnackbarHelper.SnackbarEventCallback(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a snackbar to display a message and an action.
|
||||
*
|
||||
* @param activity Activity to show the snackbar in.
|
||||
* @param message The text to show. Can be formatted text.
|
||||
* @param duration How long to display the message.
|
||||
* @param action Action text to display.
|
||||
* @param callback Callback to be invoked when the action is clicked or the snackbar is dismissed.
|
||||
*/
|
||||
public static void showSnackbarWithAction(Activity activity, String message, int duration, String action, SnackbarCallback callback) {
|
||||
final View parentView = findBestParentView(activity);
|
||||
final Snackbar snackbar = Snackbar.make(parentView, message, duration);
|
||||
|
||||
if (callback != null && !TextUtils.isEmpty(action)) {
|
||||
snackbar.setAction(action, callback);
|
||||
snackbar.setActionTextColor(ContextCompat.getColor(activity, R.color.fennec_ui_orange));
|
||||
snackbar.setCallback(callback);
|
||||
}
|
||||
|
||||
snackbar.show();
|
||||
|
||||
synchronized (currentSnackbarLock) {
|
||||
currentSnackbar = new WeakReference<>(snackbar);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss the currently visible snackbar.
|
||||
*/
|
||||
public static void dismissCurrentSnackbar() {
|
||||
synchronized (currentSnackbarLock) {
|
||||
final Snackbar snackbar = currentSnackbar.get();
|
||||
if (snackbar != null && snackbar.isShown()) {
|
||||
snackbar.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the best parent view to hold the Snackbar's view. The Snackbar implementation of the support
|
||||
* library will use this view to walk up the view tree to find an actual suitable parent (if needed).
|
||||
*/
|
||||
private static View findBestParentView(Activity activity) {
|
||||
if (activity instanceof GeckoApp) {
|
||||
final View view = activity.findViewById(R.id.root_layout);
|
||||
if (view != null) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
return activity.findViewById(android.R.id.content);
|
||||
}
|
||||
}
|
@ -21,8 +21,8 @@ import java.util.List;
|
||||
|
||||
return Arrays.asList(
|
||||
new DownloadContent.Builder()
|
||||
.setId("bff50e08-7bbc-4d77-a907-bb0a54434bee")
|
||||
.setLocation("fonts/CharisSILCompact-B.ttf.gz")
|
||||
.setId("c40929cf-7f4c-fa72-3dc9-12cadf56905d")
|
||||
.setLocation("fonts/ff7ecae7669a51d5fa6a5f8e703278ebda3a68f51bc49c4321bde4438020d639.gz")
|
||||
.setFilename("CharisSILCompact-B.ttf")
|
||||
.setChecksum("699d958b492eda0cc2823535f8567d0393090e3842f6df3c36dbe7239cb80b6d")
|
||||
.setDownloadChecksum("ff7ecae7669a51d5fa6a5f8e703278ebda3a68f51bc49c4321bde4438020d639")
|
||||
@ -32,8 +32,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("68c6472d-94a6-4fb2-8525-78e427b022fe")
|
||||
.setLocation("fonts/CharisSILCompact-BI.ttf.gz")
|
||||
.setId("6d265876-85ed-0917-fdc8-baf583ca2cba")
|
||||
.setLocation("fonts/dfb6d583edd27d5e6d91d479e6c8a5706275662c940c65b70911493bb279904a.gz")
|
||||
.setFilename("CharisSILCompact-BI.ttf")
|
||||
.setChecksum("82465e747b4f41471dbfd942842b2ee810749217d44b55dbc43623b89f9c7d9b")
|
||||
.setDownloadChecksum("dfb6d583edd27d5e6d91d479e6c8a5706275662c940c65b70911493bb279904a")
|
||||
@ -43,8 +43,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("33d0ce0d-9c48-4a37-8b74-81cce872061b")
|
||||
.setLocation("fonts/CharisSILCompact-I.ttf.gz")
|
||||
.setId("8460dc6d-d129-fd1a-24b6-343dbf6531dd")
|
||||
.setLocation("fonts/5a257ec3c5226e7be0be65e463f5b22eff108da853b9ff7bc47f1733b1ddacf2.gz")
|
||||
.setFilename("CharisSILCompact-I.ttf")
|
||||
.setChecksum("ab3ed6f2a4d4c2095b78227bd33155d7ccd05a879c107a291912640d4d64f767")
|
||||
.setDownloadChecksum("5a257ec3c5226e7be0be65e463f5b22eff108da853b9ff7bc47f1733b1ddacf2")
|
||||
@ -54,8 +54,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("7e274cdc-4216-4dc0-b7a5-8ec333f0c287")
|
||||
.setLocation("fonts/CharisSILCompact-R.ttf.gz")
|
||||
.setId("c906275c-3747-fe27-426f-6187526a6f06")
|
||||
.setLocation("fonts/cab284228b8dfe8ef46c3f1af70b5b6f9e92878f05e741ecc611e5e750a4a3b3.gz")
|
||||
.setFilename("CharisSILCompact-R.ttf")
|
||||
.setChecksum("4ed509317f1bb441b185ea13bf1c9d19d1a0b396962efa3b5dc3190ad88f2067")
|
||||
.setDownloadChecksum("cab284228b8dfe8ef46c3f1af70b5b6f9e92878f05e741ecc611e5e750a4a3b3")
|
||||
@ -65,8 +65,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("b144002f-d5de-448c-8952-da1e405e022f")
|
||||
.setLocation("fonts/ClearSans-Bold.ttf.gz")
|
||||
.setId("ff5deecc-6ecc-d816-bb51-65face460119")
|
||||
.setLocation("fonts/d95168996dc932e6504cb5448fcb759e0ee6e66c5c8603293b046d28ab589cce.gz")
|
||||
.setFilename("ClearSans-Bold.ttf")
|
||||
.setChecksum("385d0a293c1714770e198f7c762ab32f7905a0ed9d2993f69d640bd7232b4b70")
|
||||
.setDownloadChecksum("d95168996dc932e6504cb5448fcb759e0ee6e66c5c8603293b046d28ab589cce")
|
||||
@ -76,8 +76,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("f07502f5-e4c5-41a8-8788-89717397a98d")
|
||||
.setLocation("fonts/ClearSans-BoldItalic.ttf.gz")
|
||||
.setId("a173d1db-373b-ce42-1335-6b3285cfdebd")
|
||||
.setLocation("fonts/f5e18f4acc4ceaeca9e081b1be79cd6034e0dc7ad683fa240195fd6c838452e0.gz")
|
||||
.setFilename("ClearSans-BoldItalic.ttf")
|
||||
.setChecksum("7bce66864e38eecd7c94b6657b9b38c35ebfacf8046bfb1247e08f07fe933198")
|
||||
.setDownloadChecksum("f5e18f4acc4ceaeca9e081b1be79cd6034e0dc7ad683fa240195fd6c838452e0")
|
||||
@ -87,8 +87,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("afafc7ef-f516-42da-88d4-d8435f65541b")
|
||||
.setLocation("fonts/ClearSans-Italic.ttf.gz")
|
||||
.setId("e65c66df-0088-940d-ca5c-207c22118c0e")
|
||||
.setLocation("fonts/56d12114ac15d913d7d9876c698889cd25f26e14966a8bd7424aeb0f61ffaf87.gz")
|
||||
.setFilename("ClearSans-Italic.ttf")
|
||||
.setChecksum("87c13c5fbae832e4f85c3bd46fcbc175978234f39be5fe51c4937be4cbff3b68")
|
||||
.setDownloadChecksum("56d12114ac15d913d7d9876c698889cd25f26e14966a8bd7424aeb0f61ffaf87")
|
||||
@ -98,8 +98,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("28521d9b-ac2e-45d0-89b6-a4c9076dbf6d")
|
||||
.setLocation("fonts/ClearSans-Light.ttf.gz")
|
||||
.setId("25610abb-5dc8-fd75-40e7-990507f010c4")
|
||||
.setLocation("fonts/1fc716662866b9c01e32dda3fc9c54ca3e57de8c6ac523f46305d8ae6c0a9cf4.gz")
|
||||
.setFilename("ClearSans-Light.ttf")
|
||||
.setChecksum("e4885f6188e7a8587f5621c077c6c1f5e8d3739dffc8f4d055c2ba87568c750a")
|
||||
.setDownloadChecksum("1fc716662866b9c01e32dda3fc9c54ca3e57de8c6ac523f46305d8ae6c0a9cf4")
|
||||
@ -109,8 +109,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("13f01bf4-da71-4673-9c60-ec0e9a45c38c")
|
||||
.setLocation("fonts/ClearSans-Medium.ttf.gz")
|
||||
.setId("ffe40339-a096-2262-c3f8-54af75c81fe6")
|
||||
.setLocation("fonts/a29184ec6621dbd3bc6ae1e30bba70c479d1001bca647ea4a205ecb64d5a00a0.gz")
|
||||
.setFilename("ClearSans-Medium.ttf")
|
||||
.setChecksum("5d0e0115f3a3ed4be3eda6d7eabb899bb9a361292802e763d53c72e00f629da1")
|
||||
.setDownloadChecksum("a29184ec6621dbd3bc6ae1e30bba70c479d1001bca647ea4a205ecb64d5a00a0")
|
||||
@ -120,8 +120,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("73104370-c7ee-4b5b-bb37-392a4e66f65a")
|
||||
.setLocation("fonts/ClearSans-MediumItalic.ttf.gz")
|
||||
.setId("139a94be-ac69-0264-c9cc-8f2d071fd29d")
|
||||
.setLocation("fonts/a381a3d4060e993af440a7b72fed29fa3a488536cc451d7c435d5fae1256318b.gz")
|
||||
.setFilename("ClearSans-MediumItalic.ttf")
|
||||
.setChecksum("937dda88b26469306258527d38e42c95e27e7ebb9f05bd1d7c5d706a3c9541d7")
|
||||
.setDownloadChecksum("a381a3d4060e993af440a7b72fed29fa3a488536cc451d7c435d5fae1256318b")
|
||||
@ -131,8 +131,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("274f3718-f6e0-40b4-b52a-44812ec3ea9e")
|
||||
.setLocation("fonts/ClearSans-Regular.ttf.gz")
|
||||
.setId("b887012a-01e1-7c94-fdcb-ca44d5b974a2")
|
||||
.setLocation("fonts/87dec7f0331e19b293fc510f2764b9bd1b94595ac279cf9414f8d03c5bf34dca.gz")
|
||||
.setFilename("ClearSans-Regular.ttf")
|
||||
.setChecksum("9b91bbdb95ffa6663da24fdaa8ee06060cd0a4d2dceaf1ffbdda00e04915ee5b")
|
||||
.setDownloadChecksum("87dec7f0331e19b293fc510f2764b9bd1b94595ac279cf9414f8d03c5bf34dca")
|
||||
@ -142,8 +142,8 @@ import java.util.List;
|
||||
.build(),
|
||||
|
||||
new DownloadContent.Builder()
|
||||
.setId("77803858-3cfb-4a0d-a1d3-fa1bf8a6c604")
|
||||
.setLocation("fonts/ClearSans-Thin.ttf.gz")
|
||||
.setId("c8703652-d317-0356-0bf8-95441a5b2c9b")
|
||||
.setLocation("fonts/64300b48b2867e5642212690f0ff9ea3988f47790311c444a81d25213b4102aa.gz")
|
||||
.setFilename("ClearSans-Thin.ttf")
|
||||
.setChecksum("07b0db85a3ad99afeb803f0f35631436a7b4c67ac66d0c7f77d26a47357c592a")
|
||||
.setDownloadChecksum("64300b48b2867e5642212690f0ff9ea3988f47790311c444a81d25213b4102aa")
|
||||
|
@ -15,6 +15,7 @@ import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.ReaderModeUtils;
|
||||
import org.mozilla.gecko.Restrictions;
|
||||
import org.mozilla.gecko.SnackbarHelper;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
@ -413,8 +414,9 @@ public abstract class HomeFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Void result) {
|
||||
View rootView = ((Activity)mContext).findViewById(android.R.id.content);
|
||||
Snackbar.make(rootView, R.string.page_removed, Snackbar.LENGTH_SHORT).show();
|
||||
SnackbarHelper.showSnackbar((Activity) mContext,
|
||||
mContext.getString(R.string.page_removed),
|
||||
Snackbar.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import org.mozilla.gecko.Locales;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Restrictions;
|
||||
import org.mozilla.gecko.SnackbarHelper;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.TelemetryContract.Method;
|
||||
@ -34,9 +35,12 @@ import org.mozilla.gecko.restrictions.Restrictable;
|
||||
import org.mozilla.gecko.tabqueue.TabQueueHelper;
|
||||
import org.mozilla.gecko.updater.UpdateService;
|
||||
import org.mozilla.gecko.updater.UpdateServiceHelper;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.InputOptionsUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.widget.FloatingHintEditText;
|
||||
|
||||
@ -92,6 +96,7 @@ extends PreferenceActivity
|
||||
implements
|
||||
GeckoActivityStatus,
|
||||
GeckoEventListener,
|
||||
NativeEventListener,
|
||||
OnPreferenceChangeListener,
|
||||
OnSharedPreferenceChangeListener
|
||||
{
|
||||
@ -361,9 +366,12 @@ OnSharedPreferenceChangeListener
|
||||
addPreferencesFromResource(res);
|
||||
}
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener) this,
|
||||
"Sanitize:Finished");
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener) this,
|
||||
"Snackbar:Show");
|
||||
|
||||
// Add handling for long-press click.
|
||||
// This is only for Android 3.0 and below (which use the long-press-context-menu paradigm).
|
||||
final ListView mListView = getListView();
|
||||
@ -512,8 +520,12 @@ OnSharedPreferenceChangeListener
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
|
||||
"Sanitize:Finished");
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
|
||||
"Snackbar:Show");
|
||||
|
||||
if (mPrefsRequestId > 0) {
|
||||
PrefsHelper.removeObserver(mPrefsRequestId);
|
||||
}
|
||||
@ -617,19 +629,23 @@ OnSharedPreferenceChangeListener
|
||||
if (event.equals("Sanitize:Finished")) {
|
||||
boolean success = message.getBoolean("success");
|
||||
final int stringRes = success ? R.string.private_data_success : R.string.private_data_fail;
|
||||
final Context context = this;
|
||||
ThreadUtils.postToUiThread(new Runnable () {
|
||||
@Override
|
||||
public void run() {
|
||||
Snackbar.make(findViewById(android.R.id.content), stringRes, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
SnackbarHelper.showSnackbar(GeckoPreferences.this,
|
||||
getString(stringRes),
|
||||
Snackbar.LENGTH_SHORT);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message, final EventCallback callback) {
|
||||
if ("Snackbar:Show".equals(event)) {
|
||||
SnackbarHelper.showSnackbar(this, message, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all of the preferences (native of Gecko ones) for this screen.
|
||||
*
|
||||
|
@ -7,6 +7,7 @@ package org.mozilla.gecko.preferences;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.SnackbarHelper;
|
||||
import org.mozilla.gecko.favicons.Favicons;
|
||||
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
|
||||
import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
|
||||
@ -89,13 +90,12 @@ public class SearchEnginePreference extends CustomListPreference {
|
||||
// If this is the last engine, then we are the default, and none of the options
|
||||
// on this menu can do anything.
|
||||
if (mParentCategory.getPreferenceCount() == 1) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Activity activity = (Activity) getContext();
|
||||
Snackbar.make(activity.findViewById(android.R.id.content), R.string.pref_search_last_toast, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
SnackbarHelper.showSnackbar(activity,
|
||||
activity.getString(R.string.pref_search_last_toast),
|
||||
Snackbar.LENGTH_SHORT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -509,6 +509,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
|
||||
'SharedPreferencesHelper.java',
|
||||
'SiteIdentity.java',
|
||||
'SmsManager.java',
|
||||
'SnackbarHelper.java',
|
||||
'sqlite/ByteBufferInputStream.java',
|
||||
'sqlite/MatrixBlobCursor.java',
|
||||
'sqlite/SQLiteBridge.java',
|
||||
|
@ -82,6 +82,6 @@ ident:
|
||||
merge-%:
|
||||
ifdef LOCALE_MERGEDIR
|
||||
$(RM) -rf $(LOCALE_MERGEDIR)
|
||||
MACOSX_DEPLOYMENT_TARGET= compare-locales -m $(LOCALE_MERGEDIR) $(srcdir)/l10n.ini $(L10NBASEDIR) $*
|
||||
$(topsrcdir)/mach compare-locales --merge-dir $(LOCALE_MERGEDIR) $*
|
||||
endif
|
||||
@echo
|
||||
|
@ -71,7 +71,7 @@ xul|scrollbarbutton[sbattr="scrollbar-bottom-top"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
xul|thumb {
|
||||
xul|scrollbar xul|thumb {
|
||||
background-color: rgba(0, 0, 0, 0.4) !important;
|
||||
-moz-border-top-colors: none !important;
|
||||
-moz-border-bottom-colors: none !important;
|
||||
|
@ -70,7 +70,7 @@ class CompareLocales(MachCommandBase):
|
||||
merge_dir = mozpath.join(
|
||||
self.topobjdir,
|
||||
self.substs['MOZ_BUILD_APP'],
|
||||
'locales', 'merge-{ab_CD}'
|
||||
'locales', 'merge-dir-{ab_CD}'
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
@ -31,6 +31,21 @@ class LocalesMixin(ChunkingMixin):
|
||||
self.gecko_locale_revisions = None
|
||||
self.l10n_revisions = {}
|
||||
|
||||
def _get_mach_executable(self):
|
||||
python = self.query_exe('python2.7')
|
||||
return [python, 'mach']
|
||||
|
||||
def _mach(self, target, env, error_list=None, halt_on_failure=True,
|
||||
output_parser=None):
|
||||
dirs = self.query_abs_dirs()
|
||||
mach = self._get_mach_executable()
|
||||
return self.run_command(mach + target,
|
||||
error_list=error_list,
|
||||
halt_on_failure=True,
|
||||
env=env,
|
||||
cwd=dirs['abs_mozilla_dir'],
|
||||
output_parser=None)
|
||||
|
||||
def query_locales(self):
|
||||
if self.locales is not None:
|
||||
return self.locales
|
||||
@ -141,19 +156,12 @@ class LocalesMixin(ChunkingMixin):
|
||||
|
||||
def run_compare_locales(self, locale, halt_on_failure=False):
|
||||
dirs = self.query_abs_dirs()
|
||||
compare_locales_script = os.path.join(dirs['abs_compare_locales_dir'],
|
||||
'scripts', 'compare-locales')
|
||||
env = self.query_env(partial_env={'PYTHONPATH':
|
||||
os.path.join(dirs['abs_compare_locales_dir'],
|
||||
'lib')})
|
||||
env = self.query_bootstrap_env()
|
||||
compare_locales_error_list = list(PythonErrorList)
|
||||
self.rmtree(dirs['abs_merge_dir'])
|
||||
self.mkdir_p(dirs['abs_merge_dir'])
|
||||
command = "python %s -m %s l10n.ini %s %s" % (compare_locales_script,
|
||||
dirs['abs_merge_dir'], dirs['abs_l10n_dir'], locale)
|
||||
command = ['compare-locales',
|
||||
'--merge-dir', dirs['abs_merge_dir'], locale]
|
||||
self.info("*** BEGIN compare-locales %s" % locale)
|
||||
status = self.run_command(command, error_list=compare_locales_error_list,
|
||||
cwd=dirs['abs_locales_src_dir'], env=env,
|
||||
status = self._mach(command, env, error_list=compare_locales_error_list,
|
||||
halt_on_failure=halt_on_failure)
|
||||
self.info("*** END compare-locales %s" % locale)
|
||||
return status
|
||||
@ -187,8 +195,6 @@ class LocalesMixin(ChunkingMixin):
|
||||
'merged')
|
||||
dirs['abs_locales_dir'] = os.path.join(dirs['abs_objdir'],
|
||||
c['locales_dir'])
|
||||
dirs['abs_compare_locales_dir'] = os.path.join(dirs['abs_work_dir'],
|
||||
'compare-locales')
|
||||
for key in dirs.keys():
|
||||
if key not in abs_dirs:
|
||||
abs_dirs[key] = dirs[key]
|
||||
|
@ -606,25 +606,12 @@ class DesktopSingleLocale(LocalesMixin, ReleaseMixin, MockMixin, BuildbotMixin,
|
||||
self.copyfile(src, dst)
|
||||
self.read_from_file(dst, verbose=True)
|
||||
|
||||
def _mach(self, target, env, halt_on_failure=True, output_parser=None):
|
||||
dirs = self.query_abs_dirs()
|
||||
mach = self._get_mach_executable()
|
||||
return self.run_command(mach + target,
|
||||
halt_on_failure=True,
|
||||
env=env,
|
||||
cwd=dirs['abs_mozilla_dir'],
|
||||
output_parser=None)
|
||||
|
||||
def _mach_configure(self):
|
||||
"""calls mach configure"""
|
||||
env = self.query_bootstrap_env()
|
||||
target = ["configure"]
|
||||
return self._mach(target=target, env=env)
|
||||
|
||||
def _get_mach_executable(self):
|
||||
python = self.query_exe('python2.7')
|
||||
return [python, 'mach']
|
||||
|
||||
def _get_make_executable(self):
|
||||
config = self.config
|
||||
dirs = self.query_abs_dirs()
|
||||
|
@ -8271,11 +8271,6 @@
|
||||
"releaseChannelCollection": "opt-out",
|
||||
"description": "Number of sessions where at least one chat message was exchanged"
|
||||
},
|
||||
"E10S_AUTOSTART": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "boolean",
|
||||
"description": "Whether a session is set to autostart e10s windows"
|
||||
},
|
||||
"E10S_AUTOSTART_STATUS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
|
@ -746,6 +746,11 @@ var Impl = {
|
||||
// task to complete, but TelemetryStorage blocks on it during shutdown.
|
||||
TelemetryStorage.runCleanPingArchiveTask();
|
||||
|
||||
// Now that FHR/healthreporter is gone, make sure to remove FHR's DB from
|
||||
// the profile directory. This is a temporary measure that we should drop
|
||||
// in the future.
|
||||
TelemetryStorage.removeFHRDatabase();
|
||||
|
||||
this._delayedInitTaskDeferred.resolve();
|
||||
} catch (e) {
|
||||
this._delayedInitTaskDeferred.reject(e);
|
||||
|
@ -20,6 +20,7 @@ Cu.import("resource://gre/modules/osfile.jsm", this);
|
||||
Cu.import("resource://gre/modules/Task.jsm", this);
|
||||
Cu.import("resource://gre/modules/TelemetryUtils.jsm", this);
|
||||
Cu.import("resource://gre/modules/Promise.jsm", this);
|
||||
Cu.import("resource://gre/modules/Preferences.jsm", this);
|
||||
|
||||
const LOGGER_NAME = "Toolkit.Telemetry";
|
||||
const LOGGER_PREFIX = "TelemetryStorage::";
|
||||
@ -413,6 +414,15 @@ this.TelemetryStorage = {
|
||||
return TelemetryStorageImpl.loadPingFile(aFilePath);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Remove FHR database files. This is temporary and will be dropped in
|
||||
* the future.
|
||||
* @return {Promise} Resolved when the database files are deleted.
|
||||
*/
|
||||
removeFHRDatabase: function() {
|
||||
return TelemetryStorageImpl.removeFHRDatabase();
|
||||
},
|
||||
|
||||
/**
|
||||
* Only used in tests, builds an archived ping path from the ping metadata.
|
||||
* @param {String} aPingId The ping id.
|
||||
@ -1718,6 +1728,42 @@ var TelemetryStorageImpl = {
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove FHR database files. This is temporary and will be dropped in
|
||||
* the future.
|
||||
* @return {Promise} Resolved when the database files are deleted.
|
||||
*/
|
||||
removeFHRDatabase: Task.async(function*() {
|
||||
this._log.trace("removeFHRDatabase");
|
||||
|
||||
// Let's try to remove the FHR DB with the default filename first.
|
||||
const FHR_DB_DEFAULT_FILENAME = "healthreport.sqlite";
|
||||
|
||||
// Even if it's uncommon, there may be 2 additional files: - a "write ahead log"
|
||||
// (-wal) file and a "shared memory file" (-shm). We need to remove them as well.
|
||||
let FILES_TO_REMOVE = [
|
||||
OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_DEFAULT_FILENAME),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_DEFAULT_FILENAME + "-wal"),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_DEFAULT_FILENAME + "-shm"),
|
||||
];
|
||||
|
||||
// FHR could have used either the default DB file name or a custom one
|
||||
// through this preference.
|
||||
const FHR_DB_CUSTOM_FILENAME =
|
||||
Preferences.get("datareporting.healthreport.dbName", undefined);
|
||||
if (FHR_DB_CUSTOM_FILENAME) {
|
||||
FILES_TO_REMOVE.push(
|
||||
OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_CUSTOM_FILENAME),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_CUSTOM_FILENAME + "-wal"),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_CUSTOM_FILENAME + "-shm"));
|
||||
}
|
||||
|
||||
for (let f of FILES_TO_REMOVE) {
|
||||
yield OS.File.remove(f, {ignoreAbsent: true})
|
||||
.catch(e => this._log.error("removeFHRDatabase - failed to remove " + f, e));
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
///// Utility functions
|
||||
|
@ -460,6 +460,54 @@ add_task(function* test_telemetryEnabledUnexpectedValue(){
|
||||
"False must disable Telemetry recording.");
|
||||
});
|
||||
|
||||
add_task(function* test_telemetryCleanFHRDatabase(){
|
||||
const FHR_DBNAME_PREF = "datareporting.healthreport.dbName";
|
||||
const CUSTOM_DB_NAME = "unlikely.to.be.used.sqlite";
|
||||
const DEFAULT_DB_NAME = "healthreport.sqlite";
|
||||
|
||||
// Check that we're able to remove a FHR DB with a custom name.
|
||||
const CUSTOM_DB_PATHS = [
|
||||
OS.Path.join(OS.Constants.Path.profileDir, CUSTOM_DB_NAME),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, CUSTOM_DB_NAME + "-wal"),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, CUSTOM_DB_NAME + "-shm"),
|
||||
];
|
||||
Preferences.set(FHR_DBNAME_PREF, CUSTOM_DB_NAME);
|
||||
|
||||
// Write fake DB files to the profile directory.
|
||||
for (let dbFilePath of CUSTOM_DB_PATHS) {
|
||||
yield OS.File.writeAtomic(dbFilePath, "some data");
|
||||
}
|
||||
|
||||
// Trigger the cleanup and check that the files were removed.
|
||||
yield TelemetryStorage.removeFHRDatabase();
|
||||
for (let dbFilePath of CUSTOM_DB_PATHS) {
|
||||
Assert.ok(!(yield OS.File.exists(dbFilePath)), "The DB must not be on the disk anymore: " + dbFilePath);
|
||||
}
|
||||
|
||||
// We should not break anything if there's no DB file.
|
||||
yield TelemetryStorage.removeFHRDatabase();
|
||||
|
||||
// Check that we're able to remove a FHR DB with the default name.
|
||||
Preferences.reset(FHR_DBNAME_PREF);
|
||||
|
||||
const DEFAULT_DB_PATHS = [
|
||||
OS.Path.join(OS.Constants.Path.profileDir, DEFAULT_DB_NAME),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, DEFAULT_DB_NAME + "-wal"),
|
||||
OS.Path.join(OS.Constants.Path.profileDir, DEFAULT_DB_NAME + "-shm"),
|
||||
];
|
||||
|
||||
// Write fake DB files to the profile directory.
|
||||
for (let dbFilePath of DEFAULT_DB_PATHS) {
|
||||
yield OS.File.writeAtomic(dbFilePath, "some data");
|
||||
}
|
||||
|
||||
// Trigger the cleanup and check that the files were removed.
|
||||
yield TelemetryStorage.removeFHRDatabase();
|
||||
for (let dbFilePath of DEFAULT_DB_PATHS) {
|
||||
Assert.ok(!(yield OS.File.exists(dbFilePath)), "The DB must not be on the disk anymore: " + dbFilePath);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* stopServer(){
|
||||
yield PingServer.stop();
|
||||
do_test_finished();
|
||||
|
@ -4782,7 +4782,6 @@ mozilla::BrowserTabsRemoteAutostart()
|
||||
status = kE10sEnabledByUser;
|
||||
}
|
||||
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::E10S_AUTOSTART, gBrowserTabsRemoteAutostart);
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::E10S_AUTOSTART_STATUS, status);
|
||||
if (Preferences::GetBool("browser.enabledE10SFromPrompt", false)) {
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::E10S_STILL_ACCEPTED_FROM_PROMPT,
|
||||
|
Loading…
Reference in New Issue
Block a user