This commit is contained in:
Wes Kocher 2016-08-12 16:39:13 -07:00
Родитель 51baff5088 b44cee8b2a
Коммит 0fe7a92d47
803 изменённых файлов: 34365 добавлений и 6920 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -74,6 +74,9 @@ python/psutil/build/
devtools/client/chrome.manifest
devtools/shared/chrome.manifest
# Ignore node_modules directories in devtools
devtools/client/**/node_modules
# Tag files generated by GNU Global
GTAGS
GRTAGS

Просмотреть файл

@ -78,6 +78,9 @@ _OPT\.OBJ/
^devtools/client/chrome.manifest$
^devtools/shared/chrome.manifest$
# Ignore node_modules directories in devtools
^devtools/client/.*/node_modules/
# git checkout of libstagefright
^media/libstagefright/android$

Просмотреть файл

@ -197,6 +197,16 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
kNoReqStates,
eReadonlyUntilEditable
},
{ // feed
&nsGkAtoms::feed,
roles::GROUPING,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // form
&nsGkAtoms::form,
roles::FORM,

Просмотреть файл

@ -410,7 +410,7 @@ public:
NS_DECL_ISUPPORTS
NS_IMETHODIMP Notify(nsITimer* aTimer) final
NS_IMETHOD Notify(nsITimer* aTimer) final
{
if (!mContent->IsInUncomposedDoc())
return NS_OK;

Просмотреть файл

@ -31,6 +31,7 @@
testAttrs("section", {"xml-roles" : "region"}, true);
testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
testAttrs("form", {"xml-roles" : "form"}, true);
testAttrs("feed", {"xml-roles" : "feed"}, true);
testAttrs("article", {"xml-roles" : "article"}, true);
testAttrs("main_element", {"xml-roles" : "main"}, true);
@ -159,6 +160,7 @@
<section id="section">a section</section>
<article id="main" role="main">a main area</article>
<article id="form" role="form">a form area</article>
<div id="feed" role="feed">a feed</div>
<article id="article">article</article>
<main id="main_element">another main area</main>

Просмотреть файл

@ -30,6 +30,7 @@
testRole("aria_directory", ROLE_LIST);
testRole("aria_document", ROLE_DOCUMENT);
testRole("aria_form", ROLE_FORM);
testRole("aria_feed", ROLE_GROUPING);
testRole("aria_grid", ROLE_TABLE);
testRole("aria_gridcell", ROLE_GRID_CELL);
testRole("aria_group", ROLE_GROUPING);
@ -207,6 +208,7 @@
<span id="aria_directory" role="directory"/>
<span id="aria_document" role="document"/>
<span id="aria_form" role="form"/>
<span id="aria_feed" role="feed"/>
<span id="aria_grid" role="grid"/>
<span id="aria_gridcell" role="gridcell"/>
<span id="aria_group" role="group"/>

Просмотреть файл

@ -160,7 +160,7 @@
popuponly menulist to be its immediate parent. -->
<menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
<menupopup rolluponmousewheel="true"
activateontab="true"
activateontab="true" position="after_start"
#ifdef XP_WIN
consumeoutsideclicks="false" ignorekeys="handled"
#endif

Просмотреть файл

@ -473,5 +473,15 @@ add_task(function* test_mousemove_correcttarget() {
yield hideSelectPopup(selectPopup);
// The popup should be closed when fullscreen mode is entered or exited.
for (let steps = 0; steps < 2; steps++) {
yield openSelectPopup(selectPopup, true);
let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden");
let sizeModeChanged = BrowserTestUtils.waitForEvent(window, "sizemodechange");
BrowserFullScreen();
yield sizeModeChanged;
yield popupHiddenPromise;
}
yield BrowserTestUtils.removeTab(tab);
});

Просмотреть файл

@ -384,6 +384,12 @@ function* closeStream(aAlreadyClosed, aFrameId) {
if (promises)
yield Promise.all(promises);
// If a GC occurs before MediaStream.stop() is dispatched, we'll receive
// recording-device-events for each track instead of one for the stream.
if ((yield promiseTodoObserverNotCalled("recording-device-events")) == 1) {
todo(false, "Stream was GC'd before MediaStream.stop() was dispatched (bug 1284038)");
}
yield* assertWebRTCIndicatorStatus(null);
}

Просмотреть файл

@ -13,6 +13,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "styleSheetService",
"@mozilla.org/content/style-sheet-service;1",
"nsIStyleSheetService");
XPCOMUtils.defineLazyGetter(this, "colorUtils", () => {
return require("devtools/shared/css-color").colorUtils;
});
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
Cu.import("resource://gre/modules/AppConstants.jsm");
@ -95,17 +99,16 @@ class BasePopup {
this.browserStyle = browserStyle;
this.window = viewNode.ownerGlobal;
this.panel = this.viewNode;
while (this.panel.localName != "panel") {
this.panel = this.panel.parentNode;
}
this.contentReady = new Promise(resolve => {
this._resolveContentReady = resolve;
});
this.viewNode.addEventListener(this.DESTROY_EVENT, this);
let doc = viewNode.ownerDocument;
let arrowContent = doc.getAnonymousElementByAttribute(this.panel, "class", "panel-arrowcontent");
this.borderColor = doc.defaultView.getComputedStyle(arrowContent).borderTopColor;
this.browser = null;
this.browserReady = this.createBrowser(viewNode, popupURI);
}
@ -121,6 +124,9 @@ class BasePopup {
this.viewNode.style.maxHeight = "";
this.browser.remove();
this.panel.style.setProperty("--panel-arrowcontent-background", "");
this.panel.style.setProperty("--panel-arrow-image-vertical", "");
this.browser = null;
this.viewNode = null;
});
@ -136,6 +142,14 @@ class BasePopup {
return false;
}
get panel() {
let panel = this.viewNode;
while (panel.localName != "panel") {
panel = panel.parentNode;
}
return panel;
}
handleEvent(event) {
switch (event.type) {
case this.DESTROY_EVENT:
@ -263,6 +277,21 @@ class BasePopup {
return;
}
let doc = this.browser.contentDocument;
if (!doc || !doc.documentElement) {
return;
}
let root = doc.documentElement;
let body = doc.body;
if (!body || doc.compatMode == "BackCompat") {
// In quirks mode, the root element is used as the scroll frame, and the
// body lies about its scroll geometry, and returns the values for the
// root instead.
body = root;
}
if (this.fixedWidth) {
// If we're in a fixed-width area (namely a slide-in subview of the main
// menu panel), we need to calculate the view height based on the
@ -270,20 +299,6 @@ class BasePopup {
// current width, rather than the complete preferred dimensions of the
// content window.
let doc = this.browser.contentDocument;
if (!doc || !doc.documentElement) {
return;
}
let root = doc.documentElement;
let body = doc.body;
if (!body || doc.compatMode == "BackCompat") {
// In quirks mode, the root element is used as the scroll frame, and the
// body lies about its scroll geometry, and returns the values for the
// root instead.
body = root;
}
// Compensate for any offsets (margin, padding, ...) between the scroll
// area of the body and the outer height of the document.
let getHeight = elem => elem.getBoundingClientRect(elem).height;
@ -307,6 +322,32 @@ class BasePopup {
height = Math.max(height, this.viewHeight);
this.viewNode.style.maxHeight = `${height}px`;
} else {
// Copy the background color of the document's body to the panel if it's
// fully opaque.
let panelBackground = "";
let panelArrow = "";
let background = doc.defaultView.getComputedStyle(body).backgroundColor;
if (background != "transparent") {
let bgColor = colorUtils.colorToRGBA(background);
if (bgColor.a == 1) {
panelBackground = background;
let borderColor = this.borderColor || background;
panelArrow = `url("data:image/svg+xml,${encodeURIComponent(`<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="10">
<path d="M 0,10 L 10,0 20,10 z" fill="${borderColor}"/>
<path d="M 1,10 L 10,1 19,10 z" fill="${background}"/>
</svg>
`)}")`;
}
}
this.panel.style.setProperty("--panel-arrowcontent-background", panelBackground);
this.panel.style.setProperty("--panel-arrow-image-vertical", panelArrow);
// Adjust the size of the browser based on its content's preferred size.
let width, height;
try {
let w = {}, h = {};

Просмотреть файл

@ -20,6 +20,7 @@ support-files =
[browser_ext_browserAction_context.js]
[browser_ext_browserAction_disabled.js]
[browser_ext_browserAction_pageAction_icon.js]
[browser_ext_browserAction_pageAction_icon_permissions.js]
[browser_ext_browserAction_popup.js]
[browser_ext_browserAction_popup_resize.js]
[browser_ext_browserAction_simple.js]
@ -43,6 +44,7 @@ support-files =
[browser_ext_pageAction_popup_resize.js]
[browser_ext_pageAction_simple.js]
[browser_ext_popup_api_injection.js]
[browser_ext_popup_background.js]
[browser_ext_popup_corners.js]
[browser_ext_runtime_openOptionsPage.js]
[browser_ext_runtime_openOptionsPage_uninstall.js]

Просмотреть файл

@ -317,212 +317,3 @@ add_task(function* testDetailsObjects() {
yield extension.unload();
});
// Test that an error is thrown when providing invalid icon sizes
add_task(function* testInvalidIconSizes() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"browser_action": {},
"page_action": {},
},
background: function() {
browser.tabs.query({active: true, currentWindow: true}, tabs => {
let tabId = tabs[0].id;
let promises = [];
for (let api of ["pageAction", "browserAction"]) {
// helper function to run setIcon and check if it fails
let assertSetIconThrows = function(detail, error, message) {
detail.tabId = tabId;
promises.push(
browser[api].setIcon(detail).then(
() => {
browser.test.fail("Expected an error on invalid icon size.");
browser.test.notifyFail("setIcon with invalid icon size");
},
error => {
browser.test.succeed("setIcon with invalid icon size");
}));
};
let imageData = new ImageData(1, 1);
// test invalid icon size inputs
for (let type of ["path", "imageData"]) {
let img = type == "imageData" ? imageData : "test.png";
assertSetIconThrows({[type]: {"abcdef": img}});
assertSetIconThrows({[type]: {"48px": img}});
assertSetIconThrows({[type]: {"20.5": img}});
assertSetIconThrows({[type]: {"5.0": img}});
assertSetIconThrows({[type]: {"-300": img}});
assertSetIconThrows({[type]: {"abc": img, "5": img}});
}
assertSetIconThrows({imageData: {"abcdef": imageData}, path: {"5": "test.png"}});
assertSetIconThrows({path: {"abcdef": "test.png"}, imageData: {"5": imageData}});
}
Promise.all(promises).then(() => {
browser.test.notifyPass("setIcon with invalid icon size");
});
});
}
});
yield Promise.all([extension.startup(), extension.awaitFinish("setIcon with invalid icon size")]);
yield extension.unload();
});
// Test that default icon details in the manifest.json file are handled
// correctly.
add_task(function* testDefaultDetails() {
// TODO: Test localized variants.
let icons = [
"foo/bar.png",
"/foo/bar.png",
{"19": "foo/bar.png"},
{"38": "foo/bar.png"},
{"19": "foo/bar.png", "38": "baz/quux.png"},
];
let expectedURL = new RegExp(String.raw`^moz-extension://[^/]+/foo/bar\.png$`);
for (let icon of icons) {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"browser_action": {"default_icon": icon},
"page_action": {"default_icon": icon},
},
background: function() {
browser.tabs.query({active: true, currentWindow: true}, tabs => {
let tabId = tabs[0].id;
browser.pageAction.show(tabId).then(() => {
browser.test.sendMessage("ready");
});
});
},
files: {
"foo/bar.png": imageBuffer,
"baz/quux.png": imageBuffer,
},
});
yield Promise.all([extension.startup(), extension.awaitMessage("ready")]);
let browserActionId = makeWidgetId(extension.id) + "-browser-action";
let pageActionId = makeWidgetId(extension.id) + "-page-action";
let browserActionButton = document.getElementById(browserActionId);
let image = getListStyleImage(browserActionButton);
ok(expectedURL.test(image), `browser action image ${image} matches ${expectedURL}`);
let pageActionImage = document.getElementById(pageActionId);
image = getListStyleImage(pageActionImage);
ok(expectedURL.test(image), `page action image ${image} matches ${expectedURL}`);
yield extension.unload();
let node = document.getElementById(pageActionId);
is(node, null, "pageAction image removed from document");
}
});
// Check that attempts to load a privileged URL as an icon image fail.
add_task(function* testSecureURLsDenied() {
// Test URLs passed to setIcon.
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"browser_action": {},
"page_action": {},
},
background: function() {
browser.tabs.query({active: true, currentWindow: true}, tabs => {
let tabId = tabs[0].id;
let urls = ["chrome://browser/content/browser.xul",
"javascript:true"];
let promises = [];
for (let url of urls) {
for (let api of ["pageAction", "browserAction"]) {
promises.push(
browser[api].setIcon({tabId, path: url}).then(
() => {
browser.test.fail(`Load of '${url}' succeeded. Expected failure.`);
browser.test.notifyFail("setIcon security tests");
},
error => {
browser.test.succeed(`Load of '${url}' failed. Expected failure. ${error}`);
}));
}
}
Promise.all(promises).then(() => {
browser.test.notifyPass("setIcon security tests");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("setIcon security tests");
yield extension.unload();
});
add_task(function* testSecureManifestURLsDenied() {
// Test URLs included in the manifest.
let urls = ["chrome://browser/content/browser.xul",
"javascript:true"];
let apis = ["browser_action", "page_action"];
for (let url of urls) {
for (let api of apis) {
info(`TEST ${api} icon url: ${url}`);
let matchURLForbidden = url => ({
message: new RegExp(`match the format "strictRelativeUrl"`),
});
let messages = [matchURLForbidden(url)];
let waitForConsole = new Promise(resolve => {
// Not necessary in browser-chrome tests, but monitorConsole gripes
// if we don't call it.
SimpleTest.waitForExplicitFinish();
SimpleTest.monitorConsole(resolve, messages);
});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
[api]: {
"default_icon": url,
},
},
});
yield Assert.rejects(extension.startup(),
null,
"Manifest rejected");
SimpleTest.endMonitorConsole();
yield waitForConsole;
}
}
});

Просмотреть файл

@ -0,0 +1,212 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
// Test that an error is thrown when providing invalid icon sizes
add_task(function* testInvalidIconSizes() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"browser_action": {},
"page_action": {},
},
background: function() {
browser.tabs.query({active: true, currentWindow: true}, tabs => {
let tabId = tabs[0].id;
let promises = [];
for (let api of ["pageAction", "browserAction"]) {
// helper function to run setIcon and check if it fails
let assertSetIconThrows = function(detail, error, message) {
detail.tabId = tabId;
promises.push(
browser[api].setIcon(detail).then(
() => {
browser.test.fail("Expected an error on invalid icon size.");
browser.test.notifyFail("setIcon with invalid icon size");
},
error => {
browser.test.succeed("setIcon with invalid icon size");
}));
};
let imageData = new ImageData(1, 1);
// test invalid icon size inputs
for (let type of ["path", "imageData"]) {
let img = type == "imageData" ? imageData : "test.png";
assertSetIconThrows({[type]: {"abcdef": img}});
assertSetIconThrows({[type]: {"48px": img}});
assertSetIconThrows({[type]: {"20.5": img}});
assertSetIconThrows({[type]: {"5.0": img}});
assertSetIconThrows({[type]: {"-300": img}});
assertSetIconThrows({[type]: {"abc": img, "5": img}});
}
assertSetIconThrows({imageData: {"abcdef": imageData}, path: {"5": "test.png"}});
assertSetIconThrows({path: {"abcdef": "test.png"}, imageData: {"5": imageData}});
}
Promise.all(promises).then(() => {
browser.test.notifyPass("setIcon with invalid icon size");
});
});
},
});
yield Promise.all([extension.startup(), extension.awaitFinish("setIcon with invalid icon size")]);
yield extension.unload();
});
// Test that default icon details in the manifest.json file are handled
// correctly.
add_task(function* testDefaultDetails() {
// TODO: Test localized variants.
let icons = [
"foo/bar.png",
"/foo/bar.png",
{"19": "foo/bar.png"},
{"38": "foo/bar.png"},
{"19": "foo/bar.png", "38": "baz/quux.png"},
];
let expectedURL = new RegExp(String.raw`^moz-extension://[^/]+/foo/bar\.png$`);
for (let icon of icons) {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"browser_action": {"default_icon": icon},
"page_action": {"default_icon": icon},
},
background: function() {
browser.tabs.query({active: true, currentWindow: true}, tabs => {
let tabId = tabs[0].id;
browser.pageAction.show(tabId).then(() => {
browser.test.sendMessage("ready");
});
});
},
files: {
"foo/bar.png": imageBuffer,
"baz/quux.png": imageBuffer,
},
});
yield Promise.all([extension.startup(), extension.awaitMessage("ready")]);
let browserActionId = makeWidgetId(extension.id) + "-browser-action";
let pageActionId = makeWidgetId(extension.id) + "-page-action";
let browserActionButton = document.getElementById(browserActionId);
let image = getListStyleImage(browserActionButton);
ok(expectedURL.test(image), `browser action image ${image} matches ${expectedURL}`);
let pageActionImage = document.getElementById(pageActionId);
image = getListStyleImage(pageActionImage);
ok(expectedURL.test(image), `page action image ${image} matches ${expectedURL}`);
yield extension.unload();
let node = document.getElementById(pageActionId);
is(node, null, "pageAction image removed from document");
}
});
// Check that attempts to load a privileged URL as an icon image fail.
add_task(function* testSecureURLsDenied() {
// Test URLs passed to setIcon.
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"browser_action": {},
"page_action": {},
},
background: function() {
browser.tabs.query({active: true, currentWindow: true}, tabs => {
let tabId = tabs[0].id;
let urls = ["chrome://browser/content/browser.xul",
"javascript:true"];
let promises = [];
for (let url of urls) {
for (let api of ["pageAction", "browserAction"]) {
promises.push(
browser[api].setIcon({tabId, path: url}).then(
() => {
browser.test.fail(`Load of '${url}' succeeded. Expected failure.`);
browser.test.notifyFail("setIcon security tests");
},
error => {
browser.test.succeed(`Load of '${url}' failed. Expected failure. ${error}`);
}));
}
}
Promise.all(promises).then(() => {
browser.test.notifyPass("setIcon security tests");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("setIcon security tests");
yield extension.unload();
});
add_task(function* testSecureManifestURLsDenied() {
// Test URLs included in the manifest.
let urls = ["chrome://browser/content/browser.xul",
"javascript:true"];
let apis = ["browser_action", "page_action"];
for (let url of urls) {
for (let api of apis) {
info(`TEST ${api} icon url: ${url}`);
let matchURLForbidden = url => ({
message: new RegExp(`match the format "strictRelativeUrl"`),
});
let messages = [matchURLForbidden(url)];
let waitForConsole = new Promise(resolve => {
// Not necessary in browser-chrome tests, but monitorConsole gripes
// if we don't call it.
SimpleTest.waitForExplicitFinish();
SimpleTest.monitorConsole(resolve, messages);
});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
[api]: {
"default_icon": url,
},
},
});
yield Assert.rejects(extension.startup(),
null,
"Manifest rejected");
SimpleTest.endMonitorConsole();
yield waitForConsole;
}
}
});

Просмотреть файл

@ -0,0 +1,147 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
function* awaitPanel(extension, win = window) {
let {target} = yield BrowserTestUtils.waitForEvent(win.document, "load", true, (event) => {
return event.target.location && event.target.location.href.endsWith("popup.html");
});
return target.defaultView
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDocShell)
.chromeEventHandler;
}
function* awaitResize(browser) {
// Debouncing code makes this a bit racy.
// Try to skip the first, early resize, and catch the resize event we're
// looking for, but don't wait longer than a few seconds.
return Promise.race([
BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized")
.then(() => BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized")),
new Promise(resolve => setTimeout(resolve, 5000)),
]);
}
add_task(function* testPopupBackground() {
let extension = ExtensionTestUtils.loadExtension({
background() {
browser.tabs.query({active: true, currentWindow: true}, tabs => {
browser.pageAction.show(tabs[0].id);
});
},
manifest: {
"browser_action": {
"default_popup": "popup.html",
"browser_style": false,
},
"page_action": {
"default_popup": "popup.html",
"browser_style": false,
},
},
files: {
"popup.html": `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body style="width: 100px; height: 100px; background-color: green;">
</body>
</html>`,
},
});
yield extension.startup();
function* testPanel(browser, standAlone) {
let panel = getPanelForNode(browser);
let arrowContent = document.getAnonymousElementByAttribute(panel, "class", "panel-arrowcontent");
let arrow = document.getAnonymousElementByAttribute(panel, "anonid", "arrow");
let borderColor = getComputedStyle(arrowContent).borderTopColor;
let checkArrow = (background = null) => {
let image = getComputedStyle(arrow).listStyleImage;
if (background == null || !standAlone) {
ok(image.startsWith('url("chrome://'), `We should have the built-in background image (got: ${image})`);
return;
}
if (AppConstants.platform == "mac") {
// Panels have a drop shadow rather than a border on OS-X, so we extend
// the background color through the border area instead.
borderColor = background;
}
image = decodeURIComponent(image);
let borderIndex = image.indexOf(`fill="${borderColor}"`);
let backgroundIndex = image.lastIndexOf(`fill="${background}"`);
ok(borderIndex >= 0, `Have border fill (index=${borderIndex})`);
ok(backgroundIndex >= 0, `Have background fill (index=${backgroundIndex})`);
is(getComputedStyle(arrowContent).backgroundColor, background, "Arrow content should have correct background");
isnot(borderIndex, backgroundIndex, "Border and background fills are separate elements");
};
let win = browser.contentWindow;
let body = win.document.body;
yield new Promise(resolve => setTimeout(resolve, 100));
info("Test that initial background color is applied");
checkArrow(win.getComputedStyle(body).backgroundColor);
info("Test that dynamically-changed background color is applied");
body.style.backgroundColor = "black";
yield awaitResize(browser);
checkArrow(win.getComputedStyle(body).backgroundColor);
info("Test that non-opaque background color results in default styling");
body.style.backgroundColor = "rgba(1, 2, 3, .9)";
yield awaitResize(browser);
checkArrow(null);
}
{
info("Test stand-alone browserAction popup");
clickBrowserAction(extension);
let browser = yield awaitPanel(extension);
yield testPanel(browser, true);
yield closeBrowserAction(extension);
}
{
info("Test menu panel browserAction popup");
let widget = getBrowserActionWidget(extension);
CustomizableUI.addWidgetToArea(widget.id, CustomizableUI.AREA_PANEL);
clickBrowserAction(extension);
let browser = yield awaitPanel(extension);
yield testPanel(browser, false);
yield closeBrowserAction(extension);
}
{
info("Test pageAction popup");
clickPageAction(extension);
let browser = yield awaitPanel(extension);
yield testPanel(browser, true);
yield closePageAction(extension);
}
yield extension.unload();
});

Просмотреть файл

@ -1,3 +1,5 @@
requestLongerTimeout(2);
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader);
let rootDir = getRootDirectory(gTestPath);

