Merge m-c to autoland, a=merge

This commit is contained in:
Wes Kocher 2016-08-12 16:30:03 -07:00
commit 4aec37ca6e
538 changed files with 6186 additions and 4143 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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>

View File

@ -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"/>

View File

@ -7207,6 +7207,8 @@ var gIdentityHandler = {
if (event.target == this._identityPopup) {
window.addEventListener("focus", this, true);
}
this._identityPopupMultiView._mainView.style.height =
this._identityPopup.getBoundingClientRect().height + "px";
},
onPopupHidden(event) {

View File

@ -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

View File

@ -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);
});

View File

@ -152,7 +152,7 @@ const PanelUI = {
anchor = aEvent.target;
}
this.panel.addEventListener("popupshown", function onPopupShown() {
this.panel.addEventListener("popupshown", function onPopupShown(event) {
this.removeEventListener("popupshown", onPopupShown);
resolve();
});

View File

@ -58,8 +58,7 @@
<field name="_anchorElement">null</field>
<field name="_mainViewHeight">0</field>
<field name="_subViewObserver">null</field>
<field name="__transitioning">false</field>
<field name="_ignoreMutations">false</field>
<field name="__transitioning">true</field>
<property name="showingSubView" readonly="true"
onget="return this._viewStack.getAttribute('viewtype') == 'subview'"/>
@ -69,22 +68,6 @@
<property name="showingSubViewAsMainView" readonly="true"
onget="return this.getAttribute('mainViewIsSubView') == 'true'"/>
<property name="ignoreMutations">
<getter>
return this._ignoreMutations;
</getter>
<setter><![CDATA[
this._ignoreMutations = val;
if (!val && this._panel.state == "open") {
if (this.showingSubView) {
this._syncContainerWithSubView();
} else {
this._syncContainerWithMainView();
}
}
]]></setter>
</property>
<property name="_transitioning">
<getter>
return this.__transitioning;
@ -223,7 +206,10 @@
let container = this._viewContainer;
this._transitioning = true;
let onTransitionEnd = () => {
let onTransitionEnd = (event) => {
if (event.propertyName != "transform") {
return;
}
container.removeEventListener("transitionend", onTransitionEnd);
this._transitioning = false;
};
@ -296,7 +282,6 @@
}
break;
case "popupshowing":
this.setAttribute("panelopen", "true");
// Bug 941196 - The panel can get taller when opening a subview. Disabling
// autoPositioning means that the panel won't jump around if an opened
// subview causes the panel to exceed the dimensions of the screen in the
@ -312,9 +297,18 @@
subtree: true
});
break;
case "popupshown":
this._setMaxHeight();
let onTransitionEnd = (event) => {
if (event.propertyName != "transform") {
return;
}
let panel = event.target;
panel.removeEventListener("tranitionend", onTransitionEnd);
// Needed in case the panel is closed before the transition ends.
if (panel.state == "open") {
this.setAttribute("panelopen", "true");
}
};
this._panel.addEventListener("transitionend", onTransitionEnd);
break;
case "popuphidden":
this.removeAttribute("panelopen");
@ -338,22 +332,9 @@
]]></body>
</method>
<method name="_setMaxHeight">
<body><![CDATA[
if (!this._shouldSetHeight())
return;
// Ignore the mutation that'll fire when we set the height of
// the main view.
this.ignoreMutations = true;
this._mainView.style.height =
this.getBoundingClientRect().height + "px";
this.ignoreMutations = false;
]]></body>
</method>
<method name="_adjustContainerHeight">
<body><![CDATA[
if (!this.ignoreMutations && !this.showingSubView && !this._transitioning) {
if (!this.showingSubView && !this._transitioning) {
let height;
if (this.showingSubViewAsMainView) {
height = this._heightOfSubview(this._mainView);
@ -371,7 +352,7 @@
return;
}
if (!this.ignoreMutations && this.showingSubView) {
if (this.showingSubView) {
let newHeight = this._heightOfSubview(this._currentSubView, this._subViews);
this._viewContainer.style.height = newHeight + "px";
}

View File

@ -149,7 +149,8 @@ skip-if = os == "mac"
[browser_1096763_seen_widgets_post_reset.js]
[browser_1161838_inserted_new_default_buttons.js]
[browser_bootstrapped_custom_toolbar.js]
[browser_check_tooltips_in_navbar.js]
[browser_customizemode_contextmenu_menubuttonstate.js]
[browser_no_mutationrecords_during_panel_opening.js]
[browser_panel_toggle.js]
[browser_switch_to_customize_mode.js]
[browser_check_tooltips_in_navbar.js]

View File

@ -0,0 +1,88 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Test that we don't get unexpected mutations during the opening of the
* browser menu.
*/
add_task(function* test_setup() {
yield resetCustomization();
yield PanelUI.show();
let hiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield hiddenPromise;
});
add_task(function* no_mutation_events_during_opening() {
let panel = PanelUI.panel;
yield PanelUI.ensureReady();
let failures = 0;
let observer = new MutationObserver(function(mutations) {
for (let mutation of mutations) {
if (mutation.target.localName == "panel" &&
mutation.type == "attributes" &&
mutation.attributeName == "animate") {
// This mutation is allowed because it triggers the CSS transition.
continue;
}
if (mutation.type == "attributes" &&
mutation.attributeName == "panelopen") {
// This mutation is allowed because it is set after the panel has
// finished the transition.
continue;
}
let newValue = null;
if (mutation.type == "attributes") {
newValue = mutation.target.getAttribute(mutation.attributeName);
} else if (mutation.type == "characterData") {
newValue = mutation.target.textContent;
}
if (AppConstants.isPlatformAndVersionAtMost("win", "6.1") &&
mutation.target.className == "panel-arrowbox" &&
mutation.attributeName == "style" &&
newValue.startsWith("transform:")) {
// Windows 7 and earlier has an alignment offset on the arrowbox.
// This is allowed here as it is no longer used on newer platforms.
continue;
}
if (newValue == mutation.oldValue) {
// Mutations records are observed even when the new and old value are
// identical. This is unlikely to invalidate the panel, so ignore these.
continue;
}
let nodeIdentifier = `${mutation.target.localName}#${mutation.target.id}.${mutation.target.className};`;
ok(false, `Observed: ${mutation.type}; ${nodeIdentifier} ${mutation.attributeName}; oldValue: ${mutation.oldValue}; newValue: ${newValue}`);
failures++;
}
});
observer.observe(panel, {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true,
});
let shownPromise = promisePanelShown(window);
PanelUI.show();
yield shownPromise;
observer.disconnect();
is(failures, 0, "There should be no unexpected mutation events during opening of the panel");
});
add_task(function* cleanup() {
let hiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield hiddenPromise;
});

View File

@ -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 = {};

View File

@ -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]

View File

@ -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;
}
}
});

View File

@ -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;
}
}
});

View File

@ -175,17 +175,23 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
let checkPanelPosition = () => {
is(panel.getAttribute("side"), arrowSide, "Panel arrow is positioned as expected");
function isGreaterThanOrWithinPixelRoundingError(a, b, message) {
let result = a + 1 >= b;
ok(result, `${a} should be greater than or within one pixel of ${b}: ${message}`);
}
let panelRect = panel.getBoundingClientRect();
if (arrowSide == "top") {
ok(panelRect.top, origPanelRect.top, "Panel has not moved downwards");
ok(panelRect.bottom >= origPanelRect.bottom, `Panel has not shrunk from original size (${panelRect.bottom} >= ${origPanelRect.bottom})`);
isGreaterThanOrWithinPixelRoundingError(panelRect.top, origPanelRect.top, "Panel has not moved downwards");
isGreaterThanOrWithinPixelRoundingError(panelRect.bottom, origPanelRect.bottom, "Panel has not shrunk from original size");
let screenBottom = browserWin.screen.availTop + win.screen.availHeight;
let panelBottom = browserWin.mozInnerScreenY + panelRect.bottom;
ok(panelBottom <= screenBottom, `Bottom of popup should be on-screen. (${panelBottom} <= ${screenBottom})`);
} else {
ok(panelRect.bottom, origPanelRect.bottom, "Panel has not moved upwards");
ok(panelRect.top <= origPanelRect.top, `Panel has not shrunk from original size (${panelRect.top} <= ${origPanelRect.top})`);
isGreaterThanOrWithinPixelRoundingError(panelRect.bottom, origPanelRect.bottom, "Panel has not moved upwards");
// The arguments here are reversed compared to the above calls due to the coordinate system.
isGreaterThanOrWithinPixelRoundingError(origPanelRect.top, panelRect.top, "Panel has not shrunk from original size");
let panelTop = browserWin.mozInnerScreenY + panelRect.top;
ok(panelTop >= browserWin.screen.availTop, `Top of popup should be on-screen. (${panelTop} >= ${browserWin.screen.availTop})`);

View File

@ -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();
});

