Merge m-c to fx-team a=merge
3
.gitignore
vendored
@ -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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 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>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 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>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 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;
|
||||
|
3
devtools/client/webconsole/.babelrc
Normal file
@ -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);
|
||||
}
|