Просмотреть файл

@ -32,11 +32,9 @@
--toolbarbutton-checkedhover-backgroundcolor: rgba(200,200,200,.5);
--identity-box-verified-background-color: #fff;
--panel-separator-color: ThreeDShadow;
--urlbar-separator-color: hsla(0,0%,16%,.2);
--urlbar-separator-color: ThreeDShadow;
}
#menubar-items {
@ -817,6 +815,15 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
opacity: 0.4;
}
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"] > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"] > .toolbarbutton-badge-stack > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
toolbaritem[cui-areatype="menu-panel"] > :-moz-any(@nestedButtons@) > .toolbarbutton-icon {
filter: url(chrome://browser/skin/filters.svg#fill);
fill: currentColor;
opacity: 0.7 !important; /* !important overrides .toolbarbutton-1[disabled=true] rule */
}
/* Fullscreen window controls */
#window-controls {
-moz-box-align: start;
@ -985,7 +992,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
}
#urlbar-search-footer {
border-top: 1px solid hsla(210,4%,10%,.14);
border-top: 1px solid var(--panel-separator-color);
background-color: hsla(210,4%,10%,.07);
}
@ -1047,10 +1054,6 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
border-bottom-right-radius: 1.5px;
}
#identity-box.verifiedIdentity:not(:-moz-lwtheme):not(:hover):not([open=true]) {
background-color: var(--identity-box-verified-background-color);
}
#identity-box:-moz-focusring {
outline: 1px dotted #000;
outline-offset: -3px;
@ -1993,14 +1996,9 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton:not(:h
}
.webextension-popup-browser {
margin-right: -1px;
border-radius: inherit;
}
#PanelUI-popup .webextension-popup-browser {
margin: 0;
}
.menuitem-iconic[usercontextid] > .menu-iconic-left > .menu-iconic-icon {
visibility: visible;
}

Просмотреть файл

@ -93,14 +93,6 @@ menu.subviewbutton > .menu-right:-moz-locale-dir(rtl) {
margin-bottom: 2px !important;
}
.PanelUI-subView toolbarseparator,
.PanelUI-subView menuseparator,
.cui-widget-panelview menuseparator,
#PanelUI-footer-inner > toolbarseparator,
#PanelUI-footer-fxa > toolbarseparator {
-moz-appearance: none !important;
}
.subviewradio > .radio-label-box {
-moz-appearance: none;
}

Двоичные данные
browser/themes/linux/menuPanel.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 18 KiB

После

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичные данные
browser/themes/linux/menuPanel@2x.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

После

Ширина:  |  Высота:  |  Размер: 38 KiB

Просмотреть файл

@ -744,6 +744,13 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
%include ../shared/toolbarbuttons.inc.css
%include ../shared/menupanel.inc.css
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-badge-stack > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
filter: url(chrome://browser/skin/filters.svg#fill);
fill: currentColor;
}
@media not all and (min-resolution: 1.1dppx) {
#back-button:hover:active:not([disabled="true"]) {
-moz-image-region: rect(18px, 36px, 36px, 18px);
@ -1691,7 +1698,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
}
#urlbar-search-footer {
border-top: 1px solid hsla(210,4%,10%,.14);
border-top: 1px solid var(--panel-separator-color);
background-color: hsla(210,4%,10%,.07);
}
@ -3503,10 +3510,5 @@ menulist.translate-infobar-element > .menulist-dropmarker {
}
.webextension-popup-browser {
margin-right: -1px;
border-radius: inherit;
}
#PanelUI-popup .webextension-popup-browser {
margin: 0;
}

Двоичные данные
browser/themes/osx/menuPanel.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 33 KiB

После

Ширина:  |  Высота:  |  Размер: 37 KiB

Двоичные данные
browser/themes/osx/menuPanel@2x.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 75 KiB

После

Ширина:  |  Высота:  |  Размер: 84 KiB

Просмотреть файл