View File

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

View File

@ -12,41 +12,21 @@ const TELEMETRY_RESULT_ENUM = {
RESTORED_DEFAULT: 0,
KEPT_CURRENT: 1,
CHANGED_ENGINE: 2,
CLOSED_PAGE: 3
CLOSED_PAGE: 3,
OPENED_SETTINGS: 4
};
window.onload = function() {
let list = document.getElementById("defaultEngine");
let originalDefault = Services.search.originalDefaultEngine.name;
Services.search.getDefaultEngines().forEach(e => {
let opt = document.createElement("option");
opt.setAttribute("value", e.name);
opt.engine = e;
opt.textContent = e.name;
if (e.iconURI)
opt.style.backgroundImage = 'url("' + e.iconURI.spec + '")';
if (e.name == originalDefault)
opt.setAttribute("selected", "true");
list.appendChild(opt);
});
let updateIcon = () => {
list.style.setProperty("--engine-icon-url",
list.selectedOptions[0].style.backgroundImage);
};
list.addEventListener("change", updateIcon);
// When selecting using the keyboard, the 'change' event is only fired after
// the user presses <enter> or moves the focus elsewhere.
// keypress/keyup fire too late and cause flicker when updating the icon.
// keydown fires too early and the selected option isn't changed yet.
list.addEventListener("keydown", () => {
Services.tm.mainThread.dispatch(updateIcon, Ci.nsIThread.DISPATCH_NORMAL);
});
updateIcon();
let defaultEngine = document.getElementById("defaultEngine");
let originalDefault = Services.search.originalDefaultEngine;
defaultEngine.textContent = originalDefault.name;
defaultEngine.style.backgroundImage =
'url("' + originalDefault.iconURI.spec + '")';
document.getElementById("searchResetChangeEngine").focus();
window.addEventListener("unload", recordPageClosed);
document.getElementById("linkSettingsPage")
.addEventListener("click", openingSettings);
};
function doSearch() {
@ -77,6 +57,11 @@ function doSearch() {
win.openUILinkIn(submission.uri.spec, "current", false, submission.postData);
}
function openingSettings() {
record(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
window.removeEventListener("unload", recordPageClosed);
}
function record(result) {
Services.telemetry.getHistogramById("SEARCH_RESET_RESULT").add(result);
}
@ -90,18 +75,12 @@ function keepCurrentEngine() {
}
function changeSearchEngine() {
let list = document.getElementById("defaultEngine");
let engine = list.selectedOptions[0].engine;
let engine = Services.search.originalDefaultEngine;
if (engine.hidden)
engine.hidden = false;
Services.search.currentEngine = engine;
// Record if we restored the original default or changed to another engine.
let originalDefault = Services.search.originalDefaultEngine.name;
let code = TELEMETRY_RESULT_ENUM.CHANGED_ENGINE;
if (Services.search.originalDefaultEngine.name == engine.name)
code = TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT;
record(code);
record(TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT);
doSearch();
}

View File

@ -39,9 +39,7 @@
<div class="description">
<p>&searchreset.pageInfo1;</p>
<p>&searchreset.selector.label;
<select id="defaultEngine"></select>
</p>
<p>&searchreset.selector.label;<span id="defaultEngine"/></p>
<p>&searchreset.beforelink.pageInfo2;<a id="linkSettingsPage" href="about:preferences#search">&searchreset.link.pageInfo2;</a>&searchreset.afterlink.pageInfo2;</p>
</div>

View File

@ -6,7 +6,8 @@ const TELEMETRY_RESULT_ENUM = {
RESTORED_DEFAULT: 0,
KEPT_CURRENT: 1,
CHANGED_ENGINE: 2,
CLOSED_PAGE: 3
CLOSED_PAGE: 3,
OPENED_SETTINGS: 4
};
const kSearchStr = "a search";
@ -77,12 +78,15 @@ var gTests = [
run: function* () {
let currentEngine = Services.search.currentEngine;
let originalEngine = Services.search.originalDefaultEngine;
let doc = gBrowser.contentDocument;
let defaultEngineSpan = doc.getElementById("defaultEngine");
is(defaultEngineSpan.textContent, originalEngine.name,
"the name of the original default engine is displayed");
let expectedURL = originalEngine.
getSubmission(kSearchStr, null, kSearchPurpose).
uri.spec;
let loadPromise = promiseStoppedLoad(expectedURL);
let doc = gBrowser.contentDocument;
let button = doc.getElementById("searchResetChangeEngine");
is(doc.activeElement, button,
"the 'Change Search Engine' button is focused");
@ -98,41 +102,15 @@ var gTests = [
},
{
desc: "Test the engine selector drop down.",
desc: "Click the settings link.",
run: function* () {
let originalEngineName = Services.search.originalDefaultEngine.name;
let doc = gBrowser.contentDocument;
let list = doc.getElementById("defaultEngine");
is(list.value, originalEngineName,
"the default selection of the dropdown is the original default engine");
let defaultEngines = Services.search.getDefaultEngines();
is(list.childNodes.length, defaultEngines.length,
"the dropdown has the correct count of engines");
// Select an engine that isn't the original default one.
let engine;
for (let i = 0; i < defaultEngines.length; ++i) {
if (defaultEngines[i].name != originalEngineName) {
engine = defaultEngines[i];
engine.hidden = true;
break;
}
}
list.value = engine.name;
let expectedURL = engine.getSubmission(kSearchStr, null, kSearchPurpose)
.uri.spec;
let loadPromise = promiseStoppedLoad(expectedURL);
doc.getElementById("searchResetChangeEngine").click();
let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
false,
"about:preferences#search")
gBrowser.contentDocument.getElementById("linkSettingsPage").click();
yield loadPromise;
ok(!engine.hidden, "the selected engine has been unhidden");
is(engine, Services.search.currentEngine,
"the current engine is what was selected in the drop down");
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.CHANGED_ENGINE);
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
}
},

View File

@ -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;
@ -948,7 +955,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);
}
@ -1010,10 +1017,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;
@ -1956,14 +1959,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;
}

View File

@ -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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -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);
@ -1656,7 +1663,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);
}
@ -3468,10 +3475,5 @@ menulist.translate-infobar-element > .menulist-dropmarker {
}
.webextension-popup-browser {
margin-right: -1px;
border-radius: inherit;
}
#PanelUI-popup .webextension-popup-browser {
margin: 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -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;
}

View File

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

View File

@ -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 {

View File

@ -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] {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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] {

View File

@ -10,35 +10,13 @@ body {
background-image: url("chrome://browser/skin/icon-search-64.svg");
}
select {
font: inherit;
padding-inline-end: 24px;
#defaultEngine {
padding-inline-start: 26px;
background-image: var(--engine-icon-url),
url("chrome://global/skin/in-content/dropdown.svg#dropdown");
background-repeat: no-repeat;
background-position: 8px center, calc(100% - 4px) center;
background-position: 5px center;
background-size: 16px, 16px;
}
select:-moz-dir(rtl) {
background-position: calc(100% - 8px) center, 4px center;
}
select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 var(--in-content-text-color);
}
option {
padding: 4px;
padding-inline-start: 30px;
background-repeat: no-repeat;
background-position: 8px center;
background-size: 16px;
background-color: var(--in-content-page-background);
}
option:-moz-dir(rtl) {
background-position: calc(100% - 8px) center;
#defaultEngine:-moz-dir(rtl) {
background-position: calc(100% - 5px) center;
}

View File

@ -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 {
@ -1372,7 +1391,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);
}
@ -1420,10 +1439,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;
@ -2728,10 +2743,5 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton {
}
.webextension-popup-browser {
margin-right: -1px;
border-radius: inherit;
}
#PanelUI-popup .webextension-popup-browser {
margin: 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -3,6 +3,10 @@ subsuite = screenshots
support-files =
head.js
mozscreenshots/extension/lib/permissionPrompts.html
mozscreenshots/extension/lib/controlCenter/password.html
mozscreenshots/extension/lib/controlCenter/mixed.html
mozscreenshots/extension/lib/controlCenter/mixed_active.html
mozscreenshots/extension/lib/controlCenter/mixed_passive.html
mozscreenshots/extension/lib/borderify.xpi
[browser_screenshots.js]

View File

@ -0,0 +1,6 @@
[DEFAULT]
subsuite = screenshots
support-files =
../head.js
[browser_controlCenter.js]

View File

@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function* capture() {
if (!shouldCapture()) {
return;
}
let sets = ["LightweightThemes", "ControlCenter"];
yield TestRunner.start(sets, "controlCenter");
});

View File

@ -8,6 +8,7 @@ BROWSER_CHROME_MANIFESTS += [
# Each test is in it's own directory so it gets run in a clean profile with
# run-by-dir.
'browser.ini',
'controlCenter/browser.ini',
'devtools/browser.ini',
'permissionPrompts/browser.ini',
'preferences/browser.ini',

View File

@ -0,0 +1,238 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["ControlCenter"];
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://testing-common/BrowserTestUtils.jsm");
Cu.import("resource:///modules/SitePermissions.jsm");
let {UrlClassifierTestUtils} = Cu.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
const RESOURCE_PATH = "extensions/mozscreenshots/browser/chrome/mozscreenshots/lib/controlCenter";
const HTTP_PAGE = "http://example.com/";
const HTTPS_PAGE = "https://example.com/";
const PERMISSIONS_PAGE = "https://test1.example.com/";
const HTTP_PASSWORD_PAGE = `http://test2.example.org/${RESOURCE_PATH}/password.html`;
const MIXED_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed.html`;
const MIXED_ACTIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_active.html`;
const MIXED_PASSIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_passive.html`;
const TRACKING_PAGE = `http://tracking.example.org/${RESOURCE_PATH}/tracking.html`;
this.ControlCenter = {
init(libDir) { },
configurations: {
about: {
applyConfig: Task.async(function* () {
yield loadPage("about:home");
yield openIdentityPopup();
}),
},
localFile: {
applyConfig: Task.async(function* () {
let filePath = "file:///";
if (Services.appinfo.OS === "WINNT") {
filePath += "C:/";
}
yield loadPage(filePath);
yield openIdentityPopup();
}),
},
http: {
applyConfig: Task.async(function* () {
yield loadPage(HTTP_PAGE);
yield openIdentityPopup();
}),
},
httpSubView: {
applyConfig: Task.async(function* () {
yield loadPage(HTTP_PAGE);
yield openIdentityPopup(true);
}),
},
https: {
applyConfig: Task.async(function* () {
yield loadPage(HTTPS_PAGE);
yield openIdentityPopup();
}),
},
httpsSubView: {
applyConfig: Task.async(function* () {
yield loadPage(HTTPS_PAGE);
yield openIdentityPopup(true);
}),
},
singlePermission: {
applyConfig: Task.async(function* () {
let uri = Services.io.newURI(PERMISSIONS_PAGE, null, null)
SitePermissions.set(uri, "camera", SitePermissions.ALLOW);
yield loadPage(PERMISSIONS_PAGE);
yield openIdentityPopup();
}),
},
allPermissions: {
applyConfig: Task.async(function* () {
// there are 3 possible non-default permission states, so we alternate between them
let states = [SitePermissions.ALLOW, SitePermissions.BLOCK, SitePermissions.SESSION];
let uri = Services.io.newURI(PERMISSIONS_PAGE, null, null)
SitePermissions.listPermissions().forEach(function (permission, index) {
SitePermissions.set(uri, permission, states[index % 3]);
});
yield loadPage(PERMISSIONS_PAGE);
yield openIdentityPopup();
}),
},
mixed: {
applyConfig: Task.async(function* () {
yield loadPage(MIXED_CONTENT_URL);
yield openIdentityPopup();
}),
},
mixedSubView: {
applyConfig: Task.async(function* () {
yield loadPage(MIXED_CONTENT_URL);
yield openIdentityPopup(true);
}),
},
mixedPassive: {
applyConfig: Task.async(function* () {
yield loadPage(MIXED_PASSIVE_CONTENT_URL);
yield openIdentityPopup();
}),
},
mixedPassiveSubView: {
applyConfig: Task.async(function* () {
yield loadPage(MIXED_PASSIVE_CONTENT_URL);
yield openIdentityPopup(true);
}),
},
mixedActive: {
applyConfig: Task.async(function* () {
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
yield openIdentityPopup();
}),
},
mixedActiveSubView: {
applyConfig: Task.async(function* () {
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
yield openIdentityPopup(true);
}),
},
mixedActiveUnblocked: {
applyConfig: Task.async(function* () {
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
let gBrowser = browserWindow.gBrowser;
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
gBrowser.ownerGlobal.gIdentityHandler.disableMixedContentProtection();
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, MIXED_ACTIVE_CONTENT_URL);
yield openIdentityPopup();
}),
},
mixedActiveUnblockedSubView: {
applyConfig: Task.async(function* () {
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
let gBrowser = browserWindow.gBrowser;
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
gBrowser.ownerGlobal.gIdentityHandler.disableMixedContentProtection();
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, MIXED_ACTIVE_CONTENT_URL);
yield openIdentityPopup(true);
}),
},
httpPassword: {
applyConfig: Task.async(function* () {
yield loadPage(HTTP_PASSWORD_PAGE);
yield openIdentityPopup();
}),
},
httpPasswordSubView: {
applyConfig: Task.async(function* () {
yield loadPage(HTTP_PASSWORD_PAGE);
yield openIdentityPopup(true);
}),
},
trackingProtectionNoElements: {
applyConfig: Task.async(function* () {
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
yield loadPage(HTTP_PAGE);
yield openIdentityPopup();
}),
},
trackingProtectionEnabled: {
applyConfig: Task.async(function* () {
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
yield UrlClassifierTestUtils.addTestTrackers();
yield loadPage(TRACKING_PAGE);
yield openIdentityPopup();
}),
},
trackingProtectionDisabled: {
applyConfig: Task.async(function* () {
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
let gBrowser = browserWindow.gBrowser;
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
yield UrlClassifierTestUtils.addTestTrackers();
yield loadPage(TRACKING_PAGE);
yield openIdentityPopup();
// unblock the page
gBrowser.ownerGlobal.document.querySelector("#tracking-action-unblock").click();
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, TRACKING_PAGE);
yield openIdentityPopup();
}),
},
},
};
function* loadPage(url) {
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
let gBrowser = browserWindow.gBrowser;
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, url);
}
function* openIdentityPopup(expand) {
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
let gBrowser = browserWindow.gBrowser;
let { gIdentityHandler } = gBrowser.ownerGlobal;
gIdentityHandler._identityPopup.hidePopup();
gIdentityHandler._identityBox.querySelector("#identity-icon").click();
if (expand) {
// give some time for opening to avoid weird style issues
yield new Promise((c) => setTimeout(c, 500));
gIdentityHandler._identityPopup.querySelector("#identity-popup-security-expander").click();
}
}

View File