@ -144,7 +144,7 @@
.panel-subviews {
padding: 4px;
background-clip: padding-box;
border-left: 1px solid hsla(210,4%,10%,.3);
border-left: 1px solid var(--panel-separator-color);
box-shadow: 0 3px 5px hsla(210,4%,10%,.1),
0 0 7px hsla(210,4%,10%,.1);
margin-inline-start: var(--panel-ui-exit-subview-gutter-width);
@ -186,7 +186,7 @@ panelmultiview[nosubviews=true] > .panel-viewcontainer > .panel-viewstack > .pan
.panel-subview-header {
margin: -4px -4px 4px;
box-shadow: 0 -1px 0 hsla(210,4%,10%,.05) inset;
border-bottom: 1px solid var(--panel-separator-color);
color: GrayText;
font-variant: small-caps;
}
@ -577,7 +577,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
#PanelUI-footer-inner,
#PanelUI-footer-fxa:not([hidden]) {
display: flex;
border-top: 1px solid hsla(210,4%,10%,.14);
border-top: 1px solid var(--panel-separator-color);
}
#PanelUI-multiView[viewtype="subview"] #PanelUI-footer-inner,
@ -588,7 +588,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
#PanelUI-footer-inner > toolbarseparator,
#PanelUI-footer-fxa > toolbarseparator {
border: 0;
border-left: 1px solid hsla(210,4%,10%,.14);
border-left: 1px solid var(--panel-separator-color);
margin: 7px 0 7px;
-moz-appearance: none;
}
@ -617,7 +617,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
}
#PanelUI-update-status {
border-top: 1px solid hsla(210,4%,10%,.14);
border-top: 1px solid var(--panel-separator-color);
}
#PanelUI-update-status {
@ -1099,27 +1099,25 @@ menuitem.subviewbutton@menuStateActive@,
.widget-overflow-list .toolbarbutton-1@buttonStateActive@,
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton@buttonStateActive@ {
background-color: hsla(210,4%,10%,.12);
border-color: hsla(210,4%,10%,.14);
border-color: var(--panel-separator-color);
box-shadow: 0 1px 0 hsla(210,4%,10%,.03) inset;
}
.subviewbutton.panel-subview-footer {
margin: 4px -4px -4px;
background-color: hsla(210,4%,10%,.07);
border-top: 1px solid hsla(210,4%,10%,.12);
border-top: 1px solid var(--panel-separator-color);
border-radius: 0;
}
menuitem.panel-subview-footer@menuStateHover@,
.subviewbutton.panel-subview-footer@buttonStateHover@ {
background-color: hsla(210,4%,10%,.15);
border-top: 1px solid hsla(210,4%,10%,.14);
}
menuitem.panel-subview-footer@menuStateActive@,
.subviewbutton.panel-subview-footer@buttonStateActive@ {
background-color: hsla(210,4%,10%,.19);
border-top: 1px solid hsla(210,4%,10%,.14);
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}
@ -1522,23 +1520,21 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
-moz-box-align: center;
padding: 1px;
margin: 0 0 2px;
background-color: hsla(210,4%,10%,0);
background-color: transparent;
border-radius: 2px;
border-width: 1px;
border-style: solid;
border-color: hsla(210,4%,10%,0);
border: 1px solid transparent;
}
.subviewradio@buttonStateHover@ {
background-color: hsla(210,4%,10%,.08);
border-color: hsla(210,4%,10%,.11);
border-color: var(--panel-separator-color);
}
.subviewradio[selected],
.subviewradio[selected]:hover,
.subviewradio@buttonStateActive@ {
background-color: hsla(210,4%,10%,.12);
border-color: hsla(210,4%,10%,.14);
border-color: var(--panel-separator-color);
box-shadow: 0 1px 0 hsla(210,4%,10%,.03) inset;
}

Просмотреть файл

@ -60,7 +60,6 @@
:root[devtoolstheme="dark"] #identity-box {
--identity-box-chrome-color: #46afe3;
--identity-box-verified-background-color: transparent;
}
:root[devtoolstheme="light"] {

Просмотреть файл

@ -38,15 +38,15 @@
.downloadsPanelFooter {
background-color: hsla(210,4%,10%,.07);
border-top: 1px solid hsla(210,4%,10%,.14);
border-top: 1px solid var(--panel-separator-color);
}
.downloadsPanelFooter > toolbarseparator {
margin: 0;
border: 0;
min-width: 0;
border-left: 1px solid hsla(210,4%,10%,.14);
-moz-appearance: none !important;
border-left: 1px solid var(--panel-separator-color);
-moz-appearance: none;
}
.downloadsPanelFooterButton {

Просмотреть файл

@ -19,9 +19,9 @@
font-size: .9em;
padding: 3px 5px;
overflow: hidden;
/* The latter two properties have a transition to handle the delayed hiding of
/* The padding-left and padding-right transitions handle the delayed hiding of
the forward button when hovered. */
transition: background-color 150ms ease, padding-left, padding-right;
transition: padding-left, padding-right;
}
#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity {
@ -62,6 +62,9 @@
width: 16px;
height: 16px;
list-style-image: url(chrome://browser/skin/identity-icon.svg#normal);
filter: url(chrome://browser/skin/filters.svg#fill);
fill: currentColor;
opacity: .5;
}
#identity-box:hover > #identity-icon:not(.no-hover),
@ -80,10 +83,11 @@
#urlbar[pageproxystate="valid"] > #identity-box.chromeUI > #identity-icon {
list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
opacity: 1;
}
#urlbar[pageproxystate="invalid"] > #identity-box > #identity-icon {
opacity: 0.3;
opacity: .2;
}
#urlbar[actiontype="searchengine"] > #identity-box > #identity-icon {
@ -91,7 +95,7 @@
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon);
width: 16px;
height: 16px;
opacity: 1;
opacity: .5;
}
/* SHARING ICON */
@ -145,11 +149,15 @@
margin-inline-start: 2px;
margin-inline-end: 0;
list-style-image: url(chrome://browser/skin/tracking-protection-16.svg);
opacity: 1;
filter: url(chrome://browser/skin/filters.svg#fill);
fill: currentColor;
opacity: .5;
}
#tracking-protection-icon[state="loaded-tracking-content"] {
list-style-image: url(chrome://browser/skin/tracking-protection-disabled-16.svg);
filter: none;
opacity: 1;
}
#tracking-protection-icon[animate] {

Просмотреть файл

@ -8,7 +8,6 @@
<style>
path {
fill-rule: evenodd;
fill: #999999;
}
</style>
</defs>

До

Ширина:  |  Высота:  |  Размер: 1.9 KiB

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Просмотреть файл

@ -17,5 +17,5 @@
</mask>
</defs>
<use xlink:href="#shape-shield-outer" mask="url(#mask-shield-cutout)" fill="#808080" />
<use xlink:href="#shape-shield-outer" mask="url(#mask-shield-cutout)"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.3 KiB

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Просмотреть файл

@ -1,18 +1,11 @@
/* Menu panel and palette styles */
:root {
--menupanel-list-style-image: url(chrome://browser/skin/menuPanel.png);
--menupanel-list-style-image-2x: url(chrome://browser/skin/menuPanel@2x.png);
--menupanel-small-list-style-image: url(chrome://browser/skin/menuPanel-small.png);
--menupanel-small-list-style-image-2x: url(chrome://browser/skin/menuPanel-small@2x.png);
}
@media not all and (min-resolution: 1.1dppx) {
toolbaritem[sdkstylewidget="true"] > toolbarbutton,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > :-moz-any(@primaryToolbarButtons@) {
list-style-image: var(--menupanel-list-style-image);
list-style-image: url(chrome://browser/skin/menuPanel.png);
}
#home-button[cui-areatype="menu-panel"],
@ -25,19 +18,11 @@
-moz-image-region: rect(0px, 192px, 32px, 160px);
}
#bookmarks-menu-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 192px, 64px, 160px);
}
#history-panelmenu[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #history-panelmenu {
-moz-image-region: rect(0px, 224px, 32px, 192px);
}
#history-panelmenu[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 224px, 64px, 192px);
}
#downloads-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #downloads-button {
-moz-image-region: rect(0px, 256px, 32px, 224px);
@ -63,28 +48,16 @@
-moz-image-region: rect(0px, 1024px, 32px, 992px);
}
#sync-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 1024px, 64px, 992px);
}
#containers-panelmenu[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #containers-panelmenu {
-moz-image-region: rect(0px, 1056px, 32px, 1024px);
}
#containers-panelmenu[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 1056px, 64px, 1024px);
}
#feed-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #feed-button {
-moz-image-region: rect(0px, 416px, 32px, 384px);
}
#feed-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 416px, 64px, 384px);
}
#social-share-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #social-share-button {
-moz-image-region: rect(0px, 448px, 32px, 416px);
@ -95,10 +68,6 @@
-moz-image-region: rect(0px, 480px, 32px, 448px);
}
#characterencoding-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 480px, 64px, 448px);
}
#new-window-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #new-window-button {
-moz-image-region: rect(0px, 512px, 32px, 480px);
@ -139,10 +108,6 @@
-moz-image-region: rect(0px, 736px, 32px, 704px);
}
#developer-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 736px, 64px, 704px);
}
#preferences-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #preferences-button {
-moz-image-region: rect(0px, 768px, 32px, 736px);
@ -158,19 +123,11 @@
-moz-image-region: rect(0, 864px, 32px, 832px);
}
#sidebar-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 864px, 64px, 832px);
}
#panic-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #panic-button {
-moz-image-region: rect(0, 896px, 32px, 864px);
}
#panic-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(32px, 896px, 64px, 864px);
}
#webide-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #webide-button {
-moz-image-region: rect(0px, 960px, 32px, 928px);
@ -186,7 +143,7 @@
#zoom-controls@inAnyPanel@ > toolbarbutton,
toolbarpaletteitem[place="palette"] > #edit-controls > toolbarbutton,
toolbarpaletteitem[place="palette"] > #zoom-controls > toolbarbutton {
list-style-image: var(--menupanel-small-list-style-image);
list-style-image: url(chrome://browser/skin/menuPanel-small.png);
}
#edit-controls@inAnyPanel@ > #cut-button,
@ -225,7 +182,7 @@
toolbaritem[sdkstylewidget="true"] > toolbarbutton,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > :-moz-any(@primaryToolbarButtons@) {
list-style-image: var(--menupanel-list-style-image-2x);
list-style-image: url(chrome://browser/skin/menuPanel@2x.png);
}
#home-button[cui-areatype="menu-panel"],
@ -238,19 +195,11 @@
-moz-image-region: rect(0px, 384px, 64px, 320px);
}
#bookmarks-menu-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 384px, 128px, 320px);
}
#history-panelmenu[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #history-panelmenu {
-moz-image-region: rect(0px, 448px, 64px, 384px);
}
#history-panelmenu[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 448px, 128px, 384px);
}
#downloads-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #downloads-button {
-moz-image-region: rect(0px, 512px, 64px, 448px);
@ -276,28 +225,16 @@
-moz-image-region: rect(0px, 2048px, 64px, 1984px);
}
#sync-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 2048px, 128px, 1984px);
}
#containers-panelmenu[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #containers-panelmenu {
-moz-image-region: rect(0px, 2112px, 64px, 2048px);
}
#containers-panelmenu[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 2112px, 128px, 2048px);
}
#feed-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #feed-button {
-moz-image-region: rect(0px, 832px, 64px, 768px);
}
#feed-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 832px, 128px, 768px);
}
#social-share-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #social-share-button {
-moz-image-region: rect(0px, 896px, 64px, 832px);
@ -308,10 +245,6 @@
-moz-image-region: rect(0, 960px, 64px, 896px);
}
#characterencoding-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 960px, 128px, 896px);
}
#new-window-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #new-window-button {
-moz-image-region: rect(0px, 1024px, 64px, 960px);
@ -357,10 +290,6 @@
-moz-image-region: rect(0px, 1472px, 64px, 1408px);
}
#developer-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 1472px, 128px, 1408px);
}
#preferences-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #preferences-button {
-moz-image-region: rect(0px, 1536px, 64px, 1472px);
@ -376,19 +305,11 @@
-moz-image-region: rect(0px, 1728px, 64px, 1664px);
}
#sidebar-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 1728px, 128px, 1664px);
}
#panic-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #panic-button {
-moz-image-region: rect(0, 1792px, 64px, 1728px);
}
#panic-button[cui-areatype="menu-panel"][panel-multiview-anchor=true] {
-moz-image-region: rect(64px, 1792px, 128px, 1728px);
}
toolbaritem[sdkstylewidget="true"] > toolbarbutton {
-moz-image-region: rect(0, 1664px, 64px, 1600px);
}
@ -398,7 +319,7 @@
#zoom-controls@inAnyPanel@ > toolbarbutton,
toolbarpaletteitem[place="palette"] > #edit-controls > toolbarbutton,
toolbarpaletteitem[place="palette"] > #zoom-controls > toolbarbutton {
list-style-image: var(--menupanel-small-list-style-image-2x);
list-style-image: url(chrome://browser/skin/menuPanel-small@2x.png);
}
/* Wide items like the Cut/Copy/Paste and Zoom controls are special in that their icons

Просмотреть файл

@ -41,12 +41,6 @@
margin-inline-end: 10px;
}
#notification-popup-box > .notification-anchor-icon:hover {
fill: #606060;
}
/* INDIVIDUAL NOTIFICATIONS */
.camera-icon,
.geo-icon,
.indexedDB-icon,
@ -67,9 +61,16 @@
.popup-notification-icon[popupid="webRTC-shareScreen"],
.popup-notification-icon[popupid="web-notifications"] {
filter: url(chrome://browser/skin/filters.svg#fill);
fill: #999;
fill: currentColor;
opacity: .4;
}
.notification-anchor-icon:hover {
opacity: .6;
}
/* INDIVIDUAL NOTIFICATIONS */
.popup-notification-icon[popupid="web-notifications"],
.desktop-notification-icon {
list-style-image: url(chrome://browser/skin/notification-icons.svg#desktop-notification);
@ -252,7 +253,8 @@
.plugin-icon.plugin-blocked {
list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin-blocked);
fill: #d92215 !important; /* important! to override the default hover color */
fill: #d92215;
opacity: 1 !important; /* !important to override the default hover opacity */
}
#notification-popup-box[hidden] {

Просмотреть файл

@ -36,8 +36,6 @@
--toolbarbutton-checkedhover-backgroundcolor: rgba(0,0,0,.1);
--identity-box-verified-background-color: #fff;
--urlbar-dropmarker-url: url("chrome://browser/skin/urlbar-history-dropmarker.png");
--urlbar-dropmarker-region: rect(0px, 11px, 14px, 0px);
--urlbar-dropmarker-hover-region: rect(0px, 22px, 14px, 11px);
@ -49,7 +47,7 @@
--panel-separator-color: ThreeDLightShadow;
--urlbar-separator-color: hsla(0,0%,16%,.2);
--urlbar-separator-color: ThreeDLightShadow;
}
#nav-bar[brighttext] {
@ -659,7 +657,6 @@ menuitem.bookmark-item {
/* ::::: primary toolbar buttons ::::: */
%include ../shared/toolbarbuttons.inc.css
%include ../shared/menupanel.inc.css
@media (-moz-windows-theme: luna-silver) and (max-resolution: 1dppx) {
:-moz-any(@primaryToolbarButtons@),
@ -702,6 +699,28 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
max-width: 18px;
}
%include ../shared/menupanel.inc.css
@media (-moz-windows-default-theme) {
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-badge-stack > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
filter: url(chrome://browser/skin/filters.svg#fill);
fill: currentColor;
}
}
@media not all and (-moz-windows-default-theme) {
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"] > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"] > .toolbarbutton-badge-stack > .toolbarbutton-icon,
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
toolbaritem[cui-areatype="menu-panel"] > :-moz-any(@nestedButtons@) > .toolbarbutton-icon {
filter: url(chrome://browser/skin/filters.svg#fill);
fill: currentColor;
opacity: 0.7 !important; /* !important overrides .toolbarbutton-1[disabled=true] rule */
}
}
.findbar-button,
#nav-bar .toolbarbutton-1,
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button {
@ -1409,7 +1428,7 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
}
#urlbar-search-footer {
border-top: 1px solid hsla(210,4%,10%,.14);
border-top: 1px solid var(--panel-separator-color);
background-color: hsla(210,4%,10%,.07);
}
@ -1457,10 +1476,6 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
/* identity box */
#identity-box.verifiedIdentity:not(:-moz-lwtheme):not(:hover):not([open=true]) {
background-color: var(--identity-box-verified-background-color);
}
#identity-box:-moz-focusring {
outline: 1px dotted #000;
outline-offset: -3px;
@ -2765,10 +2780,5 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton {
}
.webextension-popup-browser {
margin-right: -1px;
border-radius: inherit;
}
#PanelUI-popup .webextension-popup-browser {
margin: 0;
}