@ -20,6 +20,7 @@ let lastTab = null;
this.PermissionPrompts = {
init(libDir) {
Services.prefs.setBoolPref("media.navigator.permission.fake", true);
Services.prefs.setBoolPref("media.getusermedia.screensharing.allow_on_old_platforms", true);
Services.prefs.setCharPref("media.getusermedia.screensharing.allowed_domains",
"test1.example.com");
Services.prefs.setBoolPref("extensions.install.requireBuiltInCerts", false);

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf8">
<title>Mixed Content test</title>
</head>
<body>
<iframe style="visibility:hidden" src="http://example.com"></iframe>
<img style="visibility:hidden" src="http://example.com/tests/image/test/mochitest/blue.png"></img>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf8">
<title>Mixed Active Content test</title>
</head>
<body>
<iframe style="visibility:hidden" src="http://example.com"></iframe>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf8">
<title>Mixed Passive Content test</title>
</head>
<body>
<img style="visibility:hidden" src="http://example.com/tests/image/test/mochitest/blue.png"></img>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf8">
<title>HTTP Password test</title>
</head>
<body>
<form>
<input type="password" />
<button type="submit">Submit</button>
</form>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf8">
<title>Tracking test</title>
</head>
<body>
<iframe style="visibility:hidden" src="http://tracking.example.com/"></iframe>
</body>
</html>

View File

@ -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',

View File

@ -71,8 +71,8 @@ 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;

View File

@ -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);

View File

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

View File

@ -19,7 +19,6 @@ const { LocationStore, serialize, deserialize } = require("./location-store");
function SourceMapService(target) {
this._target = target;
this._locationStore = new LocationStore();
this._isInitialResolve = true;
EventEmitter.decorate(this);
@ -41,7 +40,6 @@ function SourceMapService(target) {
* Clears the store containing the cached resolved locations and promises
*/
SourceMapService.prototype.reset = function () {
this._isInitialResolve = true;
this._locationStore.clear();
};
@ -51,7 +49,6 @@ SourceMapService.prototype.destroy = function () {
this._target.off("navigate", this.reset);
this._target.off("will-navigate", this.reset);
this._target.off("close", this.destroy);
this._isInitialResolve = null;
this._target = this._locationStore = null;
};
@ -63,10 +60,7 @@ SourceMapService.prototype.destroy = function () {
SourceMapService.prototype.subscribe = function (location, callback) {
this.on(serialize(location), callback);
this._locationStore.set(location);
if (this._isInitialResolve) {
this._resolveAndUpdate(location);
this._isInitialResolve = false;
}
this._resolveAndUpdate(location);
};
/**
@ -76,7 +70,12 @@ SourceMapService.prototype.subscribe = function (location, callback) {
*/
SourceMapService.prototype.unsubscribe = function (location, callback) {
this.off(serialize(location), callback);
this._locationStore.clearByURL(location.url);
// Check to see if the store exists before attempting to clear a location
// Sometimes un-subscribe happens during the destruction cascades and this
// condition is to protect against that. Could be looked into in the future.
if (this._locationStore) {
this._locationStore.clearByURL(location.url);
}
};
/**
@ -87,16 +86,10 @@ SourceMapService.prototype.unsubscribe = function (location, callback) {
*/
SourceMapService.prototype._resolveAndUpdate = function (location) {
this._resolveLocation(location).then(resolvedLocation => {
// We try to source map the first console log to initiate the source-updated event from
// target. The isSameLocation check is to make sure we don't update the frame, if the
// location is not source-mapped.
if (resolvedLocation) {
if (this._isInitialResolve) {
if (!isSameLocation(location, resolvedLocation)) {
this.emit(serialize(location), location, resolvedLocation);
return;
}
}
// We try to source map the first console log to initiate the source-updated
// event from target. The isSameLocation check is to make sure we don't update
// the frame, if the location is not source-mapped.
if (resolvedLocation && !isSameLocation(location, resolvedLocation)) {
this.emit(serialize(location), location, resolvedLocation);
}
});
@ -182,7 +175,6 @@ function resolveLocation(target, location) {
if (newLocation.error) {
return null;
}
return newLocation;
});
}
@ -197,4 +189,4 @@ function isSameLocation(location, resolvedLocation) {
return location.url === resolvedLocation.url &&
location.line === resolvedLocation.line &&
location.column === resolvedLocation.column;
};
}

View File

@ -19,25 +19,22 @@ const PAGE_URL = `${DEBUGGER_ROOT}doc_empty-tab-01.html`;
const JS_URL = `${URL_ROOT}code_binary_search.js`;
const COFFEE_URL = `${URL_ROOT}code_binary_search.coffee`;
const { SourceMapService } = require("devtools/client/framework/source-map-service");
const { serialize } = require("devtools/client/framework/location-store");
add_task(function* () {
const toolbox = yield openNewTabAndToolbox(PAGE_URL, "jsdebugger");
const service = new SourceMapService(toolbox.target);
const aggregator = [];
let aggregator = new Map();
function onUpdate(e, oldLoc, newLoc) {
if (oldLoc.line === 6) {
checkLoc1(oldLoc, newLoc);
} else if (oldLoc.line === 8) {
checkLoc2(oldLoc, newLoc);
} else if (oldLoc.line === 2) {
checkLoc3(oldLoc, newLoc);
} else {
throw new Error(`Unexpected location update: ${JSON.stringify(oldLoc)}`);
}
aggregator.push(newLoc);
aggregator.set(serialize(oldLoc), newLoc);
}
let loc1 = { url: JS_URL, line: 6 };
@ -51,7 +48,9 @@ add_task(function* () {
yield createScript(JS_URL);
yield sourceShown;
yield waitUntil(() => aggregator.length === 2);
yield waitUntil(() => aggregator.size === 2);
aggregator = Array.from(aggregator.values());
ok(aggregator.find(i => i.url === COFFEE_URL && i.line === 4), "found first updated location");
ok(aggregator.find(i => i.url === COFFEE_URL && i.line === 6), "found second updated location");

View File

@ -591,7 +591,12 @@ Toolbox.prototype = {
["forceReload2", true]
].forEach(([id, force]) => {
let key = toolboxStrings("toolbox." + id + ".key");
shortcuts.on(key, this.reloadTarget.bind(this, force));
shortcuts.on(key, (name, event) => {
this.reloadTarget(force);
// Prevent Firefox shortcuts from reloading the page
event.preventDefault();
});
});
},

View File

@ -17,7 +17,9 @@ const {LocalizationHelper} = require("devtools/client/shared/l10n");
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
const STRINGS_URI = "chrome://devtools/locale/shared.properties";
const STRINGS_INSPECTOR = "chrome://devtools-shared/locale/styleinspector.properties";
const SHARED_L10N = new LocalizationHelper(STRINGS_URI);
const INSPECTOR_L10N = new LocalizationHelper(STRINGS_INSPECTOR);
const NUMERIC = /^-?[\d\.]+$/;
const LONG_TEXT_ROTATE_LIMIT = 3;
@ -734,8 +736,14 @@ LayoutView.prototype = {
title += "\n" + sourceRule.selectors.join(", ");
}
if (sourceRule && sourceRule.parentStyleSheet) {
title += "\n" + sourceRule.parentStyleSheet.href + ":" + sourceRule.line;
if (sourceRule.parentStyleSheet.href) {
title += "\n" + sourceRule.parentStyleSheet.href + ":" + sourceRule.line;
} else {
title += "\n" + INSPECTOR_L10N.getStr("rule.sourceInline") +
":" + sourceRule.line;
}
}
el.setAttribute("title", title);
},

View File

@ -28,45 +28,45 @@ const VALUES_TEST_DATA = [{
values: [{
name: "margin-top",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
styleSheetLocation: "inline:1"
}, {
name: "margin-right",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
styleSheetLocation: "inline:1"
}, {
name: "margin-bottom",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
styleSheetLocation: "inline:1"
}, {
name: "margin-left",
ruleSelector: "#div1",
styleSheetLocation: "null:1"
styleSheetLocation: "inline:1"
}]
}, {
selector: "#div2",
values: [{
name: "border-bottom-width",
ruleSelector: "#div2",
styleSheetLocation: "null:2"
styleSheetLocation: "inline:2"
}]
}, {
selector: "#div3",
values: [{
name: "padding-top",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
styleSheetLocation: "inline:3"
}, {
name: "padding-right",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
styleSheetLocation: "inline:3"
}, {
name: "padding-bottom",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
styleSheetLocation: "inline:3"
}, {
name: "padding-left",
ruleSelector: "html, body, #div3",
styleSheetLocation: "null:3"
styleSheetLocation: "inline:3"
}]
}];

View File

@ -14,7 +14,7 @@ add_task(function* () {
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
helper.prefix = ID;
let {show, synthesizeKey, finalize} = helper;
let {show, finalize} = helper;
info("Show the eyedropper with the copyOnSelect option");
yield show("html", {copyOnSelect: true});
@ -24,8 +24,7 @@ add_task(function* () {
yield waitForClipboard(() => {
info("Activate the eyedropper so the background color is copied");
let generateKey = synthesizeKey({key: "VK_RETURN", options: {}});
generateKey.next();
EventUtils.synthesizeKey("VK_RETURN", {});
}, "#FF0000");
ok(true, "The clipboard contains the right value");

View File

@ -35,7 +35,7 @@ add_task(function* () {
function* respondsToMoveEvents(helper) {
info("Checking that the eyedropper responds to events from the mouse and keyboard");
let {mouse, synthesizeKey} = helper;
let {mouse} = helper;
for (let {type, x, y, key, shift, expected} of MOVE_EVENTS_DATA) {
info(`Simulating a ${type} event to move to ${expected.x} ${expected.y}`);
@ -43,7 +43,7 @@ function* respondsToMoveEvents(helper) {
yield mouse.move(x, y);
} else if (type === "keyboard") {
let options = shift ? {shiftKey: true} : {};
yield synthesizeKey({key, options});
yield EventUtils.synthesizeKey(key, options);
}
yield checkPosition(expected, helper);
}
@ -55,17 +55,17 @@ function* checkPosition({x, y}, {getElementAttribute}) {
`The eyedropper is at the expected ${x} ${y} position`);
}
function* respondsToReturnAndEscape({synthesizeKey, isElementHidden, show}) {
function* respondsToReturnAndEscape({isElementHidden, show}) {
info("Simulating return to select the color and hide the eyedropper");
yield synthesizeKey({key: "VK_RETURN", options: {}});
yield EventUtils.synthesizeKey("VK_RETURN", {});
let hidden = yield isElementHidden("root");
ok(hidden, "The eyedropper has been hidden");
info("Showing the eyedropper again and simulating escape to hide it");
yield show("html");
yield synthesizeKey({key: "VK_ESCAPE", options: {}});
yield EventUtils.synthesizeKey("VK_ESCAPE", {});
hidden = yield isElementHidden("root");
ok(hidden, "The eyedropper has been hidden again");
}

View File

@ -465,10 +465,6 @@ const getHighlighterHelperFor = (type) => Task.async(
yield testActor.synthesizeMouse(options);
},
synthesizeKey: function* (options) {
yield testActor.synthesizeKey(options);
},
// This object will synthesize any "mouse" prefixed event to the
// `testActor`, using the name of method called as suffix for the
// event's name.

View File

@ -56,6 +56,10 @@ function makeMemoryTest(url, generator) {
return Task.async(function* () {
waitForExplicitFinish();
// It can take a long time to save a snapshot to disk, read the snapshots
// back from disk, and finally perform analyses on them.
requestLongerTimeout(2);
const tab = yield addTab(url);
const results = yield openMemoryPanel(tab);

View File

@ -112,7 +112,6 @@ skip-if = (os == 'linux' && e10s && debug) # Bug 1242204
[browser_net_reload-markers.js]
[browser_net_req-resp-bodies.js]
[browser_net_resend.js]
skip-if = e10s # Bug 1091612
[browser_net_security-details.js]
[browser_net_security-error.js]
[browser_net_security-icon-click.js]

View File

@ -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"',

View File

@ -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");

View File

@ -180,6 +180,16 @@ function tunnelToInnerBrowser(outer, inner) {
outer.setDocShellIsActiveAndForeground = value => {
inner.frameLoader.tabParent.setDocShellIsActiveAndForeground(value);
};
// Make the PopupNotifications object available on the iframe's owner
// This is used for permission doorhangers
Object.defineProperty(inner.ownerGlobal, "PopupNotifications", {
get() {
return outer.ownerGlobal.PopupNotifications;
},
configurable: true,
enumerable: true,
});
}),
stop() {
@ -210,6 +220,9 @@ function tunnelToInnerBrowser(outer, inner) {
delete outer.docShellIsActive;
delete outer.setDocShellIsActiveAndForeground;
// Delete the PopupNotifications getter added for permission doorhangers
delete inner.ownerGlobal.PopupNotifications;
mmTunnel.destroy();
mmTunnel = null;

View File

@ -6,6 +6,7 @@ skip-if = !e10s
support-files =
devices.json
doc_page_state.html
geolocation.html
head.js
!/devtools/client/commandline/test/helpers.js
!/devtools/client/framework/test/shared-head.js
@ -25,6 +26,7 @@ support-files =
[browser_mouse_resize.js]
[browser_navigation.js]
[browser_page_state.js]
[browser_permission_doorhanger.js]
[browser_resize_cmd.js]
skip-if = true # GCLI target confused after swap, will fix in bug 1240912
[browser_screenshot_button.js]

View File

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that permission popups asking for user approval still appear in RDM
const DUMMY_URL = "http://example.com/";
const TEST_URL = `${URL_ROOT}geolocation.html`;
function waitForGeolocationPrompt(win, browser) {
return new Promise(resolve => {
win.PopupNotifications.panel.addEventListener("popupshown", function popupShown() {
let notification = win.PopupNotifications.getNotification("geolocation", browser);
if (notification) {
win.PopupNotifications.panel.removeEventListener("popupshown", popupShown);
resolve();
}
});
});
}
add_task(function* () {
let tab = yield addTab(DUMMY_URL);
let browser = tab.linkedBrowser;
let win = browser.ownerGlobal;
let waitPromptPromise = waitForGeolocationPrompt(win, browser);
// Checks if a geolocation permission doorhanger appears when openning a page
// requesting geolocation
yield load(browser, TEST_URL);
yield waitPromptPromise;
ok(true, "Permission doorhanger appeared without RDM enabled");
// Lets switch back to the dummy website and enable RDM
yield load(browser, DUMMY_URL);
let { ui } = yield openRDM(tab);
let newBrowser = ui.getViewportBrowser();
waitPromptPromise = waitForGeolocationPrompt(win, newBrowser);
// Checks if the doorhanger appeared again when reloading the geolocation
// page inside RDM
yield load(browser, TEST_URL);
yield waitPromptPromise;
ok(true, "Permission doorhanger appeared inside RDM");
yield closeRDM(tab);
yield removeTab(tab);
});

View File

@ -0,0 +1,13 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Geolocation permission test</title>
</head>
<body>
<script type="text/javascript">
"use strict";
navigator.geolocation.getCurrentPosition(function (pos) {});
</script>
</body>
</html>

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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");

View File

@ -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) {

View File

@ -1,6 +1,6 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#0b0b0b">
<path d="M6.7 8l3.6-3.6c.2-.2.2-.5 0-.7-.2-.2-.5-.2-.7 0L6 7.3 2.4 3.7c-.2-.2-.5-.2-.7 0-.2.2-.2.5 0 .7L5.3 8l-3.6 3.6c-.2.2-.2.5 0 .7.2.2.5.2.7 0L6 8.7l3.6 3.6c.2.2.5.2.7 0 .2-.2.2-.5 0-.7L6.7 8z"/>
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#0b0b0b">
<path d="M8.707 8l4.23 4.23a.5.5 0 1 1-.707.707L8 8.707l-4.23 4.23a.5.5 0 1 1-.707-.707L7.293 8l-4.23-4.23a.5.5 0 1 1 .707-.707L8 7.293l4.23-4.23a.5.5 0 0 1 .707.707L8.707 8z" fill-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 518 B

View File

@ -164,10 +164,7 @@
function checkResults() {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId.endsWith("_PER_USER_FLAG")) {
ok(value.length === 1 && !!value[0],
"Per user value " + histId + " has a single value of true");
} else if (histId === "DEVTOOLS_WEBIDE_IMPORT_PROJECT_BOOLEAN") {
if (histId === "DEVTOOLS_WEBIDE_IMPORT_PROJECT_BOOLEAN") {
ok(value.length === 1 && !!value[0],
histId + " has 1 successful entry");
} else if (histId ===

View File

@ -158,7 +158,7 @@ EyeDropper.prototype = {
this.moveTo(DEFAULT_START_POS_X, DEFAULT_START_POS_Y);
// Focus the content so the keyboard can be used.
this.win.document.documentElement.focus();
this.win.focus();
return true;
},
@ -360,14 +360,22 @@ EyeDropper.prototype = {
* direction depending on the key pressed.
*/
handleKeyDown(e) {
// Bail out early if any unsupported modifier is used, so that we let
// keyboard shortcuts through.
if (e.metaKey || e.ctrlKey || e.altKey) {
return;
}
if (e.keyCode === e.DOM_VK_RETURN) {
this.selectColor();
e.preventDefault();
return;
}
if (e.keyCode === e.DOM_VK_ESCAPE) {
this.emit("canceled");
this.hide();
e.preventDefault();
return;
}
@ -377,16 +385,14 @@ EyeDropper.prototype = {
if (e.keyCode === e.DOM_VK_LEFT) {
offsetX = -1;
}
if (e.keyCode === e.DOM_VK_RIGHT) {
} else if (e.keyCode === e.DOM_VK_RIGHT) {
offsetX = 1;
}
if (e.keyCode === e.DOM_VK_UP) {
} else if (e.keyCode === e.DOM_VK_UP) {
offsetY = -1;
}
if (e.keyCode === e.DOM_VK_DOWN) {
} else if (e.keyCode === e.DOM_VK_DOWN) {
offsetY = 1;
}
if (e.shiftKey) {
modifier = 10;
}
@ -402,12 +408,7 @@ EyeDropper.prototype = {
this.moveTo(this.magnifiedArea.x / this.pageZoom,
this.magnifiedArea.y / this.pageZoom);
}
// Prevent all keyboard interaction with the page, except if a modifier is used to let
// keyboard shortcuts through.
let hasModifier = e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
if (!hasModifier) {
e.preventDefault();
}
},

View File

@ -1511,15 +1511,13 @@ WebConsoleActor.prototype =
*
* @param object aEvent
* The initial network request event information.
* @param nsIHttpChannel aChannel
* The network request nsIHttpChannel object.
* @return object
* A new NetworkEventActor is returned. This is used for tracking the
* network request and response.
*/
onNetworkEvent: function WCA_onNetworkEvent(aEvent, aChannel)
onNetworkEvent: function WCA_onNetworkEvent(aEvent)
{
let actor = this.getNetworkEventActor(aChannel);
let actor = this.getNetworkEventActor(aEvent.channelId);
actor.init(aEvent);
let packet = {
@ -1534,24 +1532,23 @@ WebConsoleActor.prototype =
},
/**
* Get the NetworkEventActor for a nsIChannel, if it exists,
* Get the NetworkEventActor for a nsIHttpChannel, if it exists,
* otherwise create a new one.
*
* @param nsIHttpChannel aChannel
* The channel for the network event.
* @param string channelId
* The id of the channel for the network event.
* @return object
* The NetworkEventActor for the given channel.
*/
getNetworkEventActor: function WCA_getNetworkEventActor(aChannel) {
let actor = this._netEvents.get(aChannel);
getNetworkEventActor: function WCA_getNetworkEventActor(channelId) {
let actor = this._netEvents.get(channelId);
if (actor) {
// delete from map as we should only need to do this check once
this._netEvents.delete(aChannel);
actor.channel = null;
this._netEvents.delete(channelId);
return actor;
}
actor = new NetworkEventActor(aChannel, this);
actor = new NetworkEventActor(this);
this._actorPool.addActor(actor);
return actor;
},
@ -1575,10 +1572,11 @@ WebConsoleActor.prototype =
}
request.send(details.body);
let actor = this.getNetworkEventActor(request.channel);
let channel = request.channel.QueryInterface(Ci.nsIHttpChannel);
let actor = this.getNetworkEventActor(channel.channelId);
// map channel to actor so we can associate future events with it
this._netEvents.set(request.channel, actor);
this._netEvents.set(channel.channelId, actor);
return {
from: this.actorID,
@ -1802,16 +1800,12 @@ exports.WebConsoleActor = WebConsoleActor;
* Creates an actor for a network event.
*
* @constructor
* @param object aChannel
* The nsIChannel associated with this event.
* @param object aWebConsoleActor
* @param object webConsoleActor
* The parent WebConsoleActor instance for this object.
*/
function NetworkEventActor(aChannel, aWebConsoleActor)
{
this.parent = aWebConsoleActor;
function NetworkEventActor(webConsoleActor) {
this.parent = webConsoleActor;
this.conn = this.parent.conn;
this.channel = aChannel;
this._request = {
method: null,

View File

@ -29,7 +29,6 @@ using namespace testing;
// GTest fixture class that all of our tests derive from.
struct DevTools : public ::testing::Test {
bool _initialized;
JSRuntime* rt;
JSContext* cx;
JSCompartment* compartment;
JS::Zone* zone;
@ -37,23 +36,19 @@ struct DevTools : public ::testing::Test {
DevTools()
: _initialized(false),
rt(nullptr),
cx(nullptr)
{ }
virtual void SetUp() {
MOZ_ASSERT(!_initialized);
rt = getRuntime();
if (!rt)
cx = getContext();
if (!cx)
return;
MOZ_RELEASE_ASSERT(!cx);
cx = JS_GetContext(rt);
JS_BeginRequest(cx);
global.init(rt, createGlobal());
global.init(cx, createGlobal());
if (!global)
return;
JS_EnterCompartment(cx, global);
@ -64,8 +59,8 @@ struct DevTools : public ::testing::Test {
_initialized = true;
}
JSRuntime* getRuntime() {
return CycleCollectedJSRuntime::Get()->Runtime();
JSContext* getContext() {
return CycleCollectedJSRuntime::Get()->Context();
}
static void reportError(JSContext* cx, const char* message, JSErrorReport* report) {

View File

@ -722,15 +722,14 @@ NetworkResponseListener.prototype = {
* logged.
* @param object owner
* The network monitor owner. This object needs to hold:
* - onNetworkEvent(requestInfo, channel, networkMonitor).
* - onNetworkEvent(requestInfo)
* This method is invoked once for every new network request and it is
* given the following arguments: the initial network request
* information, and the channel. The third argument is the NetworkMonitor
* instance. onNetworkEvent() must return an object which holds several add*()
* methods which are used to add further network request/response
* information.
* - stackTraceCollector If the owner has this optional property, it will
* be used as a StackTraceCollector by the NetworkMonitor.
* given the initial network request information as an argument.
* onNetworkEvent() must return an object which holds several add*()
* methods which are used to add further network request/response information.
* - stackTraceCollector
* If the owner has this optional property, it will be used as a
* StackTraceCollector by the NetworkMonitor.
*/
function NetworkMonitor(filters, owner) {
this.filters = filters;
@ -1089,7 +1088,7 @@ NetworkMonitor.prototype = {
cookies = NetworkHelper.parseCookieHeader(cookieHeader);
}
httpActivity.owner = this.owner.onNetworkEvent(event, channel);
httpActivity.owner = this.owner.onNetworkEvent(event);
this._setupResponseListener(httpActivity);

View File

@ -9502,7 +9502,7 @@ public:
{
}
NS_IMETHODIMP
NS_IMETHOD
OnComplete(nsIURI* aFaviconURI, uint32_t aDataLen,
const uint8_t* aData, const nsACString& aMimeType) override
{

View File

@ -23,7 +23,7 @@ using mozilla::dom::DOMRequestService;
using mozilla::dom::DOMCursor;
using mozilla::dom::Promise;
using mozilla::dom::AutoJSAPI;
using mozilla::dom::GetJSRuntime;
using mozilla::dom::RootingCx;
DOMRequest::DOMRequest(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow)
@ -302,7 +302,7 @@ class FireSuccessAsyncTask : public mozilla::Runnable
FireSuccessAsyncTask(DOMRequest* aRequest,
const JS::Value& aResult) :
mReq(aRequest),
mResult(GetJSRuntime(), aResult)
mResult(RootingCx(), aResult)
{
}

View File

@ -511,6 +511,12 @@ private:
oldTextNode);
}
if (newTextNode) {
nsINode* oldDirAutoSetBy =
static_cast<nsTextNode*>(rootNode->GetProperty(nsGkAtoms::dirAutoSetBy));
if (oldDirAutoSetBy == newTextNode) {
// We're already registered.
return OpNext;
}
nsTextNodeDirectionalityMap::AddEntryToMap(newTextNode, rootNode);
} else {
rootNode->ClearHasDirAutoSet();
@ -684,7 +690,9 @@ WalkDescendantsResetAutoDirection(Element* aElement)
if (child->NodeType() == nsIDOMNode::TEXT_NODE &&
child->HasTextNodeDirectionalityMap()) {
nsTextNodeDirectionalityMap::ResetTextNodeDirection(static_cast<nsTextNode*>(child), nullptr);
nsTextNodeDirectionalityMap::EnsureMapIsClearFor(child);
// Don't call nsTextNodeDirectionalityMap::EnsureMapIsClearFor(child)
// since ResetTextNodeDirection may have kept elements in child's
// DirectionalityMap.
}
child = child->GetNextNode(aElement);
}

View File

@ -147,6 +147,7 @@
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
#include "nsComputedDOMStyle.h"
#include "nsDOMStringMap.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -3862,3 +3863,29 @@ Element::GetReferrerPolicyAsEnum()
}
return net::RP_Unset;
}
already_AddRefed<nsDOMStringMap>
Element::Dataset()
{
nsDOMSlots *slots = DOMSlots();
if (!slots->mDataset) {
// mDataset is a weak reference so assignment will not AddRef.
// AddRef is called before returning the pointer.
slots->mDataset = new nsDOMStringMap(this);
}
RefPtr<nsDOMStringMap> ret = slots->mDataset;
return ret.forget();
}
void
Element::ClearDataset()
{
nsDOMSlots *slots = GetExistingDOMSlots();
MOZ_ASSERT(slots && slots->mDataset,
"Slots should exist and dataset should not be null.");
slots->mDataset = nullptr;
}

View File

@ -53,6 +53,7 @@ class nsGlobalWindow;
class nsICSSDeclaration;
class nsISMILAttr;
class nsDocument;
class nsDOMStringMap;
namespace mozilla {
namespace dom {
@ -1142,6 +1143,16 @@ public:
net::ReferrerPolicy GetReferrerPolicyAsEnum();
/*
* Helpers for .dataset. This is implemented on Element, though only some
* sorts of elements expose it to JS as a .dataset property
*/
// Getter, to be called from bindings.
already_AddRefed<nsDOMStringMap> Dataset();
// Callback for destructor of dataset to ensure to null out our weak pointer
// to it.
void ClearDataset();
protected:
/*
* Named-bools for use with SetAttrAndNotify to make call sites easier to

View File

@ -181,7 +181,7 @@ FileReader::GetResult(JSContext* aCx,
}
}
static NS_IMETHODIMP
static NS_METHOD
ReadFuncBinaryString(nsIInputStream* in,
void* closure,
const char* fromRawSegment,

View File

@ -496,7 +496,7 @@ class EncoderThreadPoolTerminator final : public nsIObserver
public:
NS_DECL_ISUPPORTS
NS_IMETHODIMP Observe(nsISupports *, const char *topic, const char16_t *) override
NS_IMETHOD Observe(nsISupports *, const char *topic, const char16_t *) override
{
NS_ASSERTION(!strcmp(topic, "xpcom-shutdown-threads"),
"Unexpected topic");

View File

@ -293,10 +293,10 @@ GetJSContext()
}
} // namespace danger
JSRuntime*
GetJSRuntime()
JS::RootingContext*
RootingCx()
{
return CycleCollectedJSRuntime::Get()->Runtime();
return CycleCollectedJSRuntime::Get()->RootingCx();
}
AutoJSAPI::AutoJSAPI()
@ -590,7 +590,8 @@ AutoJSAPI::ReportException()
nsContentUtils::IsCallerChrome(),
inner ? inner->WindowID() : 0);
if (inner && jsReport.report()->errorNumber != JSMSG_OUT_OF_MEMORY) {
DispatchScriptErrorEvent(inner, JS_GetRuntime(cx()), xpcReport, exn);
JS::RootingContext* rcx = JS::RootingContext::get(cx());
DispatchScriptErrorEvent(inner, rcx, xpcReport, exn);
} else {
JS::Rooted<JSObject*> stack(cx(),
xpc::FindExceptionStackForConsoleReport(inner, exn));

View File

@ -136,7 +136,7 @@ JSContext* GetJSContext();
} // namespace danger
JSRuntime* GetJSRuntime();
JS::RootingContext* RootingCx();
class ScriptSettingsStack;
class ScriptSettingsStackEntry {

View File

@ -79,6 +79,7 @@
#include "nsContentDLF.h"
#include "nsContentList.h"
#include "nsContentPolicyUtils.h"
#include "nsContentSecurityManager.h"
#include "nsCPrefetchService.h"
#include "nsCRT.h"
#include "nsCycleCollectionParticipant.h"
@ -2790,7 +2791,10 @@ nsIPrincipal*
nsContentUtils::ObjectPrincipal(JSObject* aObj)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(JS_GetObjectRuntime(aObj) == CycleCollectedJSRuntime::Get()->Runtime());
#ifdef DEBUG
JS::AssertObjectBelongsToCurrentThread(aObj);
#endif
// This is duplicated from nsScriptSecurityManager. We don't call through there
// because the API unnecessarily requires a JSContext for historical reasons.
@ -9275,3 +9279,100 @@ nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget)
return nullptr;
}
/*
* Note: this function only relates to figuring out HTTPS state, which is an
* input to the Secure Context algorithm. We are not actually implementing any
* part of the Secure Context algorithm itself here.
*
* This is a bit of a hack. Ideally we'd propagate HTTPS state through
* nsIChannel as described in the Fetch and HTML specs, but making channels
* know about whether they should inherit HTTPS state, propagating information
* about who the channel's "client" is, exposing GetHttpsState API on channels
* and modifying the various cache implementations to store and retrieve HTTPS
* state involves a huge amount of code (see bug 1220687). We avoid that for
* now using this function.
*
* This function takes advantage of the observation that we can return true if
* nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
* the document's origin (e.g. the origin has a scheme of 'https' or host
* 'localhost' etc.). Since we generally propagate a creator document's origin
* onto data:, blob:, etc. documents, this works for them too.
*
* The scenario where this observation breaks down is sandboxing without the
* 'allow-same-origin' flag, since in this case a document is given a unique
* origin (IsOriginPotentiallyTrustworthy would return false). We handle that
* by using the origin that the document would have had had it not been
* sandboxed.
*
* DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
* getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
* sandboxing is limited to the immediate sandbox. In the case that aDocument
* should inherit its origin (e.g. data: URI) but its parent has ended up
* with a unique origin due to sandboxing further up the parent chain we may
* end up returning false when we would ideally return true (since we will
* examine the parent's origin for 'https' and not finding it.) This means
* that we may restrict the privileges of some pages unnecessarily in this
* edge case.
*/
/* static */ bool
nsContentUtils::HttpsStateIsModern(nsIDocument* aDocument)
{
if (!aDocument) {
return false;
}
nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
if (principal->GetIsSystemPrincipal()) {
return true;
}
// If aDocument is sandboxed, try and get the principal that it would have
// been given had it not been sandboxed:
if (principal->GetIsNullPrincipal() &&
(aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
nsIChannel* channel = aDocument->GetChannel();
if (channel) {
nsCOMPtr<nsIScriptSecurityManager> ssm =
nsContentUtils::GetSecurityManager();
nsresult rv =
ssm->GetChannelResultPrincipalIfNotSandboxed(channel,
getter_AddRefs(principal));
if (NS_FAILED(rv)) {
return false;
}
if (principal->GetIsSystemPrincipal()) {
// If a document with the system principal is sandboxing a subdocument
// that would normally inherit the embedding element's principal (e.g.
// a srcdoc document) then the embedding document does not trust the
// content that is written to the embedded document. Unlike when the
// embedding document is https, in this case we have no indication as
// to whether the embedded document's contents are delivered securely
// or not, and the sandboxing would possibly indicate that they were
// not. To play it safe we return false here. (See bug 1162772
// comment 73-80.)
return false;
}
}
}
if (principal->GetIsNullPrincipal()) {
return false;
}
MOZ_ASSERT(principal->GetIsCodebasePrincipal());
nsCOMPtr<nsIContentSecurityManager> csm =
do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
NS_WARN_IF(!csm);
if (csm) {
bool isTrustworthyOrigin = false;
csm->IsOriginPotentiallyTrustworthy(principal, &isTrustworthyOrigin);
if (isTrustworthyOrigin) {
return true;
}
}
return false;
}

View File

@ -1739,9 +1739,6 @@ public:
static JSContext *GetCurrentJSContext();
static JSContext *GetCurrentJSContextForThread();
inline static JSContext *RootingCx() {
return mozilla::dom::danger::GetJSContext();
}
/**
* Case insensitive comparison between two strings. However it only ignores
@ -2666,6 +2663,14 @@ public:
*/
static nsIDocShell* GetDocShellForEventTarget(mozilla::dom::EventTarget* aTarget);
/**
* Returns true if the "HTTPS state" of the document should be "modern". See:
*
* https://html.spec.whatwg.org/#concept-document-https-state
* https://fetch.spec.whatwg.org/#concept-response-https-state
*/
static bool HttpsStateIsModern(nsIDocument* aDocument);
private:
static bool InitializeEventTable();

View File

@ -1535,7 +1535,7 @@ public:
explicit nsFrameLoaderDestroyRunnable(nsFrameLoader* aFrameLoader)
: mFrameLoader(aFrameLoader), mPhase(eDestroyDocShell) {}
NS_IMETHODIMP Run() override;
NS_IMETHOD Run() override;
};
void
@ -2735,8 +2735,10 @@ class nsAsyncMessageToChild : public nsSameProcessAsyncMessageBase,
public Runnable
{
public:
nsAsyncMessageToChild(JSContext* aCx, JS::Handle<JSObject*> aCpows, nsFrameLoader* aFrameLoader)
: nsSameProcessAsyncMessageBase(aCx, aCpows)
nsAsyncMessageToChild(JS::RootingContext* aRootingCx,
JS::Handle<JSObject*> aCpows,
nsFrameLoader* aFrameLoader)
: nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
, mFrameLoader(aFrameLoader)
{
}
@ -2786,8 +2788,9 @@ nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
}
if (mChildMessageManager) {
RefPtr<nsAsyncMessageToChild> ev = new nsAsyncMessageToChild(aCx, aCpows, this);
nsresult rv = ev->Init(aCx, aMessage, aData, aPrincipal);
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
RefPtr<nsAsyncMessageToChild> ev = new nsAsyncMessageToChild(rcx, aCpows, this);
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}

View File

@ -1711,8 +1711,8 @@ nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL,
return;
}
JSRuntime* rt = CycleCollectedJSRuntime::Get()->Runtime();
JS::Rooted<JSScript*> script(rt);
JS::RootingContext* rcx = RootingCx();
JS::Rooted<JSScript*> script(rcx);
nsMessageManagerScriptHolder* holder = sCachedScripts->Get(aURL);
if (holder && holder->WillRunInGlobalScope() == aRunInGlobalScope) {
@ -1725,7 +1725,7 @@ nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL,
shouldCache, &script);
}
JS::Rooted<JSObject*> global(rt, mGlobal->GetJSObject());
JS::Rooted<JSObject*> global(rcx, mGlobal->GetJSObject());
if (global) {
AutoEntryScript aes(global, "message manager script load");
JSContext* cx = aes.cx();
@ -1845,7 +1845,7 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
const nsAString& aURL,
bool aRunInGlobalScope)
{
JS::Rooted<JSScript*> script(nsContentUtils::RootingCx());
JS::Rooted<JSScript*> script(RootingCx());
TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope, true, &script);
}
@ -1914,8 +1914,9 @@ class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase,
public Runnable
{
public:
nsAsyncMessageToSameProcessChild(JSContext* aCx, JS::Handle<JSObject*> aCpows)
: nsSameProcessAsyncMessageBase(aCx, aCpows)
nsAsyncMessageToSameProcessChild(JS::RootingContext* aRootingCx,
JS::Handle<JSObject*> aCpows)
: nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
{ }
NS_IMETHOD Run() override
{
@ -1956,10 +1957,11 @@ public:
JS::Handle<JSObject *> aCpows,
nsIPrincipal* aPrincipal) override
{
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
RefPtr<nsAsyncMessageToSameProcessChild> ev =
new nsAsyncMessageToSameProcessChild(aCx, aCpows);
new nsAsyncMessageToSameProcessChild(rcx, aCpows);
nsresult rv = ev->Init(aCx, aMessage, aData, aPrincipal);
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
}
@ -2073,8 +2075,9 @@ class nsAsyncMessageToSameProcessParent : public nsSameProcessAsyncMessageBase,
public SameProcessMessageQueue::Runnable
{
public:
nsAsyncMessageToSameProcessParent(JSContext* aCx, JS::Handle<JSObject*> aCpows)
: nsSameProcessAsyncMessageBase(aCx, aCpows)
nsAsyncMessageToSameProcessParent(JS::RootingContext* aRootingCx,
JS::Handle<JSObject*> aCpows)
: nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
{ }
virtual nsresult HandleMessage() override
{
@ -2111,7 +2114,7 @@ public:
queue->Flush();
if (nsFrameMessageManager::sSameProcessParentManager) {
SameProcessCpowHolder cpows(js::GetRuntime(aCx), aCpows);
SameProcessCpowHolder cpows(JS::RootingContext::get(aCx), aCpows);
RefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr, aMessage,
true, &aData, &cpows, aPrincipal, aRetVal);
@ -2126,9 +2129,10 @@ public:
nsIPrincipal* aPrincipal) override
{
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
RefPtr<nsAsyncMessageToSameProcessParent> ev =
new nsAsyncMessageToSameProcessParent(aCx, aCpows);
nsresult rv = ev->Init(aCx, aMessage, aData, aPrincipal);
new nsAsyncMessageToSameProcessParent(rcx, aCpows);
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
if (NS_FAILED(rv)) {
return rv;
@ -2226,15 +2230,18 @@ nsFrameMessageManager::MarkForCC()
return true;
}
nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JSContext* aCx, JS::Handle<JSObject*> aCpows)
: mRuntime(nullptr)
, mCpows(aCx, aCpows)
nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JS::RootingContext* aRootingCx,
JS::Handle<JSObject*> aCpows)
: mRootingCx(aRootingCx)
, mCpows(aRootingCx, aCpows)
#ifdef DEBUG
, mCalledInit(false)
#endif
{ }
nsresult
nsSameProcessAsyncMessageBase::Init(JSContext* aCx,
const nsAString& aMessage,
nsSameProcessAsyncMessageBase::Init(const nsAString& aMessage,
StructuredCloneData& aData,
nsIPrincipal* aPrincipal)
{
@ -2243,9 +2250,11 @@ nsSameProcessAsyncMessageBase::Init(JSContext* aCx,
return NS_ERROR_OUT_OF_MEMORY;
}
mRuntime = js::GetRuntime(aCx);
mMessage = aMessage;
mPrincipal = aPrincipal;
#ifdef DEBUG
mCalledInit = true;
#endif
return NS_OK;
}
@ -2256,9 +2265,9 @@ nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget,
nsFrameMessageManager* aManager)
{
// Make sure that we have called Init() and it has succeeded.
MOZ_ASSERT(mRuntime);
MOZ_ASSERT(mCalledInit);
if (aManager) {
SameProcessCpowHolder cpows(mRuntime, mCpows);
SameProcessCpowHolder cpows(mRootingCx, mCpows);
RefPtr<nsFrameMessageManager> mm = aManager;
mm->ReceiveMessage(aTarget, aTargetFrameLoader, mMessage, false, &mData,

View File

@ -145,8 +145,8 @@ struct nsMessageListenerInfo
class MOZ_STACK_CLASS SameProcessCpowHolder : public mozilla::jsipc::CpowHolder
{
public:
SameProcessCpowHolder(JSRuntime *aRuntime, JS::Handle<JSObject*> aObj)
: mObj(aRuntime, aObj)
SameProcessCpowHolder(JS::RootingContext* aRootingCx, JS::Handle<JSObject*> aObj)
: mObj(aRootingCx, aObj)
{
}
@ -338,9 +338,9 @@ class nsSameProcessAsyncMessageBase
public:
typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
nsSameProcessAsyncMessageBase(JSContext* aCx, JS::Handle<JSObject*> aCpows);
nsresult Init(JSContext* aCx,
const nsAString& aMessage,
nsSameProcessAsyncMessageBase(JS::RootingContext* aRootingCx,
JS::Handle<JSObject*> aCpows);
nsresult Init(const nsAString& aMessage,
StructuredCloneData& aData,
nsIPrincipal* aPrincipal);
@ -349,11 +349,14 @@ public:
private:
nsSameProcessAsyncMessageBase(const nsSameProcessAsyncMessageBase&);
JSRuntime* mRuntime;
JS::RootingContext* mRootingCx;
nsString mMessage;
StructuredCloneData mData;
JS::PersistentRooted<JSObject*> mCpows;
nsCOMPtr<nsIPrincipal> mPrincipal;
#ifdef DEBUG
bool mCalledInit;
#endif
};
class nsScriptCacheCleaner;
@ -425,9 +428,9 @@ class nsScriptCacheCleaner final : public nsIObserver
}
}
NS_IMETHODIMP Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData) override
NS_IMETHOD Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData) override
{
if (strcmp("message-manager-flush-caches", aTopic) == 0) {
nsMessageManagerScriptExecutor::PurgeCache();

Some files were not shown because too many files have changed in this diff Show More