Двоичные данные
browser/themes/windows/menuPanel-aero.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 36 KiB

После

Ширина:  |  Высота:  |  Размер: 40 KiB

Двоичные данные
browser/themes/windows/menuPanel-aero@2x.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 97 KiB

После

Ширина:  |  Высота:  |  Размер: 100 KiB

Двоичные данные
browser/themes/windows/menuPanel.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 18 KiB

После

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичные данные
browser/themes/windows/menuPanel@2x.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 42 KiB

После

Ширина:  |  Высота:  |  Размер: 38 KiB

Просмотреть файл

@ -51,6 +51,8 @@ SEARCH_PATHS = [
'python/pyyaml/lib',
'python/requests',
'python/slugid',
'python/py',
'python/pytest',
'python/voluptuous',
'build',
'build/pymake',

Просмотреть файл

@ -14,9 +14,7 @@ js_option('--with-android-toolchain', nargs=1,
js_option('--with-android-gnu-compiler-version', nargs=1,
help='GNU compiler version to use')
@depends('--help')
def min_android_version(_):
return '9'
min_android_version = dependable('9')
js_option('--with-android-version',
nargs=1,

Просмотреть файл

@ -93,7 +93,6 @@ def checking(what, callback=None):
# use that value instead.
@template
@imports(_from='mozbuild.shellutil', _import='quote')
@imports(_from='mozbuild.configure', _import='DependsFunction')
def check_prog(var, progs, what=None, input=None, allow_missing=False,
paths=None):
if input:
@ -115,10 +114,8 @@ def check_prog(var, progs, what=None, input=None, allow_missing=False,
what = what or var.lower()
# Trick to make a @depends function out of an immediate value.
if not isinstance(progs, DependsFunction):
progs = depends('--help')(lambda h: progs)
if not isinstance(paths, DependsFunction):
paths = depends('--help')(lambda h: paths)
progs = dependable(progs)
paths = dependable(paths)
@depends_if(input, progs, paths)
@checking('for %s' % what, lambda x: quote(x) if x else 'not found')

Просмотреть файл

@ -44,7 +44,7 @@ def try_compile(includes=None, body='', language='C++', flags=None, check_msg=No
# conditional on the value of that function.
@template
def check_header(header, language='C++', flags=None, includes=None, when=None):
when = when or depends('--help')(lambda _: True)
when = when or always
if includes:
includes = includes[:]
@ -55,8 +55,7 @@ def check_header(header, language='C++', flags=None, includes=None, when=None):
@depends_when(try_compile(includes=includes, language=language, flags=flags,
check_msg='for %s' % header), when=when)
def have_header(value):
if value is not None:
return True
return value
header_var = 'HAVE_%s' % (header.upper()
.replace('-', '_')
.replace('/', '_')
@ -104,8 +103,7 @@ def check_and_add_gcc_warning(warning, compiler=None, when=None, check=True):
else:
compilers = (c_compiler, cxx_compiler)
if not when:
when = depends('--help')(lambda _: True)
when = when or always
for c in compilers:
assert c in (c_compiler, cxx_compiler)
@ -140,7 +138,7 @@ def check_and_add_gcc_warning(warning, compiler=None, when=None, check=True):
@depends(result, warnings_flags)
def maybe_add_flag(result, warnings_flags):
if result is not None:
if result:
warnings_flags.append(warning)
# Add the given warning to the list of warning flags for the build.

Просмотреть файл

@ -38,8 +38,7 @@ def compiler_class(compiler):
if check_msg:
def checking_fn(fn):
return checking(check_msg,
callback=lambda r: r is not None)(fn)
return checking(check_msg)(fn)
else:
def checking_fn(fn):
return fn
@ -55,9 +54,11 @@ def compiler_class(compiler):
flags += extra_flags
flags.append('-c')
return try_invoke_compiler(
if try_invoke_compiler(
compiler.wrapper + [compiler.compiler] + compiler.flags,
compiler.language, source, flags, onerror=onerror)
compiler.language, source, flags,
onerror=onerror) is not None:
return True
return func

Просмотреть файл

@ -125,21 +125,18 @@ set_config('MOZCONFIG', depends(mozconfig)(lambda m: m['path']))
# Hacks related to old-configure
# ==============================
@depends('--help')
def old_configure_assignments(help):
@dependable
def old_configure_assignments():
return []
@depends('--help')
def extra_old_configure_args(help):
@dependable
def extra_old_configure_args():
return []
@template
@imports(_from='mozbuild.configure', _import='DependsFunction')
def add_old_configure_assignment(var, value):
if not isinstance(var, DependsFunction):
var = depends('--help')(lambda x: var)
if not isinstance(value, DependsFunction):
value = depends('--help')(lambda x: value)
var = dependable(var)
value = dependable(value)
@depends(old_configure_assignments, var, value)
@imports(_from='mozbuild.shellutil', _import='quote')
@ -248,9 +245,9 @@ add_old_configure_assignment('PYTHON', virtualenv_python)
# below, so collect them.
@template
def early_options():
@depends('--help')
@dependable
@imports('__sandbox__')
def early_options(help):
def early_options():
return set(
option.env
for option in __sandbox__._options.itervalues()
@ -324,6 +321,7 @@ option('--target', nargs=1,
'used')
@imports(_from='mozbuild.configure.constants', _import='CPU')
@imports(_from='mozbuild.configure.constants', _import='CPU_bitness')
@imports(_from='mozbuild.configure.constants', _import='Endianness')
@imports(_from='mozbuild.configure.constants', _import='Kernel')
@imports(_from='mozbuild.configure.constants', _import='OS')
@ -422,6 +420,7 @@ def split_triplet(triplet):
return namespace(
alias=triplet,
cpu=CPU(canonical_cpu),
bitness=CPU_bitness[canonical_cpu],
kernel=Kernel(canonical_kernel),
os=OS(canonical_os),
endianness=Endianness(endianness),
@ -472,6 +471,16 @@ set_define('CROSS_COMPILE', cross_compiling)
add_old_configure_assignment('CROSS_COMPILE', cross_compiling)
@depends(target)
def have_64_bit(target):
if target.bitness == 64:
return True
set_config('HAVE_64BIT_BUILD', have_64_bit)
set_define('HAVE_64BIT_BUILD', have_64_bit)
add_old_configure_assignment('HAVE_64BIT_BUILD', have_64_bit)
# Autoconf needs these set
@depends(host)
def host_for_old_configure(host):
@ -804,8 +813,8 @@ add_old_configure_assignment('PKG_CONFIG', pkg_config)
# actual implementation is located in b2g/moz.configure.
# Remove this function as soon as 'android_ndk_include'
# depends on 'target.'
@depends('--help')
def gonkdir(_):
@dependable
def gonkdir():
return None
include(include_project_configure)

Просмотреть файл

@ -145,8 +145,8 @@ def old_configure_options(*options):
for opt in options:
option(opt, nargs='*', help='Help missing for old configure options')
@depends('--help')
def all_options(help):
@dependable
def all_options():
return list(options)
return depends(prepare_configure, extra_old_configure_args, all_options,
@ -181,7 +181,6 @@ def old_configure_options(*options):
'--enable-faststripe',
'--enable-feeds',
'--enable-gamepad',
'--enable-gc-trace',
'--enable-gconf',
'--enable-gczeal',
'--enable-gio',
@ -203,7 +202,6 @@ def old_configure_options(*options):
'--enable-media-navigator',
'--enable-memory-sanitizer',
'--enable-mobile-optimize',
'--enable-more-deterministic',
'--enable-mozril-geoloc',
'--enable-necko-protocols',
'--enable-necko-wifi',
@ -215,7 +213,6 @@ def old_configure_options(*options):
'--enable-oom-breakpoint',
'--enable-optimize',
'--enable-parental-controls',
'--enable-perf',
'--enable-permissions',
'--enable-pie',
'--enable-png-arm-neon-support',
@ -438,10 +435,10 @@ def post_old_configure(raw_config):
# them. We only do so for options that haven't been declared so far,
# which should be a proxy for the options that old-configure handles
# and that we don't know anything about.
@depends('--help')
@dependable
@imports('__sandbox__')
@imports(_from='mozbuild.configure.options', _import='Option')
def remaining_mozconfig_options(_):
def remaining_mozconfig_options():
helper = __sandbox__._helper
for arg in helper:
if helper._origins[arg] != 'mozconfig':

Просмотреть файл

@ -25,14 +25,11 @@ def pkg_config_version(pkg_config):
# will be returned to the caller.
# Returns `True` when the package description is fulfilled.
@template
@imports(_from='mozbuild.configure', _import='DependsFunction')
def pkg_check_modules(var, package_desc,
condition=depends('--help')(lambda _: True),
def pkg_check_modules(var, package_desc, condition=always,
allow_missing=False):
if isinstance(package_desc, (tuple, list)):
package_desc = ' '.join(package_desc)
if not isinstance(package_desc, DependsFunction):
package_desc = depends('--help')(lambda _: package_desc)
package_desc = dependable(package_desc)
@depends_when(pkg_config, pkg_config_version, when=condition)
def check_pkg_config(pkg_config, version):

Просмотреть файл

@ -62,8 +62,8 @@ set_config('HAVE_YASM', have_yasm)
# Until the YASM variable is not necessary in old-configure.
add_old_configure_assignment('YASM', have_yasm)
@depends('--help')
def extra_toolchain_flags(_):
@dependable
def extra_toolchain_flags():
# This value will be overriden for android builds, where
# extra flags are required to do basic checks.
return []
@ -766,6 +766,15 @@ host_cxx_compiler = compiler('C++', host, c_compiler=host_c_compiler,
include('compile-checks.configure')
@depends(have_64_bit,
try_compile(body='static_assert(sizeof(void *) == 8, "")',
check_msg='for 64-bit OS'))
def check_have_64_bit(have_64_bit, compiler_have_64_bit):
if have_64_bit != compiler_have_64_bit:
configure_error('The target compiler does not agree with configure '
'about the target bitness.')
@depends(c_compiler)
def default_debug_flags(compiler_info):
# Debug info is ON by default.

Просмотреть файл

@ -302,6 +302,24 @@ def namespace(**kwargs):
return ReadOnlyNamespace(**kwargs)
# Turn an object into an object that can be used as an argument to @depends.
# The given object can be a literal value, a function that takes no argument,
# or, for convenience, a @depends function.
@template
@imports(_from='inspect', _import='isfunction')
@imports(_from='mozbuild.configure', _import='DependsFunction')
def dependable(obj):
if isinstance(obj, DependsFunction):
return obj
if isfunction(obj):
return depends('--help')(lambda _: obj())
return depends('--help')(lambda _: obj)
always = dependable(True)
never = dependable(False)
# Some @depends function return namespaces, and one could want to use one
# specific attribute from such a namespace as a "value" given to functions
# such as `set_config`. But those functions do not take immediate values.

Просмотреть файл

@ -57,7 +57,7 @@ if __name__ == '__main__':
env["XPCOM_DEBUG_BREAK"] = "warn"
# For VC12+, make sure we can find the right bitness of pgort1x0.dll
if not substs['HAVE_64BIT_BUILD']:
if not substs.get('HAVE_64BIT_BUILD'):
for e in ('VS140COMNTOOLS', 'VS120COMNTOOLS'):
if e not in env:
continue

Просмотреть файл

@ -16,6 +16,8 @@ which.pth:python/which
ply.pth:other-licenses/ply/
macholib.pth:python/macholib
mock.pth:python/mock-1.0.0
py.pth:python/py
pytest.pth:python/pytest
mozilla.pth:build
mozilla.pth:config
mozilla.pth:xpcom/typelib/xpt/tools

Просмотреть файл

@ -586,6 +586,22 @@ BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
return NS_OK;
}
bool
BasePrincipal::AddonHasPermission(const nsAString& aPerm)
{
if (mOriginAttributes.mAddonId.IsEmpty()) {
return false;
}
nsCOMPtr<nsIAddonPolicyService> aps =
do_GetService("@mozilla.org/addons/policy-service;1");
NS_ENSURE_TRUE(aps, false);
bool retval = false;
nsresult rv = aps->AddonHasPermission(mOriginAttributes.mAddonId, aPerm, &retval);
NS_ENSURE_SUCCESS(rv, false);
return retval;
}
already_AddRefed<BasePrincipal>
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs)
{

Просмотреть файл

@ -266,6 +266,8 @@ public:
NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
virtual bool AddonHasPermission(const nsAString& aPerm);
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
virtual bool IsCodebasePrincipal() const { return false; };

Просмотреть файл

@ -40,6 +40,11 @@ interface nsIAddonPolicyService : nsISupports
*/
ACString getGeneratedBackgroundPageUrl(in ACString aAddonId);
/**
* Returns true if the addon was granted the |aPerm| API permission.
*/
boolean addonHasPermission(in AString aAddonId, in AString aPerm);
/**
* Returns true if unprivileged code associated with the given addon may load
* data from |aURI|.

Просмотреть файл

@ -786,6 +786,17 @@ nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
return NS_ERROR_NOT_AVAILABLE;
}
bool
nsExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
{
for (size_t i = 0; i < mPrincipals.Length(); ++i) {
if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
return true;
}
}
return false;
}
bool
nsExpandedPrincipal::IsOnCSSUnprefixingWhitelist()
{

Просмотреть файл

@ -71,14 +71,15 @@ public:
NS_DECL_NSIEXPANDEDPRINCIPAL
NS_DECL_NSISERIALIZABLE
NS_IMETHODIMP_(MozExternalRefCountType) AddRef() override { return nsJSPrincipals::AddRef(); };
NS_IMETHODIMP_(MozExternalRefCountType) Release() override { return nsJSPrincipals::Release(); };
NS_IMETHOD_(MozExternalRefCountType) AddRef() override { return nsJSPrincipals::AddRef(); };
NS_IMETHOD_(MozExternalRefCountType) Release() override { return nsJSPrincipals::Release(); };
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
NS_IMETHOD GetURI(nsIURI** aURI) override;
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool AddonHasPermission(const nsAString& aPerm) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
virtual void GetScriptLocation(nsACString &aStr) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;

Просмотреть файл

@ -76,7 +76,7 @@ using namespace mozilla::dom;
nsIIOService *nsScriptSecurityManager::sIOService = nullptr;
nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr;
JSRuntime *nsScriptSecurityManager::sRuntime = 0;
JSContext *nsScriptSecurityManager::sContext = nullptr;
bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
///////////////////////////
@ -1413,19 +1413,18 @@ nsresult nsScriptSecurityManager::Init()
//-- Register security check callback in the JS engine
// Currently this is used to control access to function.caller
sRuntime = xpc::GetJSRuntime();
sContext = danger::GetJSContext();
static const JSSecurityCallbacks securityCallbacks = {
ContentSecurityPolicyPermitsJSAction,
JSPrincipalsSubsume,
};
JSContext* cx = JS_GetContext(sRuntime);
MOZ_ASSERT(!JS_GetSecurityCallbacks(cx));
JS_SetSecurityCallbacks(cx, &securityCallbacks);
JS_InitDestroyPrincipalsCallback(cx, nsJSPrincipals::Destroy);
MOZ_ASSERT(!JS_GetSecurityCallbacks(sContext));
JS_SetSecurityCallbacks(sContext, &securityCallbacks);
JS_InitDestroyPrincipalsCallback(sContext, nsJSPrincipals::Destroy);
JS_SetTrustedPrincipals(cx, system);
JS_SetTrustedPrincipals(sContext, system);
return NS_OK;
}
@ -1448,10 +1447,10 @@ nsScriptSecurityManager::~nsScriptSecurityManager(void)
void
nsScriptSecurityManager::Shutdown()
{
if (sRuntime) {
JS_SetSecurityCallbacks(JS_GetContext(sRuntime), nullptr);
JS_SetTrustedPrincipals(JS_GetContext(sRuntime), nullptr);
sRuntime = nullptr;
if (sContext) {
JS_SetSecurityCallbacks(sContext, nullptr);
JS_SetTrustedPrincipals(sContext, nullptr);
sContext = nullptr;
}
NS_IF_RELEASE(sIOService);

Просмотреть файл

@ -148,7 +148,7 @@ private:
static nsIIOService *sIOService;
static nsIStringBundle *sStrBundle;
static JSRuntime *sRuntime;
static JSContext *sContext;
};
namespace mozilla {

Просмотреть файл

@ -17,9 +17,9 @@ function test() {
"-H 'Accept: */*'",
"-H 'Accept-Language: " + navigator.language + "'",
"--compressed",
"-H 'x-custom-header-1: Custom value'",
"-H 'x-custom-header-2: 8.8.8.8'",
"-H 'x-custom-header-3: Mon, 3 Mar 2014 11:11:11 GMT'",
"-H 'X-Custom-Header-1: Custom value'",
"-H 'X-Custom-Header-2: 8.8.8.8'",
"-H 'X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT'",
"-H 'Referer: " + CURL_URL + "'",
"-H 'Connection: keep-alive'",
"-H 'Pragma: no-cache'",
@ -34,9 +34,9 @@ function test() {
'-H "Accept: */*"',
'-H "Accept-Language: ' + navigator.language + '"',
"--compressed",
'-H "x-custom-header-1: Custom value"',
'-H "x-custom-header-2: 8.8.8.8"',
'-H "x-custom-header-3: Mon, 3 Mar 2014 11:11:11 GMT"',
'-H "X-Custom-Header-1: Custom value"',
'-H "X-Custom-Header-2: 8.8.8.8"',
'-H "X-Custom-Header-3: Mon, 3 Mar 2014 11:11:11 GMT"',
'-H "Referer: ' + CURL_URL + '"',
'-H "Connection: keep-alive"',
'-H "Pragma: no-cache"',

Просмотреть файл

@ -154,7 +154,7 @@ function testSentRequest(aData, aOrigData) {
is(aData.url, aOrigData.url + "&" + ADD_QUERY, "correct url in sent request");
let hasHeader = aData.requestHeaders.headers.some((header) => {
return (header.name.toLowerCase() + ": " + header.value) == ADD_HEADER.toLowerCase();
return (header.name + ": " + header.value) == ADD_HEADER;
});
ok(hasHeader, "new header added to sent request");

Просмотреть файл

@ -122,13 +122,19 @@ define(function (require, exports, module) {
let mode = this.props.mode || "short";
let object = this.props.object;
let items;
let brackets;
let needSpace = function (space) {
return space ? { left: "[ ", right: " ]"} : { left: "[", right: "]"};
};
if (mode == "tiny") {
let isEmpty = object.length === 0;
items = DOM.span({className: "length"}, isEmpty ? "" : object.length);
brackets = needSpace(false);
} else {
let max = (mode == "short") ? 3 : 300;
items = this.arrayIterator(object, max);
brackets = needSpace(items.length > 0);
}
let objectLink = this.props.objectLink || DOM.span;
@ -140,13 +146,13 @@ define(function (require, exports, module) {
className: "arrayLeftBracket",
role: "presentation",
object: object
}, "["),
}, brackets.left),
items,
objectLink({
className: "arrayRightBracket",
role: "presentation",
object: object
}, "]"),
}, brackets.right),
DOM.span({
className: "arrayProperties",
role: "group"}

Просмотреть файл

@ -105,14 +105,20 @@ define(function (require, exports, module) {
let object = this.props.object;
let items;
let brackets;
let needSpace = function (space) {
return space ? { left: "[ ", right: " ]"} : { left: "[", right: "]"};
};
if (mode == "tiny") {
let objectLength = this.getLength(object);
let isEmpty = objectLength === 0;
items = span({className: "length"}, isEmpty ? "" : objectLength);
brackets = needSpace(false);
} else {
let max = (mode == "short") ? 3 : 300;
items = this.arrayIterator(object, max);
brackets = needSpace(items.length > 0);
}
let objectLink = this.props.objectLink || span;
@ -126,13 +132,13 @@ define(function (require, exports, module) {
className: "arrayLeftBracket",
role: "presentation",
object: object
}, "["),
}, brackets.left),
items,
objectLink({
className: "arrayRightBracket",
role: "presentation",
object: object
}, "]"),
}, brackets.right),
span({
className: "arrayProperties",
role: "group"}

Просмотреть файл

@ -189,13 +189,13 @@ define(function (require, exports, module) {
className: "objectLeftBrace",
role: "presentation",
object: object
}, " {"),
}, " { "),
props,
objectLink({
className: "objectRightBrace",
role: "presentation",
object: object
}, "}")
}, " }")
)
);
},

Просмотреть файл

@ -150,13 +150,13 @@ define(function (require, exports, module) {
className: "objectLeftBrace",
role: "presentation",
object: object
}, "{"),
}, " { "),
props,
objectLink({
className: "objectRightBrace",
role: "presentation",
object: object
}, "}")
}, " }")
)
);
},

Просмотреть файл

@ -131,16 +131,6 @@
font-weight: bold;
}
.objectLeftBrace,
.arrayLeftBracket {
margin-right: 4px;
}
.objectRightBrace,
.arrayRightBracket {
margin-left: 4px;
}
/******************************************************************************/
/* Cycle reference*/

Просмотреть файл

@ -81,7 +81,7 @@ window.onload = Task.async(function* () {
function testMaxProps() {
const stub = [1, "foo", {}];
const defaultOutput = `[1, "foo", Object]`;
const defaultOutput = `[ 1, "foo", Object ]`;
const modeTests = [
{
@ -107,7 +107,7 @@ window.onload = Task.async(function* () {
function testMoreThanShortMaxProps() {
const stub = Array(maxLength.short + 1).fill("foo");
const defaultShortOutput = `[${Array(maxLength.short).fill("\"foo\"").join(", ")}, 1 more…]`;
const defaultShortOutput = `[ ${Array(maxLength.short).fill("\"foo\"").join(", ")}, 1 more… ]`;
const modeTests = [
{
@ -124,7 +124,7 @@ window.onload = Task.async(function* () {
},
{
mode: "long",
expectedOutput: `[${Array(maxLength.short + 1).fill("\"foo\"").join(", ")}]`,
expectedOutput: `[ ${Array(maxLength.short + 1).fill("\"foo\"").join(", ")} ]`,
}
];
@ -133,8 +133,8 @@ window.onload = Task.async(function* () {
function testMoreThanLongMaxProps() {
const stub = Array(maxLength.long + 1).fill("foo");
const defaultShortOutput = `[${Array(maxLength.short).fill("\"foo\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more…]`;
const defaultLongOutput = `[${Array(maxLength.long).fill("\"foo\"").join(", ")}, 1 more…]`;
const defaultShortOutput = `[ ${Array(maxLength.short).fill("\"foo\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more… ]`;
const defaultLongOutput = `[ ${Array(maxLength.long).fill("\"foo\"").join(", ")}, 1 more… ]`;
const modeTests = [
{
@ -161,7 +161,7 @@ window.onload = Task.async(function* () {
function testRecursiveArray() {
let stub = [1];
stub.push(stub);
const defaultOutput = `[1, […]]`;
const defaultOutput = `[ 1, […] ]`;
const modeTests = [
{
@ -194,7 +194,7 @@ window.onload = Task.async(function* () {
p4: "s4"
}
];
const defaultOutput = `[Object{p1: "s1", p3: "s3", p4: "s4", 1 more…}]`;
const defaultOutput = `[ Object { p1: "s1", p3: "s3", p4: "s4", 1 more… } ]`;
const modeTests = [
{
@ -224,10 +224,10 @@ window.onload = Task.async(function* () {
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
];
const defaultOutput = `["a", "b", "c", "d", "e", "f", "g", "h", "i", "j",` +
const defaultOutput = `[ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",` +
` "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",` +
` "u", "v", "w", "x", "y", "z"]`;
const shortOutput = `["a", "b", "c", 23 more…]`;
` "u", "v", "w", "x", "y", "z" ]`;
const shortOutput = `[ "a", "b", "c", 23 more… ]`;
const modeTests = [
{

Просмотреть файл

@ -78,7 +78,7 @@ window.onload = Task.async(function* () {
// Test array: `[1, "foo", {}]`;
const testName = "testMaxProps";
const defaultOutput = `Array[1, "foo", Object]`;
const defaultOutput = `Array[ 1, "foo", Object ]`;
const modeTests = [
{
@ -106,7 +106,7 @@ window.onload = Task.async(function* () {
// Test array = `["test string"…] //4 items`
const testName = "testMoreThanShortMaxProps";
const defaultOutput = `Array[${Array(maxLength.short).fill("\"test string\"").join(", ")}, 1 more…]`;
const defaultOutput = `Array[ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, 1 more… ]`;
const modeTests = [
{
@ -123,7 +123,7 @@ window.onload = Task.async(function* () {
},
{
mode: "long",
expectedOutput: `Array[${Array(maxLength.short + 1).fill("\"test string\"").join(", ")}]`,
expectedOutput: `Array[ ${Array(maxLength.short + 1).fill("\"test string\"").join(", ")} ]`,
}
];
@ -134,8 +134,8 @@ window.onload = Task.async(function* () {
// Test array = `["test string"…] //301 items`
const testName = "testMoreThanLongMaxProps";
const defaultShortOutput = `Array[${Array(maxLength.short).fill("\"test string\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more…]`;
const defaultLongOutput = `Array[${Array(maxLength.long).fill("\"test string\"").join(", ")}, 1 more…]`;
const defaultShortOutput = `Array[ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more… ]`;
const defaultLongOutput = `Array[ ${Array(maxLength.long).fill("\"test string\"").join(", ")}, 1 more… ]`;
const modeTests = [
{
@ -166,7 +166,7 @@ window.onload = Task.async(function* () {
// Test array = `let a = []; a = [a]`
const testName = "testRecursiveArray";
const defaultOutput = `Array[[1]]`;
const defaultOutput = `Array[ [1] ]`;
const modeTests = [
{
@ -193,7 +193,7 @@ window.onload = Task.async(function* () {
function testNamedNodeMap() {
const testName = "testNamedNodeMap";
const defaultOutput = `NamedNodeMap[class="myclass", cellpadding="7", border="3"]`;
const defaultOutput = `NamedNodeMap[ class="myclass", cellpadding="7", border="3" ]`;
const modeTests = [
{

Просмотреть файл

@ -75,7 +75,7 @@ window.onload = Task.async(function* () {
// Test object: `{a: "a", b: "b", c: "c"}`;
const testName = "testMaxProps";
const defaultOutput = `Object {a: "a", b: "b", c: "c"}`;
const defaultOutput = `Object { a: "a", b: "b", c: "c" }`;
const modeTests = [
{
@ -103,7 +103,7 @@ window.onload = Task.async(function* () {
// Test object = `{p0: "0", p1: "1", p2: "2", …, p100: "100"}`
const testName = "testMoreThanMaxProps";
const defaultOutput = `Object {p0: "0", p1: "1", p2: "2", 98 more…}`;
const defaultOutput = `Object { p0: "0", p1: "1", p2: "2", 98 more… }`;
// Generate string with 100 properties, which is the max limit
// for 'long' mode.
@ -112,7 +112,7 @@ window.onload = Task.async(function* () {
props += "p" + i + ": \"" + i + "\", ";
}
const longOutput = `Object {${props}1 more…}`;
const longOutput = `Object { ${props}1 more… }`;
const modeTests = [
{
@ -140,14 +140,14 @@ window.onload = Task.async(function* () {
// Test object: `{a: undefined, b: undefined, c: "c", d: 1}`
// @TODO This is not how we actually want the preview to be output.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1276376
const expectedOutput = `Object {a: undefined, b: undefined, c: "c", 1 more…}`;
const expectedOutput = `Object { a: undefined, b: undefined, c: "c", 1 more… }`;
}
function testNestedObject() {
// Test object: `{objProp: {id: 1}, strProp: "test string"}`
const testName = "testNestedObject";
const defaultOutput = `Object {objProp: Object, strProp: "test string"}`;
const defaultOutput = `Object { objProp: Object, strProp: "test string" }`;
const modeTests = [
{
@ -175,7 +175,7 @@ window.onload = Task.async(function* () {
// Test object: `{arrProp: ["foo", "bar", "baz"]}`
const testName = "testNestedArray";
const defaultOutput = `Object {arrProp: [3]}`;
const defaultOutput = `Object { arrProp: [3] }`;
const modeTests = [
{

Просмотреть файл

@ -72,7 +72,7 @@ window.onload = Task.async(function* () {
const testName = "testMaxProps";
const stub = {a: "a", b: "b", c: "c"};
const defaultOutput = `Object{a: "a", b: "b", c: "c"}`;
const defaultOutput = `Object { a: "a", b: "b", c: "c" }`;
const modeTests = [
{
@ -101,7 +101,7 @@ window.onload = Task.async(function* () {
for (let i = 0; i<100; i++) {
stub[`p${i}`] = i
}
const defaultOutput = `Object{p0: 0, p1: 1, p2: 2, 97 more…}`;
const defaultOutput = `Object { p0: 0, p1: 1, p2: 2, 97 more… }`;
const modeTests = [
{
@ -127,7 +127,7 @@ window.onload = Task.async(function* () {
function testUninterestingProps() {
const stub = {a:undefined, b:undefined, c:"c", d:0};
const defaultOutput = `Object{c: "c", d: 0, a: undefined, 1 more…}`;
const defaultOutput = `Object { c: "c", d: 0, a: undefined, 1 more… }`;
const modeTests = [
{
@ -160,7 +160,7 @@ window.onload = Task.async(function* () {
strProp: "test string",
arrProp: [1]
};
const defaultOutput = `Object{strProp: "test string", objProp: Object{id: 1, arr: [2]}, arrProp: [1]}`;
const defaultOutput = `Object { strProp: "test string", objProp: Object { id: 1, arr: [ 2 ] }, arrProp: [ 1 ] }`;
const modeTests = [
{

Просмотреть файл

@ -15,6 +15,9 @@ const PREF_INT = 64;
const PREF_BOOL = 128;
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
// We prefix all our local storage items with this.
const PREFIX = "Services.prefs:";
/**
* Create a new preference object.
*
@ -101,7 +104,7 @@ Preference.prototype = {
userValue: this.userValue,
};
localStorage.setItem(this.fullName, JSON.stringify(store));
localStorage.setItem(PREFIX + this.fullName, JSON.stringify(store));
this.branch._notify(this.name);
},
@ -249,9 +252,6 @@ PrefBranch.prototype = {
/** @see nsIPrefBranch.addObserver */
addObserver: function (domain, observer, holdWeak) {
if (domain !== "" && !domain.endsWith(".")) {
throw new Error("invalid domain to addObserver: " + domain);
}
if (holdWeak) {
throw new Error("shim prefs only supports strong observers");
}
@ -325,7 +325,8 @@ PrefBranch.prototype = {
*/
_notify: function (relativeName) {
for (let domain in this._observers) {
if (relativeName.startsWith(domain)) {
if (relativeName === domain || domain === "" ||
(domain.endsWith(".") && relativeName.startsWith(domain))) {
// Allow mutation while walking.
let localList = this._observers[domain].slice();
for (let observer of localList) {
@ -448,9 +449,12 @@ PrefBranch.prototype = {
// representations.
for (let i = 0; i < localStorage.length; ++i) {
let keyName = localStorage.key(i);
let {userValue, hasUserValue, defaultValue} =
JSON.parse(localStorage.getItem(keyName));
this._findOrCreatePref(keyName, userValue, hasUserValue, defaultValue);
if (keyName.startsWith(PREFIX)) {
let {userValue, hasUserValue, defaultValue} =
JSON.parse(localStorage.getItem(keyName));
this._findOrCreatePref(keyName.slice(PREFIX.length), userValue,
hasUserValue, defaultValue);
}
}
this._onStorageChange = this._onStorageChange.bind(this);

Просмотреть файл

@ -16,7 +16,7 @@ var exports = {}
var module = {exports};
// Add some starter prefs.
localStorage.setItem("devtools.branch1.somebool", JSON.stringify({
localStorage.setItem("Services.prefs:devtools.branch1.somebool", JSON.stringify({
// bool
type: 128,
defaultValue: false,
@ -24,7 +24,7 @@ localStorage.setItem("devtools.branch1.somebool", JSON.stringify({
userValue: false
}));
localStorage.setItem("devtools.branch1.somestring", JSON.stringify({
localStorage.setItem("Services.prefs:devtools.branch1.somestring", JSON.stringify({
// string
type: 32,
defaultValue: "dinosaurs",
@ -32,7 +32,7 @@ localStorage.setItem("devtools.branch1.somestring", JSON.stringify({
userValue: "elephants"
}));
localStorage.setItem("devtools.branch2.someint", JSON.stringify({
localStorage.setItem("Services.prefs:devtools.branch2.someint", JSON.stringify({
// string
type: 64,
defaultValue: -16,
@ -144,11 +144,11 @@ function do_tests() {
WrappedPrefs.setIntPref("devtools.branch2.someint", -93);
is(WrappedPrefs.getIntPref("devtools.branch2.someint"), -93, "set int pref");
WrappedPrefs.setCharPref("devtools.branch1.somestring", "hello");
ok(WrappedPrefs.getCharPref("devtools.branch1.somestring"), "hello",
is(WrappedPrefs.getCharPref("devtools.branch1.somestring"), "hello",
"set string pref");
Services.prefs.clearUserPref("devtools.branch1.somestring");
ok(Services.prefs.getCharPref("devtools.branch1.somestring"), "dinosaurs",
is(Services.prefs.getCharPref("devtools.branch1.somestring"), "dinosaurs",
"clear string pref");
ok(Services.prefs.prefHasUserValue("devtools.branch1.somebool"),
@ -168,9 +168,9 @@ function do_tests() {
Services.prefs.setCharPref("devtools.branch1.somestring", "octopus");
is(Services.prefs.getCharPref("devtools.branch1.somestring"), "octopus",
"set correctly via branch");
ok(branch0.getCharPref("devtools.branch1.somestring"), "octopus",
is(branch0.getCharPref("devtools.branch1.somestring"), "octopus",
"get via base branch");
ok(branch1.getCharPref("somestring"), "octopus", "get via branch");
is(branch1.getCharPref("somestring"), "octopus", "get via branch");
let notifications = {};
@ -181,14 +181,7 @@ function do_tests() {
}
};
try {
threw = false;
branch0.addObserver("devtools.branch1", null, null);
} catch (e) {
threw = true;
}
ok(threw, "invalid branch name to addObserver");
branch0.addObserver("devtools.branch1", null, null);
branch0.addObserver("devtools.branch1.", observer, false);
branch1.addObserver("", observer, false);
@ -209,6 +202,15 @@ function do_tests() {
"somestring": true
}, "removeObserver worked");
clearNotificationList();
branch0.addObserver("devtools.branch1.somestring", observer, false);
Services.prefs.setCharPref("devtools.branch1.somestring", "northern shoveler");
isDeeply(notifications, {
"devtools.branch1.somestring": true,
"somestring": true
}, "notifications sent to two listeners");
branch0.removeObserver("devtools.branch1.somestring", observer);
// Make sure we update if the pref change comes from somewhere else.
clearNotificationList();
pref("devtools.branch1.someotherstring", "lazuli bunting");

Просмотреть файл

@ -15,7 +15,6 @@
* (Telemetry.prototype._histograms):
* mytoolname: {
* histogram: "DEVTOOLS_MYTOOLNAME_OPENED_COUNT",
* userHistogram: "DEVTOOLS_MYTOOLNAME_OPENED_PER_USER_FLAG",
* timerHistogram: "DEVTOOLS_MYTOOLNAME_TIME_ACTIVE_SECONDS"
* },
*
@ -62,179 +61,142 @@ Telemetry.prototype = {
_histograms: {
toolbox: {
histogram: "DEVTOOLS_TOOLBOX_OPENED_COUNT",
userHistogram: "DEVTOOLS_TOOLBOX_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_TOOLBOX_TIME_ACTIVE_SECONDS"
},
options: {
histogram: "DEVTOOLS_OPTIONS_OPENED_COUNT",
userHistogram: "DEVTOOLS_OPTIONS_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_OPTIONS_TIME_ACTIVE_SECONDS"
},
webconsole: {
histogram: "DEVTOOLS_WEBCONSOLE_OPENED_COUNT",
userHistogram: "DEVTOOLS_WEBCONSOLE_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_WEBCONSOLE_TIME_ACTIVE_SECONDS"
},
browserconsole: {
histogram: "DEVTOOLS_BROWSERCONSOLE_OPENED_COUNT",
userHistogram: "DEVTOOLS_BROWSERCONSOLE_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_BROWSERCONSOLE_TIME_ACTIVE_SECONDS"
},
inspector: {
histogram: "DEVTOOLS_INSPECTOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_INSPECTOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_INSPECTOR_TIME_ACTIVE_SECONDS"
},
ruleview: {
histogram: "DEVTOOLS_RULEVIEW_OPENED_COUNT",
userHistogram: "DEVTOOLS_RULEVIEW_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_RULEVIEW_TIME_ACTIVE_SECONDS"
},
computedview: {
histogram: "DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT",
userHistogram: "DEVTOOLS_COMPUTEDVIEW_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_COMPUTEDVIEW_TIME_ACTIVE_SECONDS"
},
fontinspector: {
histogram: "DEVTOOLS_FONTINSPECTOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_FONTINSPECTOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_FONTINSPECTOR_TIME_ACTIVE_SECONDS"
},
animationinspector: {
histogram: "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_ANIMATIONINSPECTOR_TIME_ACTIVE_SECONDS"
},
jsdebugger: {
histogram: "DEVTOOLS_JSDEBUGGER_OPENED_COUNT",
userHistogram: "DEVTOOLS_JSDEBUGGER_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_JSDEBUGGER_TIME_ACTIVE_SECONDS"
},
jsbrowserdebugger: {
histogram: "DEVTOOLS_JSBROWSERDEBUGGER_OPENED_COUNT",
userHistogram: "DEVTOOLS_JSBROWSERDEBUGGER_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_JSBROWSERDEBUGGER_TIME_ACTIVE_SECONDS"
},
styleeditor: {
histogram: "DEVTOOLS_STYLEEDITOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_STYLEEDITOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_STYLEEDITOR_TIME_ACTIVE_SECONDS"
},
shadereditor: {
histogram: "DEVTOOLS_SHADEREDITOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_SHADEREDITOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_SHADEREDITOR_TIME_ACTIVE_SECONDS"
},
webaudioeditor: {
histogram: "DEVTOOLS_WEBAUDIOEDITOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_WEBAUDIOEDITOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_WEBAUDIOEDITOR_TIME_ACTIVE_SECONDS"
},
canvasdebugger: {
histogram: "DEVTOOLS_CANVASDEBUGGER_OPENED_COUNT",
userHistogram: "DEVTOOLS_CANVASDEBUGGER_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_CANVASDEBUGGER_TIME_ACTIVE_SECONDS"
},
performance: {
histogram: "DEVTOOLS_JSPROFILER_OPENED_COUNT",
userHistogram: "DEVTOOLS_JSPROFILER_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_JSPROFILER_TIME_ACTIVE_SECONDS"
},
memory: {
histogram: "DEVTOOLS_MEMORY_OPENED_COUNT",
userHistogram: "DEVTOOLS_MEMORY_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_MEMORY_TIME_ACTIVE_SECONDS"
},
netmonitor: {
histogram: "DEVTOOLS_NETMONITOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_NETMONITOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_NETMONITOR_TIME_ACTIVE_SECONDS"
},
storage: {
histogram: "DEVTOOLS_STORAGE_OPENED_COUNT",
userHistogram: "DEVTOOLS_STORAGE_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_STORAGE_TIME_ACTIVE_SECONDS"
},
paintflashing: {
histogram: "DEVTOOLS_PAINTFLASHING_OPENED_COUNT",
userHistogram: "DEVTOOLS_PAINTFLASHING_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_PAINTFLASHING_TIME_ACTIVE_SECONDS"
},
scratchpad: {
histogram: "DEVTOOLS_SCRATCHPAD_OPENED_COUNT",
userHistogram: "DEVTOOLS_SCRATCHPAD_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_SCRATCHPAD_TIME_ACTIVE_SECONDS"
},
"scratchpad-window": {
histogram: "DEVTOOLS_SCRATCHPAD_WINDOW_OPENED_COUNT",
userHistogram: "DEVTOOLS_SCRATCHPAD_WINDOW_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_SCRATCHPAD_WINDOW_TIME_ACTIVE_SECONDS"
},
responsive: {
histogram: "DEVTOOLS_RESPONSIVE_OPENED_COUNT",
userHistogram: "DEVTOOLS_RESPONSIVE_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_RESPONSIVE_TIME_ACTIVE_SECONDS"
},
eyedropper: {
histogram: "DEVTOOLS_EYEDROPPER_OPENED_COUNT",
userHistogram: "DEVTOOLS_EYEDROPPER_OPENED_PER_USER_FLAG",
},
menueyedropper: {
histogram: "DEVTOOLS_MENU_EYEDROPPER_OPENED_COUNT",
userHistogram: "DEVTOOLS_MENU_EYEDROPPER_OPENED_PER_USER_FLAG",
},
pickereyedropper: {
histogram: "DEVTOOLS_PICKER_EYEDROPPER_OPENED_COUNT",
userHistogram: "DEVTOOLS_PICKER_EYEDROPPER_OPENED_PER_USER_FLAG",
},
toolbareyedropper: {
histogram: "DEVTOOLS_TOOLBAR_EYEDROPPER_OPENED_COUNT",
userHistogram: "DEVTOOLS_TOOLBAR_EYEDROPPER_OPENED_PER_USER_FLAG",
},
developertoolbar: {
histogram: "DEVTOOLS_DEVELOPERTOOLBAR_OPENED_COUNT",
userHistogram: "DEVTOOLS_DEVELOPERTOOLBAR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_DEVELOPERTOOLBAR_TIME_ACTIVE_SECONDS"
},
aboutdebugging: {
histogram: "DEVTOOLS_ABOUTDEBUGGING_OPENED_COUNT",
userHistogram: "DEVTOOLS_ABOUTDEBUGGING_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_ABOUTDEBUGGING_TIME_ACTIVE_SECONDS"
},
webide: {
histogram: "DEVTOOLS_WEBIDE_OPENED_COUNT",
userHistogram: "DEVTOOLS_WEBIDE_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_WEBIDE_TIME_ACTIVE_SECONDS"
},
webideProjectEditor: {
histogram: "DEVTOOLS_WEBIDE_PROJECT_EDITOR_OPENED_COUNT",
userHistogram: "DEVTOOLS_WEBIDE_PROJECT_EDITOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_WEBIDE_PROJECT_EDITOR_TIME_ACTIVE_SECONDS"
},
webideProjectEditorSave: {
histogram: "DEVTOOLS_WEBIDE_PROJECT_EDITOR_SAVE_COUNT",
userHistogram: "DEVTOOLS_WEBIDE_PROJECT_EDITOR_SAVE_PER_USER_FLAG",
},
webideNewProject: {
histogram: "DEVTOOLS_WEBIDE_NEW_PROJECT_COUNT",
userHistogram: "DEVTOOLS_WEBIDE_NEW_PROJECT_PER_USER_FLAG",
},
webideImportProject: {
histogram: "DEVTOOLS_WEBIDE_IMPORT_PROJECT_COUNT",
userHistogram: "DEVTOOLS_WEBIDE_IMPORT_PROJECT_PER_USER_FLAG",
},
custom: {
histogram: "DEVTOOLS_CUSTOM_OPENED_COUNT",
userHistogram: "DEVTOOLS_CUSTOM_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_CUSTOM_TIME_ACTIVE_SECONDS"
},
reloadAddonInstalled: {
histogram: "DEVTOOLS_RELOAD_ADDON_INSTALLED_COUNT",
userHistogram: "DEVTOOLS_RELOAD_ADDON_INSTALLED_PER_USER_FLAG",
},
reloadAddonReload: {
histogram: "DEVTOOLS_RELOAD_ADDON_RELOAD_COUNT",
userHistogram: "DEVTOOLS_RELOAD_ADDON_RELOAD_PER_USER_FLAG",
},
},
@ -251,9 +213,6 @@ Telemetry.prototype = {
if (charts.histogram) {
this.log(charts.histogram, true);
}
if (charts.userHistogram) {
this.logOncePerBrowserVersion(charts.userHistogram, true);
}
if (charts.timerHistogram) {
this.startTimer(charts.timerHistogram);
}

Просмотреть файл

@ -42,10 +42,7 @@ function checkResults(histIdFocus, Telemetry) {
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_COUNT")) {
if (histId.endsWith("OPENED_COUNT")) {
is(value.length, 1, histId + " has one entry");
let okay = value.every(element => element === true);

Просмотреть файл

@ -68,10 +68,7 @@ function checkResults(histIdFocus, Telemetry) {
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_COUNT")) {
if (histId.endsWith("OPENED_COUNT")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function (element) {

Просмотреть файл

@ -72,10 +72,7 @@ function checkResults(histIdFocus, Telemetry) {
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_COUNT")) {
if (histId.endsWith("OPENED_COUNT")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function (element) {

Просмотреть файл

@ -103,10 +103,7 @@ function checkResults(histIdFocus, Telemetry) {
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_COUNT")) {
if (histId.endsWith("OPENED_COUNT")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function (element) {

Просмотреть файл

@ -59,10 +59,7 @@ function checkResults(Telemetry) {
continue;
}
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId === "DEVTOOLS_TOOLBOX_OPENED_COUNT") {
if (histId === "DEVTOOLS_TOOLBOX_OPENED_COUNT") {
is(value.length, 1, histId + " has only one entry");
} else if (histId.endsWith("OPENED_COUNT")) {
ok(value.length > 1, histId + " has more than one entry");

Просмотреть файл

@ -166,10 +166,7 @@ function checkTelemetryResults(Telemetry) {
for (let histId in result) {
let value = result[histId];
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_COUNT")) {
if (histId.endsWith("OPENED_COUNT")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function (element) {

Просмотреть файл

@ -136,10 +136,6 @@
margin-inline-start: -12px !important;
}
.expander:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.expandable {
visibility: visible;
}

Просмотреть файл

@ -282,6 +282,12 @@ div.CodeMirror span.eval-text {
visibility: hidden;
}
/* Mirror the twisty for rtl direction */
.theme-twisty:dir(rtl),
.theme-twisty:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.theme-checkbox {
display: inline-block;
border: 0;

Просмотреть файл

@ -294,6 +294,12 @@ div.CodeMirror span.eval-text {
background-position: -42px -14px;
}
/* Mirror the twisty for rtl direction */
.theme-twisty:dir(rtl),
.theme-twisty:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.theme-checkbox {
display: inline-block;
border: 0;

Просмотреть файл

@ -536,6 +536,12 @@ a {
flex-shrink: 0;
}
/*Do not mirror the twisty because container force to ltr */
.message .theme-twisty:dir(rtl),
.message .theme-twisty:-moz-locale-dir(rtl) {
transform: none;
}
.cm-s-mozilla a[class] {
font-style: italic;
text-decoration: none;

Просмотреть файл

@ -0,0 +1,3 @@
{
"presets": ["es2015"]
}

Просмотреть файл

@ -9,6 +9,7 @@
const {
prepareMessage
} = require("devtools/client/webconsole/new-console-output/utils/messages");
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
const {
MESSAGE_ADD,
@ -18,8 +19,14 @@ const {
FILTERS_CLEAR,
} = require("../constants");
function messageAdd(packet) {
let message = prepareMessage(packet);
const defaultIdGenerator = new IdGenerator();
function messageAdd(packet, idGenerator = null) {
if (idGenerator == null) {
idGenerator = defaultIdGenerator;
}
let message = prepareMessage(packet, idGenerator);
return {
type: MESSAGE_ADD,
message

Просмотреть файл

@ -14,7 +14,6 @@ const { getAllFilters } = require("devtools/client/webconsole/new-console-output
const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui");
const messagesActions = require("devtools/client/webconsole/new-console-output/actions/messages");
const uiActions = require("devtools/client/webconsole/new-console-output/actions/ui");
const { store } = require("devtools/client/webconsole/new-console-output/store");
const {
SEVERITY_FILTER
} = require("../constants");
@ -30,23 +29,23 @@ const FilterBar = createClass({
},
onClearOutputButtonClick: function () {
store.dispatch(messagesActions.messagesClear());
this.props.dispatch(messagesActions.messagesClear());
},
onToggleFilterConfigBarButtonClick: function () {
store.dispatch(uiActions.filterBarToggle());
this.props.dispatch(uiActions.filterBarToggle());
},
onClearFiltersButtonClick: function () {
store.dispatch(messagesActions.filtersClear());
this.props.dispatch(messagesActions.filtersClear());
},
onSearchInput: function (e) {
store.dispatch(messagesActions.messagesSearch(e.target.value));
this.props.dispatch(messagesActions.messagesSearch(e.target.value));
},
render() {
const {filter, ui} = this.props;
const {dispatch, filter, ui} = this.props;
let configFilterBarVisible = ui.configFilterBarVisible;
let children = [];
@ -78,22 +77,30 @@ const FilterBar = createClass({
active: filter.error,
label: "Errors",
filterType: SEVERITY_FILTER,
filterKey: "error"}),
filterKey: "error",
dispatch
}),
FilterToggleButton({
active: filter.warn,
label: "Warnings",
filterType: SEVERITY_FILTER,
filterKey: "warn"}),
filterKey: "warn",
dispatch
}),
FilterToggleButton({
active: filter.log,
label: "Logs",
filterType: SEVERITY_FILTER,
filterKey: "log"}),
filterKey: "log",
dispatch
}),
FilterToggleButton({
active: filter.info,
label: "Info",
filterType: SEVERITY_FILTER,
filterKey: "info"})
filterKey: "info",
dispatch
})
)
);
}

Просмотреть файл

@ -8,7 +8,6 @@ const {
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const { store } = require("devtools/client/webconsole/new-console-output/store");
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
const {
SEVERITY_FILTER
@ -23,11 +22,12 @@ const FilterToggleButton = createClass({
filterType: PropTypes.string.isRequired,
filterKey: PropTypes.string.isRequired,
active: PropTypes.bool.isRequired,
dispatch: PropTypes.func.isRequired,
},
onClick: function () {
if (this.props.filterType === SEVERITY_FILTER) {
store.dispatch(actions.severityFilter(
this.props.dispatch(actions.severityFilter(
this.props.filterKey, !this.props.active));
}
},

Просмотреть файл

@ -6,6 +6,12 @@
"use strict";
// If this is being run from Mocha, then the browser loader hasn't set up
// define. We need to do that before loading Rep.
if (typeof define === "undefined") {
require("amd-loader");
}
// React
const {
createFactory,

Просмотреть файл

@ -19,13 +19,3 @@ DevToolsModules(
'store.js',
'types.js',
)
MOCHITEST_CHROME_MANIFESTS += [
'test/components/chrome.ini',
'test/utils/chrome.ini'
]
XPCSHELL_TESTS_MANIFESTS += [
'test/actions/xpcshell.ini',
'test/store/xpcshell.ini'
]

Просмотреть файл

@ -9,17 +9,19 @@ const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const { Provider } = require("devtools/client/shared/vendor/react-redux");
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
const { store } = require("devtools/client/webconsole/new-console-output/store");
const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
const ConsoleOutput = React.createFactory(require("devtools/client/webconsole/new-console-output/components/console-output"));
const FilterBar = React.createFactory(require("devtools/client/webconsole/new-console-output/components/filter-bar"));
const store = configureStore();
function NewConsoleOutputWrapper(parentNode, jsterm) {
let childComponent = ConsoleOutput({ jsterm });
let filterBar = FilterBar({});
let provider = React.createElement(
Provider,
{ store: store },
{ store },
React.DOM.div(
{className: "webconsole-output-wrapper"},
filterBar,

Просмотреть файл

@ -3,13 +3,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Services = require("Services");
const {FilterState} = require("devtools/client/webconsole/new-console-output/reducers/filters");
const {PrefState} = require("devtools/client/webconsole/new-console-output/reducers/prefs");
const { combineReducers, createStore } = require("devtools/client/shared/vendor/redux");
const { reducers } = require("./reducers/index");
function storeFactory() {
function configureStore(Services) {
if (!Services) {
Services = require("Services");
}
const initialState = {
prefs: new PrefState({
logLimit: Math.max(Services.prefs.getIntPref("devtools.hud.loglimit"), 1),
@ -26,9 +29,7 @@ function storeFactory() {
return createStore(combineReducers(reducers), initialState);
}
// Provide the single store instance for app code.
module.exports.store = storeFactory();
// Provide the store factory for test code so that each test is working with
// its own instance.
module.exports.storeFactory = storeFactory;
module.exports.configureStore = configureStore;

Просмотреть файл

@ -1,39 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var { utils: Cu } = Components;
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
var flags = require("devtools/shared/flags");
flags.testing = true;
flags.wantLogging = true;
flags.wantVerbose = false;
// @TODO consolidate once we have a shared head. See #16
const testPackets = new Map();
testPackets.set("console.log", {
"from": "server1.conn4.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [
"foobar",
"test"
],
"columnNumber": 1,
"counter": null,
"filename": "file:///test.html",
"functionName": "",
"groupName": "",
"level": "log",
"lineNumber": 1,
"private": false,
"styles": [],
"timeStamp": 1455064271115,
"timer": null,
"workerType": "none",
"category": "webdev"
}
});

Просмотреть файл

@ -0,0 +1,68 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { getRepeatId } = require("devtools/client/webconsole/new-console-output/utils/messages");
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const { setupActions } = require("devtools/client/webconsole/new-console-output/test/helpers");
const constants = require("devtools/client/webconsole/new-console-output/constants");
const expect = require("expect");
let actions;
describe("Message actions:", () => {
before(()=>{
actions = setupActions();
});
describe("messageAdd", () => {
it("creates expected action given a packet", () => {
const packet = {
"from": "server1.conn4.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [
"foobar",
"test"
],
"columnNumber": 1,
"counter": null,
"filename": "file:///test.html",
"functionName": "",
"groupName": "",
"level": "log",
"lineNumber": 1,
"private": false,
"styles": [],
"timeStamp": 1455064271115,
"timer": null,
"workerType": "none",
"category": "webdev"
}
};
const action = actions.messageAdd(packet);
const expected = {
type: constants.MESSAGE_ADD,
message: stubConsoleMessages.get("console.log('foobar', 'test')")
};
// Some values on the message are generated by prepareMessage. Manually set
// these on the expected message to match.
expected.message = expected.message.set("repeatId", getRepeatId(expected.message));
expected.message = expected.message.set("id", "1");
expect(action).toEqual(expected);
});
});
describe("messagesClear", () => {
it("creates expected action", () => {
const action = actions.messagesClear();
const expected = {
type: constants.MESSAGES_CLEAR,
};
expect(action).toEqual(expected);
});
});
});

Просмотреть файл

@ -1,40 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {
messageAdd,
messagesClear
} = require("devtools/client/webconsole/new-console-output/actions/messages");
const {
prepareMessage
} = require("devtools/client/webconsole/new-console-output/utils/messages");
const constants = require("devtools/client/webconsole/new-console-output/constants");
function run_test() {
run_next_test();
}
add_task(function* () {
const packet = testPackets.get("console.log");
const action = messageAdd(packet);
const expected = {
type: constants.MESSAGE_ADD,
// Prepare message is tested independently.
message: prepareMessage(packet)
};
// Remove ID for deepEqual comparison.
action.message = action.message.remove('id');
expected.message = expected.message.remove('id');
deepEqual(action, expected,
"messageAdd action creator returns expected action object");
});
add_task(function* () {
const action = messagesClear();
const expected = {
type: constants.MESSAGES_CLEAR,
};
deepEqual(action, expected,
"messagesClear action creator returns expected action object");
});

Просмотреть файл

@ -1,7 +0,0 @@
[DEFAULT]
tags = devtools devtools-webconsole
head = head.js
tail =
firefox-appdir = browser
[test_messages.js]

Просмотреть файл

@ -1,8 +1,7 @@
[DEFAULT]
support-files =
../components/head.js
head.js
[test_getRepeatId.html]
[test_render_perf.html]
skip-if = debug

Просмотреть файл

@ -0,0 +1,16 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var { utils: Cu } = Components;
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
var { Assert } = require("resource://testing-common/Assert.jsm");
var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
var { Task } = require("devtools/shared/task");
var { require: browserRequire } = BrowserLoader({
baseURI: "resource://devtools/client/webconsole/",
window: this
});

Просмотреть файл

@ -57,11 +57,13 @@ function timeit(cb) {
}
window.onload = Task.async(function* () {
const { store } = browserRequire("devtools/client/webconsole/new-console-output/store");
const { configureStore } = browserRequire("devtools/client/webconsole/new-console-output/store");
const { messagesSearch, filtersClear } = browserRequire("devtools/client/webconsole/new-console-output/actions/messages");
const NewConsoleOutputWrapper = browserRequire("devtools/client/webconsole/new-console-output/new-console-output-wrapper");
const wrapper = new NewConsoleOutputWrapper(document.querySelector("#output"), {});
const store = configureStore();
let time = yield timeit(() => {
testPackets.forEach((message) => {
wrapper.dispatchMessageAdd(message);

Просмотреть файл

@ -1,12 +0,0 @@
[DEFAULT]
support-files =
head.js
[test_console-api-call.html]
[test_console-api-call_repeat.html]
[test_evaluation-result.html]
[test_message-icon.html]
[test_message-container.html]
[test_message-repeat.html]
[test_page-error.html]

Просмотреть файл

@ -0,0 +1,58 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
const jsdom = require("mocha-jsdom");
const expect = require("expect");
const {
renderComponent
} = require("devtools/client/webconsole/new-console-output/test/helpers");
describe("ConsoleAPICall component:", () => {
jsdom();
describe("console.log", () => {
it("renders string grips", () => {
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
const rendered = renderComponent(ConsoleApiCall, {message});
const messageBody = getMessageBody(rendered);
// @TODO should output: foobar test
expect(messageBody.textContent).toBe("\"foobar\"\"test\"");
const consoleStringNodes = messageBody.querySelectorAll(".objectBox-string");
expect(consoleStringNodes.length).toBe(2);
});
it("renders repeat node", () => {
const message =
stubConsoleMessages.get("console.log('foobar', 'test')")
.set("repeat", 107);
const rendered = renderComponent(ConsoleApiCall, {message});
const repeatNode = getRepeatNode(rendered);
expect(repeatNode[0].textContent).toBe("107");
});
});
describe("console.count", () => {
it("renders", () => {
const message = stubConsoleMessages.get("console.count('bar')");
const rendered = renderComponent(ConsoleApiCall, {message});
const messageBody = getMessageBody(rendered);
expect(messageBody.textContent).toBe(message.messageText);
});
});
});
function getMessageBody(rendered) {
const queryPath = "div.message.cm-s-mozilla span span.message-flex-body span.message-body.devtools-monospace";
return rendered.querySelector(queryPath);
}
function getRepeatNode(rendered) {
const repeatPath = "span > span.message-flex-body > span.message-body.devtools-monospace + span.message-repeats";
return rendered.querySelectorAll(repeatPath);
}

Просмотреть файл

@ -0,0 +1,32 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const { EvaluationResult } = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
const jsdom = require("mocha-jsdom");
const expect = require("expect");
const {
renderComponent
} = require("devtools/client/webconsole/new-console-output/test/helpers");
describe("EvaluationResult component:", () => {
jsdom();
it("renders a grip result", () => {
const message = stubConsoleMessages.get("new Date(0)");
const props = {
message
};
const rendered = renderComponent(EvaluationResult, props);
const messageBody = getMessageBody(rendered);
expect(messageBody.textContent).toBe("Date1970-01-01T00:00:00.000Z");
});
});
function getMessageBody(rendered) {
const queryPath = "div.message.cm-s-mozilla span.message-body-wrapper.message-body.devtools-monospace";
return rendered.querySelector(queryPath);
}

Просмотреть файл

@ -1,268 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* exported getPacket, renderComponent, shallowRenderComponent,
cleanActualHTML, cleanExpectedHTML */
"use strict";
var { utils: Cu } = Components;
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
var { Assert } = require("resource://testing-common/Assert.jsm");
var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
var flags = require("devtools/shared/flags");
var { Task } = require("devtools/shared/task");
var { DebuggerServer } = require("devtools/server/main");
var { DebuggerClient } = require("devtools/shared/client/main");
const Services = require("Services");
flags.testing = true;
var { require: browserRequire } = BrowserLoader({
baseURI: "resource://devtools/client/webconsole/",
window: this
});
let ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
let React = browserRequire("devtools/client/shared/vendor/react");
var TestUtils = React.addons.TestUtils;
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/stubs");
// @TODO Remove this.
let testCommands = new Map();
testCommands.set("console.log()", {
command: "console.log('foobar', 'test')",
commandType: "consoleAPICall",
// @TODO should output: foobar test
expectedText: "\"foobar\"\"test\""
});
testCommands.set("new Date()", {
command: "new Date(448156800000)",
commandType: "evaluationResult",
// @TODO should output: Date 1984-03-15T00:00:00.000Z
expectedText: "Date1984-03-15T00:00:00.000Z"
});
testCommands.set("pageError", {
command: null,
commandType: "pageError",
expectedText: "ReferenceError: asdf is not defined"
});
function* getPacket(command, type = "evaluationResult") {
try {
// Attach the console to the tab.
let state = yield new Promise(function (resolve) {
attachConsoleToTab(["ConsoleAPI"], resolve);
});
// Run the command and get the packet.
let packet;
switch (type) {
case "consoleAPICall":
packet = yield new Promise((resolve) => {
function onConsoleApiCall(apiCallType, apiCallPacket) {
state.dbgClient.removeListener("consoleAPICall", onConsoleApiCall);
resolve(apiCallPacket);
}
state.dbgClient.addListener("consoleAPICall", onConsoleApiCall);
state.client.evaluateJS(`top.${command}`);
});
break;
case "evaluationResult":
packet = yield new Promise(resolve => {
state.client.evaluateJS(command, resolve);
});
break;
case "pageError":
// @TODO: get packet with RDP
packet = {
"from": "server1.conn1.child1/consoleActor2",
"type": "pageError",
"pageError": {
"errorMessage": "ReferenceError: asdf is not defined",
"sourceName": "data:text/html,<script>asdf</script>",
"lineText": "",
"lineNumber": 1,
"columnNumber": 1,
"category": "content javascript",
"timeStamp": 1455735574091,
"warning": false,
"error": false,
"exception": true,
"strict": false,
"info": false,
"private": false,
"stacktrace": [{
"columnNumber": 68,
"filename": "test.html",
"functionName": "baz",
"language": 2,
"lineNumber": 1
}, {
"columnNumber": 43,
"filename": "test.html",
"functionName": "bar",
"language": 2,
"lineNumber": 2
}, {
"columnNumber": 18,
"filename": "test.html",
"functionName": "foo",
"language": 2,
"lineNumber": 3
}, {
"columnNumber": 150,
"filename": "test.html",
"functionName": "",
"language": 2,
"lineNumber": 4
}]
}
};
break;
}
closeDebugger(state);
return packet;
} catch (e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
}
}
function renderComponent(component, props) {
const el = React.createElement(component, props, {});
// By default, renderIntoDocument() won't work for stateless components, but
// it will work if the stateless component is wrapped in a stateful one.
// See https://github.com/facebook/react/issues/4839
const wrappedEl = React.DOM.span({}, [el]);
const renderedComponent = TestUtils.renderIntoDocument(wrappedEl);
return ReactDOM.findDOMNode(renderedComponent).children[0];
}
function shallowRenderComponent(component, props) {
const el = React.createElement(component, props);
const renderer = TestUtils.createRenderer();
renderer.render(el, {});
return renderer.getRenderOutput();
}
function cleanActualHTML(htmlString) {
return htmlString.replace(/ data-reactid=\".*?\"/g, "");
}
function cleanExpectedHTML(htmlString) {
return htmlString.replace(/(?:\r\n|\r|\n)\s*/g, "");
}
// Helpers copied in from shared/webconsole/test/common.js
function initCommon()
{
// Services.prefs.setBoolPref("devtools.debugger.log", true);
}
function initDebuggerServer()
{
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
DebuggerServer.allowChromeProcess = true;
}
function connectToDebugger(aCallback)
{
initCommon();
initDebuggerServer();
let transport = DebuggerServer.connectPipe();
let client = new DebuggerClient(transport);
let dbgState = { dbgClient: client };
client.connect().then(response => aCallback(dbgState, response));
}
function closeDebugger(aState, aCallback)
{
aState.dbgClient.close(aCallback);
aState.dbgClient = null;
aState.client = null;
}
function attachConsole(aListeners, aCallback) {
_attachConsole(aListeners, aCallback);
}
function attachConsoleToTab(aListeners, aCallback) {
_attachConsole(aListeners, aCallback, true);
}
function attachConsoleToWorker(aListeners, aCallback) {
_attachConsole(aListeners, aCallback, true, true);
}
function _attachConsole(aListeners, aCallback, aAttachToTab, aAttachToWorker)
{
function _onAttachConsole(aState, aResponse, aWebConsoleClient)
{
if (aResponse.error) {
console.error("attachConsole failed: " + aResponse.error + " " +
aResponse.message);
}
aState.client = aWebConsoleClient;
aCallback(aState, aResponse);
}
connectToDebugger(function _onConnect(aState, aResponse) {
if (aResponse.error) {
console.error("client.connect() failed: " + aResponse.error + " " +
aResponse.message);
aCallback(aState, aResponse);
return;
}
if (aAttachToTab) {
aState.dbgClient.listTabs(function _onListTabs(aResponse) {
if (aResponse.error) {
console.error("listTabs failed: " + aResponse.error + " " +
aResponse.message);
aCallback(aState, aResponse);
return;
}
let tab = aResponse.tabs[aResponse.selected];
aState.dbgClient.attachTab(tab.actor, function (response, tabClient) {
if (aAttachToWorker) {
var worker = new Worker("console-test-worker.js");
worker.addEventListener("message", function listener() {
worker.removeEventListener("message", listener);
tabClient.listWorkers(function (response) {
tabClient.attachWorker(response.workers[0].actor, function (response, workerClient) {
workerClient.attachThread({}, function (aResponse) {
aState.actor = workerClient.consoleActor;
aState.dbgClient.attachConsole(workerClient.consoleActor, aListeners,
_onAttachConsole.bind(null, aState));
});
});
});
});
} else {
aState.actor = tab.consoleActor;
aState.dbgClient.attachConsole(tab.consoleActor, aListeners,
_onAttachConsole.bind(null, aState));
}
});
});
} else {
aState.dbgClient.getProcess().then(response => {
aState.dbgClient.attachTab(response.form.actor, function () {
let consoleActor = response.form.consoleActor;
aState.actor = consoleActor;
aState.dbgClient.attachConsole(consoleActor, aListeners,
_onAttachConsole.bind(null, aState));
});
});
}
});
}

Просмотреть файл

@ -0,0 +1,49 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const { MessageContainer } = require("devtools/client/webconsole/new-console-output/components/message-container");
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
const { EvaluationResult } = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
const { PageError } = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
const jsdom = require("mocha-jsdom");
const expect = require("expect");
const {
renderComponent,
shallowRenderComponent
} = require("devtools/client/webconsole/new-console-output/test/helpers");
describe("MessageContainer component:", () => {
jsdom();
it("pipes data to children as expected", () => {
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
const rendered = renderComponent(MessageContainer, {message});
expect(rendered.textContent.includes("foobar")).toBe(true);
});
it("picks correct child component", () => {
const messageTypes = [
{
component: ConsoleApiCall,
message: stubConsoleMessages.get("console.log('foobar', 'test')")
},
{
component: EvaluationResult,
message: stubConsoleMessages.get("new Date(0)")
},
{
component: PageError,
message: stubConsoleMessages.get("ReferenceError")
}
];
messageTypes.forEach(info => {
const rendered = shallowRenderComponent(MessageContainer, {message: info.message});
expect(rendered.type).toBe(info.component);
});
});
});

Просмотреть файл

@ -0,0 +1,26 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {
SEVERITY_ERROR,
} = require("devtools/client/webconsole/new-console-output/constants");
const { MessageIcon } = require("devtools/client/webconsole/new-console-output/components/message-icon");
const jsdom = require("mocha-jsdom");
const expect = require("expect");
const {
renderComponent
} = require("devtools/client/webconsole/new-console-output/test/helpers");
describe("MessageIcon component:", () => {
jsdom();
it("renders icon based on severity", () => {
const rendered = renderComponent(MessageIcon, { severity: SEVERITY_ERROR });
expect(rendered.classList.contains("icon")).toBe(true);
expect(rendered.getAttribute("title")).toBe("Error");
});
});

Просмотреть файл

@ -0,0 +1,30 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
const { PageError } = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
const jsdom = require("mocha-jsdom");
const expect = require("expect");
const {
renderComponent
} = require("devtools/client/webconsole/new-console-output/test/helpers");
describe("PageError component:", () => {
jsdom();
it("renders a page error", () => {
const message = stubConsoleMessages.get("ReferenceError");
const rendered = renderComponent(PageError, {message});
const messageBody = getMessageBody(rendered);
expect(messageBody.textContent).toBe("ReferenceError: asdf is not defined");
});
});
function getMessageBody(rendered) {
const queryPath = "div.message span.message-body-wrapper.message-body.devtools-monospace";
return rendered.querySelector(queryPath);
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше