Merge mozilla-central to inbound. a=merge CLOSED TREE

--HG--
extra : rebase_source : 4502430f7e773b654c4557946c39000735b14bb3
This commit is contained in:
shindli 2019-02-14 06:58:32 +02:00
Родитель 062b239e89 38035ee924
Коммит c6c323a9e4
126 изменённых файлов: 1691 добавлений и 829 удалений

3
Cargo.lock сгенерированный
Просмотреть файл

@ -1,5 +1,3 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "Inflector"
version = "0.11.2"
@ -3089,6 +3087,7 @@ dependencies = [
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",

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

@ -1814,3 +1814,5 @@ pref("browser.aboutConfig.showWarning", true);
// Launcher process is disabled by default, will be selectively enabled via SHIELD
pref("browser.launcherProcess.enabled", false);
#endif // defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
pref("browser.toolbars.keyboard_navigation", false);

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

@ -0,0 +1,246 @@
/* 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/. */
// This file is loaded into the browser window scope.
/* eslint-env mozilla/browser-window */
/**
* Handle keyboard navigation for toolbars.
* Having separate tab stops for every toolbar control results in an
* unmanageable number of tab stops. Therefore, we group buttons under a single
* tab stop and allow movement between them using left/right arrows.
* However, text inputs use the arrow keys for their own purposes, so they need
* their own tab stop. There are also groups of buttons before and after the
* URL bar input which should get their own tab stop. The subsequent buttons on
* the toolbar are then another tab stop after that.
* Tab stops for groups of buttons are set using the <toolbartabstop/> element.
* This element is invisible, but gets included in the tab order. When one of
* these gets focus, it redirects focus to the appropriate button. This avoids
* the need to continually manage the tabindex of toolbar buttons in response to
* toolbarchanges.
*/
ToolbarKeyboardNavigator = {
// Toolbars we want to be keyboard navigable.
kToolbars: [CustomizableUI.AREA_NAVBAR, CustomizableUI.AREA_BOOKMARKS],
_isButton(aElem) {
return aElem.tagName == "toolbarbutton" ||
aElem.getAttribute("role") == "button";
},
// Get a TreeWalker which includes only controls which should be keyboard
// navigable.
_getWalker(aRoot) {
if (aRoot._toolbarKeyNavWalker) {
return aRoot._toolbarKeyNavWalker;
}
let filter = (aNode) => {
if (aNode.tagName == "toolbartabstop") {
return NodeFilter.FILTER_ACCEPT;
}
// Special case for the "View site information" button, which isn't
// actionable in some cases but is still visible.
if (aNode.id == "identity-box" &&
document.getElementById("urlbar").getAttribute("pageproxystate") ==
"invalid") {
return NodeFilter.FILTER_REJECT;
}
// Skip invisible or disabled elements.
if (aNode.hidden || aNode.disabled) {
return NodeFilter.FILTER_REJECT;
}
// This width check excludes the overflow button when there's no overflow.
let bounds = window.windowUtils.getBoundsWithoutFlushing(aNode);
if (bounds.width == 0) {
return NodeFilter.FILTER_REJECT;
}
if (this._isButton(aNode)) {
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_SKIP;
};
aRoot._toolbarKeyNavWalker = document.createTreeWalker(aRoot,
NodeFilter.SHOW_ELEMENT, filter);
return aRoot._toolbarKeyNavWalker;
},
init() {
for (let id of this.kToolbars) {
let toolbar = document.getElementById(id);
// When enabled, no toolbar buttons should themselves be tabbable.
// We manage toolbar focus completely. This attribute ensures that CSS
// doesn't set -moz-user-focus: normal.
toolbar.setAttribute("keyNav", "true");
for (let stop of toolbar.getElementsByTagName("toolbartabstop")) {
// These are invisible, but because they need to be in the tab order,
// they can't get display: none or similar. They must therefore be
// explicitly hidden for accessibility.
stop.setAttribute("aria-hidden", "true");
stop.addEventListener("focus", this);
}
toolbar.addEventListener("keydown", this);
toolbar.addEventListener("keypress", this);
}
},
uninit() {
for (let id of this.kToolbars) {
let toolbar = document.getElementById(id);
for (let stop of toolbar.getElementsByTagName("toolbartabstop")) {
stop.removeEventListener("focus", this);
}
toolbar.removeEventListener("keydown", this);
toolbar.removeEventListener("keypress", this);
toolbar.removeAttribute("keyNav");
}
},
_focusButton(aButton) {
// Toolbar buttons aren't focusable because if they were, clicking them
// would focus them, which is undesirable. Therefore, we must make a
// button focusable only when we want to focus it.
aButton.setAttribute("tabindex", "-1");
aButton.focus();
// We could remove tabindex now, but even though the button keeps DOM
// focus, a11y gets confused because the button reports as not being
// focusable. This results in weirdness if the user switches windows and
// then switches back. Instead, remove tabindex when the button loses
// focus.
aButton.addEventListener("blur", this);
},
_onButtonBlur(aEvent) {
if (document.activeElement == aEvent.target) {
// This event was fired because the user switched windows. This button
// will get focus again when the user returns.
return;
}
aEvent.target.removeEventListener("blur", this);
aEvent.target.removeAttribute("tabindex");
},
_onTabStopFocus(aEvent) {
let toolbar = aEvent.target.closest("toolbar");
let walker = this._getWalker(toolbar);
let oldFocus = aEvent.relatedTarget;
if (oldFocus) {
// Save this because we might rewind focus and the subsequent focus event
// won't get a relatedTarget.
this._isFocusMovingBackward =
oldFocus.compareDocumentPosition(aEvent.target) &
Node.DOCUMENT_POSITION_PRECEDING;
if (this._isFocusMovingBackward && oldFocus && this._isButton(oldFocus)) {
// Shift+tabbing from a button will land on its toolbartabstop. Skip it.
document.commandDispatcher.rewindFocus();
return;
}
}
walker.currentNode = aEvent.target;
let button = walker.nextNode();
if (!button || !this._isButton(button)) {
// No navigable buttons for this tab stop. Skip it.
if (this._isFocusMovingBackward) {
document.commandDispatcher.rewindFocus();
} else {
document.commandDispatcher.advanceFocus();
}
return;
}
this._focusButton(button);
},
navigateButtons(aToolbar, aPrevious) {
let oldFocus = document.activeElement;
let walker = this._getWalker(aToolbar);
// Start from the current control and walk to the next/previous control.
walker.currentNode = oldFocus;
let newFocus;
if (aPrevious) {
newFocus = walker.previousNode();
} else {
newFocus = walker.nextNode();
}
if (!newFocus || newFocus.tagName == "toolbartabstop") {
// There are no more controls or we hit a tab stop placeholder.
return;
}
this._focusButton(newFocus);
},
_onKeyDown(aEvent) {
let focus = document.activeElement;
if (aEvent.altKey || aEvent.controlKey || aEvent.metaKey ||
aEvent.shiftKey || !this._isButton(focus)) {
return;
}
switch (aEvent.key) {
case "ArrowLeft":
this.navigateButtons(aEvent.currentTarget, true);
break;
case "ArrowRight":
this.navigateButtons(aEvent.currentTarget, false);
break;
default:
return;
}
aEvent.preventDefault();
},
_onKeyPress(aEvent) {
let focus = document.activeElement;
if ((aEvent.key != "Enter" && aEvent.key != " ") ||
!this._isButton(focus)) {
return;
}
if (focus.getAttribute("type") == "menu") {
focus.open = true;
} else {
// Several buttons specifically don't use command events; e.g. because
// they want to activate for middle click. Therefore, simulate a
// click event.
// If this button does handle command events, that won't trigger here.
// Command events have their own keyboard handling: keypress for enter
// and keyup for space. We rely on that behavior, since there's no way
// for us to reliably know what events a button handles.
focus.dispatchEvent(new MouseEvent("click", {
bubbles: true,
ctrlKey: aEvent.ctrlKey,
altKey: aEvent.altKey,
shiftKey: aEvent.shiftKey,
metaKey: aEvent.metaKey,
}));
}
// We deliberately don't call aEvent.preventDefault() here so that enter
// will trigger a command event handler if appropriate.
aEvent.stopPropagation();
},
handleEvent(aEvent) {
switch (aEvent.type) {
case "focus":
this._onTabStopFocus(aEvent);
break;
case "keydown":
this._onKeyDown(aEvent);
break;
case "keypress":
this._onKeyPress(aEvent);
break;
case "blur":
this._onButtonBlur(aEvent);
break;
}
},
};

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

@ -778,7 +778,7 @@ html|input.urlbar-input {
display: none;
}
#identity-box {
#nav-bar:not([keyNav=true]) #identity-box {
-moz-user-focus: normal;
}
@ -981,7 +981,7 @@ html|*#fullscreen-exit-button {
/* notification anchors should only be visible when their associated
notifications are */
.notification-anchor-icon {
#nav-bar:not([keyNav=true]) .notification-anchor-icon {
-moz-user-focus: normal;
}
@ -1427,4 +1427,8 @@ toolbarpaletteitem > toolbaritem {
}
}
toolbar[keyNav=true]:not([collapsed=true]):not([customizing=true]) toolbartabstop {
-moz-user-focus: normal;
}
%include theme-vars.inc.css

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

@ -148,6 +148,8 @@ if (AppConstants.NIGHTLY_BUILD) {
}
XPCOMUtils.defineLazyScriptGetter(this, "pktUI", "chrome://pocket/content/main.js");
XPCOMUtils.defineLazyScriptGetter(this, "ToolbarKeyboardNavigator",
"chrome://browser/content/browser-toolbarKeyNav.js");
// lazy service getters
@ -283,6 +285,16 @@ XPCOMUtils.defineLazyGetter(this, "Win7Features", () => {
return null;
});
XPCOMUtils.defineLazyPreferenceGetter(this, "gToolbarKeyNavEnabled",
"browser.toolbars.keyboard_navigation", false,
(aPref, aOldVal, aNewVal) => {
if (aNewVal) {
ToolbarKeyboardNavigator.init();
} else {
ToolbarKeyboardNavigator.uninit();
}
});
customElements.setElementCreationCallback("translation-notification", () => {
Services.scriptloader.loadSubScript(
"chrome://browser/content/translation-notification.js", window);
@ -1384,6 +1396,9 @@ var gBrowserInit = {
BrowserPageActions.init();
gAccessibilityServiceIndicator.init();
AccessibilityRefreshBlocker.init();
if (gToolbarKeyNavEnabled) {
ToolbarKeyboardNavigator.init();
}
gRemoteControl.updateVisualCue(Marionette.running);
@ -1930,6 +1945,10 @@ var gBrowserInit = {
AccessibilityRefreshBlocker.uninit();
if (gToolbarKeyNavEnabled) {
ToolbarKeyboardNavigator.uninit();
}
LanguagePrompt.uninit();
BrowserSearch.uninit();

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

@ -835,6 +835,7 @@ xmlns="http://www.w3.org/1999/xhtml"
overflowpanel="widget-overflow"
context="toolbar-context-menu">
<toolbartabstop/>
<hbox id="nav-bar-customization-target" flex="1">
<toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
label="&backCmd.label;"
@ -888,6 +889,7 @@ xmlns="http://www.w3.org/1999/xhtml"
<toolbaritem id="urlbar-container" flex="400" persist="width"
removable="false"
class="chromeclass-location" overflows="false">
<toolbartabstop/>
<textbox id="urlbar" flex="1"
placeholder="&urlbar.placeholder2;"
defaultPlaceholder="&urlbar.placeholder2;"
@ -1007,6 +1009,7 @@ xmlns="http://www.w3.org/1999/xhtml"
<label id="extension" class="urlbar-display urlbar-display-extension" value="&urlbar.extension.label;"/>
</box>
<hbox id="page-action-buttons" context="pageActionContextMenu">
<toolbartabstop/>
<hbox id="contextual-feature-recommendation" role="button" hidden="true">
<hbox id="cfr-label-container">
<label id="cfr-label"/>
@ -1064,6 +1067,7 @@ xmlns="http://www.w3.org/1999/xhtml"
</hbox>
</hbox>
</textbox>
<toolbartabstop/>
</toolbaritem>
<toolbarspring cui-areatype="toolbar" class="chromeclass-toolbar-additional"/>
@ -1159,6 +1163,7 @@ xmlns="http://www.w3.org/1999/xhtml"
toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
collapsed="true"
customizable="true">
<toolbartabstop skipintoolbarset="true"/>
<toolbaritem id="personal-bookmarks"
title="&bookmarksToolbarItem.label;"
cui-areatype="toolbar"
@ -1328,7 +1333,9 @@ xmlns="http://www.w3.org/1999/xhtml"
align="center"
flex="100"
persist="width">
<toolbartabstop/>
<searchbar id="searchbar" flex="1"/>
<toolbartabstop/>
</toolbaritem>
</toolbarpalette>
</toolbox>

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

@ -1 +1,3 @@
[browser_toolbarButtonKeyPress.js]
[browser_toolbarKeyNav.js]
support-files = !/browser/base/content/test/permissions/permissions.html

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

@ -30,6 +30,12 @@ function waitForLocationChange() {
return promise;
}
add_task(async function setPref() {
await SpecialPowers.pushPrefEnv({
set: [["browser.toolbars.keyboard_navigation", true]],
});
});
// Test activation of the app menu button from the keyboard.
// The app menu should appear and focus should move inside it.
add_task(async function testAppMenuButtonPress() {
@ -86,6 +92,7 @@ add_task(async function testDeveloperButtonPress() {
await hidden;
CustomizableUI.reset();
});
// Test that the Developer menu doesn't open when a key other than space or
// enter is pressed .
add_task(async function testDeveloperButtonWrongKey() {
@ -159,3 +166,80 @@ add_task(async function testSendTabToDeviceButtonPress() {
PageActions.actionForID("sendToDevice").pinnedToUrlbar = false;
});
});
// Test activation of the Reload button from the keyboard.
// This is a toolbarbutton with a click handler and no command handler, but
// the toolbar keyboard navigation code should handle keyboard activation.
add_task(async function testReloadButtonPress() {
await BrowserTestUtils.withNewTab("https://example.com", async function(aBrowser) {
let button = document.getElementById("reload-button");
await TestUtils.waitForCondition(() => !button.disabled);
forceFocus(button);
let loaded = BrowserTestUtils.browserLoaded(aBrowser);
EventUtils.synthesizeKey(" ");
await loaded;
ok(true, "Page loaded after Reload button pressed");
});
});
// Test activation of the Sidebars button from the keyboard.
// This is a toolbarbutton with a command handler.
add_task(async function testSidebarsButtonPress() {
let button = document.getElementById("sidebar-button");
ok(!button.checked, "Sidebars button not checked at start of test");
let sidebarBox = document.getElementById("sidebar-box");
ok(sidebarBox.hidden, "Sidebar hidden at start of test");
forceFocus(button);
EventUtils.synthesizeKey(" ");
await TestUtils.waitForCondition(() => button.checked);
ok(true, "Sidebars button checked after press");
ok(!sidebarBox.hidden, "Sidebar visible after press");
// Make sure the sidebar is fully loaded before we hide it.
// Otherwise, the unload event might call JS which isn't loaded yet.
// We can't use BrowserTestUtils.browserLoaded because it fails on non-tab
// docs. Instead, wait for something in the JS script.
let sidebarWin = document.getElementById("sidebar").contentWindow;
await TestUtils.waitForCondition(() => sidebarWin.PlacesUIUtils);
forceFocus(button);
EventUtils.synthesizeKey(" ");
await TestUtils.waitForCondition(() => !button.checked);
ok(true, "Sidebars button not checked after press");
ok(sidebarBox.hidden, "Sidebar hidden after press");
});
// Test activation of the Bookmark this page button from the keyboard.
// This is an image with a click handler on its parent and no command handler,
// but the toolbar keyboard navigation code should handle keyboard activation.
add_task(async function testBookmarkButtonPress() {
await BrowserTestUtils.withNewTab("https://example.com", async function(aBrowser) {
let button = document.getElementById("star-button");
forceFocus(button);
let panel = document.getElementById("editBookmarkPanel");
let focused = BrowserTestUtils.waitForEvent(panel, "focus", true);
EventUtils.synthesizeKey(" ");
await focused;
ok(true, "Focus inside edit bookmark panel after Bookmark button pressed");
let hidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
EventUtils.synthesizeKey("KEY_Escape");
await hidden;
});
});
// Test activation of the Bookmarks Menu button from the keyboard.
// This is a button with type="menu".
// The Bookmarks Menu should appear.
add_task(async function testBookmarksmenuButtonPress() {
CustomizableUI.addWidgetToArea("bookmarks-menu-button",
CustomizableUI.AREA_NAVBAR);
let button = document.getElementById("bookmarks-menu-button");
forceFocus(button);
let menu = document.getElementById("BMB_bookmarksPopup");
let shown = BrowserTestUtils.waitForEvent(menu, "popupshown");
EventUtils.synthesizeKey(" ");
await shown;
ok(true, "Bookmarks Menu shown after toolbar button pressed");
let hidden = BrowserTestUtils.waitForEvent(menu, "popuphidden");
menu.hidePopup();
await hidden;
CustomizableUI.reset();
});

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

@ -0,0 +1,219 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test browser toolbar keyboard navigation.
* These tests assume the default browser configuration for toolbars unless
* otherwise specified.
*/
const PERMISSIONS_PAGE = "https://example.com/browser/browser/base/content/test/permissions/permissions.html";
async function expectFocusAfterKey(aKey, aFocus, aAncestorOk = false) {
let res = aKey.match(/^(Shift\+)?(?:(.)|(.+))$/);
let shift = Boolean(res[1]);
let key;
if (res[2]) {
key = res[2]; // Character.
} else {
key = "KEY_" + res[3]; // Tab, ArrowRight, etc.
}
let expected;
let friendlyExpected;
if (typeof aFocus == "string") {
expected = document.getElementById(aFocus);
friendlyExpected = aFocus;
} else {
expected = aFocus;
if (aFocus == gURLBar.inputField) {
friendlyExpected = "URL bar input";
} else if (aFocus == gBrowser.selectedBrowser) {
friendlyExpected = "Web document";
}
}
let focused = BrowserTestUtils.waitForEvent(expected, "focus", aAncestorOk);
EventUtils.synthesizeKey(key, {shiftKey: shift});
await focused;
ok(true, friendlyExpected + " focused after " + aKey + " pressed");
}
function startFromUrlBar() {
gURLBar.focus();
is(document.activeElement, gURLBar.inputField,
"URL bar focused for start of test");
}
// The Reload button is disabled for a short time even after the page finishes
// loading. Wait for it to be enabled.
async function waitUntilReloadEnabled() {
let button = document.getElementById("reload-button");
await TestUtils.waitForCondition(() => !button.disabled);
}
add_task(async function setPref() {
await SpecialPowers.pushPrefEnv({
set: [
["browser.toolbars.keyboard_navigation", true],
["accessibility.tabfocus", 7],
],
});
});
// Test tab stops with no page loaded.
add_task(async function testTabStopsNoPage() {
await BrowserTestUtils.withNewTab("about:blank", async function() {
startFromUrlBar();
await expectFocusAfterKey("Shift+Tab", "home-button");
await expectFocusAfterKey("Shift+Tab", "tabbrowser-tabs", true);
await expectFocusAfterKey("Tab", "home-button");
await expectFocusAfterKey("Tab", gURLBar.inputField);
await expectFocusAfterKey("Tab", "library-button");
await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
});
});
// Test tab stops with a page loaded.
add_task(async function testTabStopsPageLoaded() {
await BrowserTestUtils.withNewTab("https://example.com", async function() {
await waitUntilReloadEnabled();
startFromUrlBar();
await expectFocusAfterKey("Shift+Tab", "identity-box");
await expectFocusAfterKey("Shift+Tab", "reload-button");
await expectFocusAfterKey("Shift+Tab", "tabbrowser-tabs", true);
await expectFocusAfterKey("Tab", "reload-button");
await expectFocusAfterKey("Tab", "identity-box");
await expectFocusAfterKey("Tab", gURLBar.inputField);
await expectFocusAfterKey("Tab", "pageActionButton");
await expectFocusAfterKey("Tab", "library-button");
await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
});
});
// Test tab stops with a notification anchor visible.
// The notification anchor should not get its own tab stop.
add_task(async function testTabStopsWithNotification() {
await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function(aBrowser) {
let popupShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
// Request a permission.
BrowserTestUtils.synthesizeMouseAtCenter("#geo", {}, aBrowser);
await popupShown;
startFromUrlBar();
// If the notification anchor were in the tab order, the next shift+tab
// would focus it instead of #identity-box.
await expectFocusAfterKey("Shift+Tab", "identity-box");
});
});
// Test tab stops with the Bookmarks toolbar visible.
add_task(async function testTabStopsWithBookmarksToolbar() {
await BrowserTestUtils.withNewTab("about:blank", async function() {
CustomizableUI.setToolbarVisibility("PersonalToolbar", true);
startFromUrlBar();
await expectFocusAfterKey("Tab", "library-button");
await expectFocusAfterKey("Tab", "PersonalToolbar", true);
await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
// Make sure the Bookmarks toolbar is no longer tabbable once hidden.
CustomizableUI.setToolbarVisibility("PersonalToolbar", false);
startFromUrlBar();
await expectFocusAfterKey("Tab", "library-button");
await expectFocusAfterKey("Tab", gBrowser.selectedBrowser);
});
});
// Test a focusable toolbartabstop which has no navigable buttons.
add_task(async function testTabStopNoButtons() {
await BrowserTestUtils.withNewTab("about:blank", async function() {
// The Back, Forward and Reload buttons are all currently disabled.
// The Home button is the only other button at that tab stop.
CustomizableUI.removeWidgetFromArea("home-button");
startFromUrlBar();
await expectFocusAfterKey("Shift+Tab", "tabbrowser-tabs", true);
await expectFocusAfterKey("Tab", gURLBar.inputField);
CustomizableUI.reset();
// Make sure the button is reachable now that it has been re-added.
await expectFocusAfterKey("Shift+Tab", "home-button", true);
});
});
// Test that right/left arrows move through toolbarbuttons.
// This also verifies that:
// 1. Right/left arrows do nothing when at the edges; and
// 2. The overflow menu button can't be reached by right arrow when it isn't
// visible.
add_task(async function testArrowsToolbarbuttons() {
await BrowserTestUtils.withNewTab("about:blank", async function() {
startFromUrlBar();
await expectFocusAfterKey("Tab", "library-button");
EventUtils.synthesizeKey("KEY_ArrowLeft");
is(document.activeElement.id, "library-button",
"ArrowLeft at end of button group does nothing");
await expectFocusAfterKey("ArrowRight", "sidebar-button");
// This next check also confirms that the overflow menu button is skipped,
// since it is currently invisible.
await expectFocusAfterKey("ArrowRight", "PanelUI-menu-button");
EventUtils.synthesizeKey("KEY_ArrowRight");
is(document.activeElement.id, "PanelUI-menu-button",
"ArrowRight at end of button group does nothing");
await expectFocusAfterKey("ArrowLeft", "sidebar-button");
await expectFocusAfterKey("ArrowLeft", "library-button");
});
});
// Test that right/left arrows move through buttons wihch aren't toolbarbuttons
// but have role="button".
add_task(async function testArrowsRoleButton() {
await BrowserTestUtils.withNewTab("https://example.com", async function() {
startFromUrlBar();
await expectFocusAfterKey("Tab", "pageActionButton");
await expectFocusAfterKey("ArrowRight", "pocket-button");
await expectFocusAfterKey("ArrowRight", "star-button");
await expectFocusAfterKey("ArrowLeft", "pocket-button");
await expectFocusAfterKey("ArrowLeft", "pageActionButton");
});
});
// Test that right/left arrows do not land on disabled buttons.
add_task(async function testArrowsDisabledButtons() {
await BrowserTestUtils.withNewTab("https://example.com", async function(aBrowser) {
await waitUntilReloadEnabled();
startFromUrlBar();
await expectFocusAfterKey("Shift+Tab", "identity-box");
// Back and Forward buttons are disabled.
await expectFocusAfterKey("Shift+Tab", "reload-button");
EventUtils.synthesizeKey("KEY_ArrowLeft");
is(document.activeElement.id, "reload-button",
"ArrowLeft on Reload button when prior buttons disabled does nothing");
BrowserTestUtils.loadURI(aBrowser, "https://example.com/2");
await BrowserTestUtils.browserLoaded(aBrowser);
await waitUntilReloadEnabled();
startFromUrlBar();
await expectFocusAfterKey("Shift+Tab", "identity-box");
await expectFocusAfterKey("Shift+Tab", "back-button");
// Forward button is still disabled.
await expectFocusAfterKey("ArrowRight", "reload-button");
});
});
// Test that right arrow reaches the overflow menu button when it is visible.
add_task(async function testArrowsOverflowButton() {
await BrowserTestUtils.withNewTab("about:blank", async function() {
// Move something to the overflow menu to make the button appear.
CustomizableUI.addWidgetToArea("home-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
startFromUrlBar();
await expectFocusAfterKey("Tab", "library-button");
await expectFocusAfterKey("ArrowRight", "sidebar-button");
await expectFocusAfterKey("ArrowRight", "nav-bar-overflow-button");
await expectFocusAfterKey("ArrowRight", "PanelUI-menu-button");
await expectFocusAfterKey("ArrowLeft", "nav-bar-overflow-button");
// Make sure the button is not reachable once it is invisible again.
await expectFocusAfterKey("ArrowRight", "PanelUI-menu-button");
CustomizableUI.reset();
// Flush layout so its invisibility can be detected.
document.getElementById("nav-bar-overflow-button").clientWidth;
await expectFocusAfterKey("ArrowLeft", "sidebar-button");
});
});

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

@ -55,7 +55,8 @@ browser.jar:
content/browser/browser-sidebar.js (content/browser-sidebar.js)
content/browser/browser-siteIdentity.js (content/browser-siteIdentity.js)
content/browser/browser-sync.js (content/browser-sync.js)
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js)
content/browser/browser-tabsintitlebar.js (content/browser-tabsintitlebar.js)
content/browser/browser-toolbarKeyNav.js (content/browser-toolbarKeyNav.js)
content/browser/browser-thumbnails.js (content/browser-thumbnails.js)
content/browser/browser-webrender.js (content/browser-webrender.js)
content/browser/tab-content.js (content/tab-content.js)

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

@ -126,21 +126,25 @@
display: none;
}
.urlbarView-tags,
.urlbarView-secondary {
color: var(--urlbar-popup-action-color);
font-size: .85em;
}
.urlbarView-url {
color: var(--urlbar-popup-url-color);
}
.urlbarView-title > strong,
.urlbarView-url > strong,
.urlbarView-tag > strong {
font-weight: 600;
}
.urlbarView-secondary {
color: var(--urlbar-popup-action-color);
}
.urlbarView-url {
color: var(--urlbar-popup-url-color);
}
.urlbarView-row[selected] > .urlbarView-row-inner > .urlbarView-secondary::before,
.urlbarView-row[selected] > .urlbarView-row-inner > .urlbarView-secondary {
color: inherit;

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

@ -20,13 +20,7 @@ export function createFrame(thread: ThreadId, frame: FramePacket): ?Frame {
if (!frame) {
return null;
}
let title;
if (frame.type == "call") {
const c = frame.callee;
title = c.name || c.userDisplayName || c.displayName;
} else {
title = `(${frame.type})`;
}
const location = {
sourceId: clientCommands.getSourceForActor(frame.where.actor),
line: frame.where.line,
@ -36,7 +30,7 @@ export function createFrame(thread: ThreadId, frame: FramePacket): ?Frame {
return {
id: frame.actor,
thread,
displayName: title,
displayName: frame.displayName,
location,
generatedLocation: location,
this: frame.this,

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

@ -9,7 +9,7 @@ import { isDevelopment } from "devtools-environment";
import Services from "devtools-services";
import { asyncStoreHelper } from "./asyncStoreHelper";
const prefsSchemaVersion = "1.0.7";
const prefsSchemaVersion = "1.0.8";
const pref = Services.pref;
@ -137,8 +137,8 @@ export const asyncStore = asyncStoreHelper("debugger", {
if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) {
// clear pending Breakpoints
prefs.pendingBreakpoints = {};
prefs.tabs = [];
prefs.xhrBreakpoints = [];
asyncStore.pendingBreakpoints = {};
asyncStore.tabs = [];
asyncStore.xhrBreakpoints = [];
prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion;
}

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

@ -11,6 +11,15 @@ const { createValueGrip } = require("devtools/server/actors/object/utils");
const { ActorClassWithSpec } = require("devtools/shared/protocol");
const { frameSpec } = require("devtools/shared/specs/frame");
function formatDisplayName(frame) {
if (frame.type === "call") {
const callee = frame.callee;
return callee.name || callee.userDisplayName || callee.displayName;
}
return `(${frame.type})`;
}
/**
* An actor for a specified stack frame.
*/
@ -76,10 +85,6 @@ const FrameActor = ActorClassWithSpec(frameSpec, {
const threadActor = this.threadActor;
const form = { actor: this.actorID,
type: this.frame.type };
if (this.frame.type === "call") {
form.callee = createValueGrip(this.frame.callee, threadActor._pausePool,
threadActor.objectGrip);
}
// NOTE: ignoreFrameEnvironment lets the client explicitly avoid
// populating form environments on pause.
@ -95,6 +100,7 @@ const FrameActor = ActorClassWithSpec(frameSpec, {
threadActor.objectGrip);
}
form.displayName = formatDisplayName(this.frame);
form.arguments = this._args();
if (this.frame.script) {
const generatedLocation = this.threadActor.sources.getFrameLocation(this.frame);

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

@ -33,7 +33,7 @@ function test_pause_frame() {
gThreadClient.addOneTimeListener("paused", function(event, packet) {
Assert.ok(!!packet.frame);
Assert.ok(!!packet.frame.actor);
Assert.equal(packet.frame.callee.name, "stopMe");
Assert.equal(packet.frame.displayName, "stopMe");
gThreadClient.resume(function() {
finishClient(gClient);
});

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

@ -29,57 +29,36 @@ function run_test() {
do_test_pending();
}
var gFrames = [
var frameFixtures = [
// Function calls...
{ type: "call", callee: { name: "depth3" } },
{ type: "call", callee: { name: "depth2" } },
{ type: "call", callee: { name: "depth1" } },
{ type: "call", displayName: "depth3" },
{ type: "call", displayName: "depth2" },
{ type: "call", displayName: "depth1" },
// Anonymous function call in our eval...
{ type: "call", callee: { name: undefined } },
{ type: "call", displayName: undefined },
// The eval itself.
{ type: "eval", callee: { name: undefined } },
{ type: "eval", displayName: "(eval)" },
];
var gSliceTests = [
{ start: 0, count: undefined, resetActors: true },
{ start: 0, count: 1 },
{ start: 2, count: 2 },
{ start: 1, count: 15 },
{ start: 15, count: undefined },
];
function test_frame_slice() {
if (gSliceTests.length == 0) {
gThreadClient.resume(() => finishClient(gClient));
return;
}
const test = gSliceTests.shift();
gThreadClient.getFrames(test.start, test.count, function(response) {
const testFrames = gFrames.slice(test.start,
test.count ? test.start + test.count : undefined);
Assert.equal(testFrames.length, response.frames.length);
for (let i = 0; i < testFrames.length; i++) {
const expected = testFrames[i];
function test_frame_packet() {
gThreadClient.getFrames(0, 1000, function(response) {
for (let i = 0; i < response.frames.length; i++) {
const expected = frameFixtures[i];
const actual = response.frames[i];
if (test.resetActors) {
expected.actor = actual.actor;
}
for (const key of ["type", "callee-name"]) {
Assert.equal(expected[key] || undefined, actual[key]);
}
Assert.equal(expected.displayname, actual.displayname, "Frame displayname");
Assert.equal(expected.type, actual.type, "Frame displayname");
}
test_frame_slice();
gThreadClient.resume(() => finishClient(gClient));
});
}
function test_pause_frame() {
gThreadClient.addOneTimeListener("paused", function(event, packet) {
test_frame_slice();
test_frame_packet();
});
gDebuggee.eval("(" + function() {

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

@ -64,8 +64,7 @@ static void Sync(BrowsingContext* aBrowsingContext) {
MOZ_DIAGNOSTIC_ASSERT(cc);
RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
BrowsingContext* opener = aBrowsingContext->GetOpener();
cc->SendAttachBrowsingContext(BrowsingContextId(parent ? parent->Id() : 0),
BrowsingContextId(opener ? opener->Id() : 0),
cc->SendAttachBrowsingContext(parent, opener,
BrowsingContextId(aBrowsingContext->Id()),
aBrowsingContext->Name());
}
@ -103,6 +102,10 @@ BrowsingContext* BrowsingContext::TopLevelBrowsingContext() {
return nullptr;
}
CanonicalBrowsingContext* BrowsingContext::Canonical() {
return CanonicalBrowsingContext::Cast(this);
}
/* static */ already_AddRefed<BrowsingContext> BrowsingContext::Create(
BrowsingContext* aParent, BrowsingContext* aOpener, const nsAString& aName,
Type aType) {
@ -238,8 +241,7 @@ void BrowsingContext::Detach() {
auto cc = ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
cc->SendDetachBrowsingContext(BrowsingContextId(Id()),
false /* aMoveToBFCache */);
cc->SendDetachBrowsingContext(this, false /* aMoveToBFCache */);
}
void BrowsingContext::CacheChildren() {
@ -264,8 +266,7 @@ void BrowsingContext::CacheChildren() {
auto cc = ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
cc->SendDetachBrowsingContext(BrowsingContextId(Id()),
true /* aMoveToBFCache */);
cc->SendDetachBrowsingContext(this, true /* aMoveToBFCache */);
}
bool BrowsingContext::IsCached() { return sCachedBrowsingContexts->has(Id()); }
@ -288,8 +289,7 @@ void BrowsingContext::SetOpener(BrowsingContext* aOpener) {
auto cc = ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
cc->SendSetOpenerBrowsingContext(
BrowsingContextId(Id()), BrowsingContextId(aOpener ? aOpener->Id() : 0));
cc->SendSetOpenerBrowsingContext(this, aOpener);
}
BrowsingContext::~BrowsingContext() {
@ -326,7 +326,7 @@ void BrowsingContext::NotifyUserGestureActivation() {
}
auto cc = ContentChild::GetSingleton();
MOZ_ASSERT(cc);
cc->SendSetUserGestureActivation(BrowsingContextId(topLevelBC->Id()), true);
cc->SendSetUserGestureActivation(topLevelBC, true);
}
void BrowsingContext::NotifyResetUserGestureActivation() {
@ -343,7 +343,7 @@ void BrowsingContext::NotifyResetUserGestureActivation() {
}
auto cc = ContentChild::GetSingleton();
MOZ_ASSERT(cc);
cc->SendSetUserGestureActivation(BrowsingContextId(topLevelBC->Id()), false);
cc->SendSetUserGestureActivation(topLevelBC, false);
}
void BrowsingContext::SetUserGestureActivation() {
@ -397,18 +397,17 @@ void BrowsingContext::Close(CallerType aCallerType, ErrorResult& aError) {
// document for this browsing context is loaded).
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1516343.
ContentChild* cc = ContentChild::GetSingleton();
cc->SendWindowClose(BrowsingContextId(mBrowsingContextId),
aCallerType == CallerType::System);
cc->SendWindowClose(this, aCallerType == CallerType::System);
}
void BrowsingContext::Focus(ErrorResult& aError) {
ContentChild* cc = ContentChild::GetSingleton();
cc->SendWindowFocus(BrowsingContextId(mBrowsingContextId));
cc->SendWindowFocus(this);
}
void BrowsingContext::Blur(ErrorResult& aError) {
ContentChild* cc = ContentChild::GetSingleton();
cc->SendWindowBlur(BrowsingContextId(mBrowsingContextId));
cc->SendWindowBlur(this);
}
Nullable<WindowProxyHolder> BrowsingContext::GetTop(ErrorResult& aError) {
@ -460,7 +459,7 @@ void BrowsingContext::PostMessageMoz(JSContext* aCx,
getter_AddRefs(data.callerDocumentURI()), aError)) {
return;
}
data.source() = BrowsingContextId(sourceBc->Id());
data.source() = sourceBc;
data.isFromPrivateWindow() =
callerInnerWindow &&
nsScriptErrorBase::ComputeIsFromPrivateWindow(callerInnerWindow);
@ -485,8 +484,7 @@ void BrowsingContext::PostMessageMoz(JSContext* aCx,
return;
}
cc->SendWindowPostMessage(BrowsingContextId(mBrowsingContextId), messageData,
data);
cc->SendWindowPostMessage(this, messageData, data);
}
void BrowsingContext::PostMessageMoz(JSContext* aCx,
@ -515,4 +513,46 @@ already_AddRefed<BrowsingContext> BrowsingContext::FindChildWithName(
}
} // namespace dom
namespace ipc {
void IPDLParamTraits<dom::BrowsingContext>::Write(
IPC::Message* aMsg, IProtocol* aActor, dom::BrowsingContext* aParam) {
uint64_t id = aParam ? aParam->Id() : 0;
WriteIPDLParam(aMsg, aActor, id);
// If his is an in-process send. We want to make sure that our BrowsingContext
// object lives long enough to make it to the other side, so we take an extra
// reference. This reference is freed in ::Read().
if (!aActor->GetIPCChannel()->IsCrossProcess()) {
NS_IF_ADDREF(aParam);
}
}
bool IPDLParamTraits<dom::BrowsingContext>::Read(
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
RefPtr<dom::BrowsingContext>* aResult) {
uint64_t id = 0;
if (!ReadIPDLParam(aMsg, aIter, aActor, &id)) {
return false;
}
if (id == 0) {
aResult = nullptr;
return true;
}
*aResult = dom::BrowsingContext::Get(id);
MOZ_ASSERT(aResult, "Deserialized absent BrowsingContext!");
// If this is an in-process actor, free the reference taken in ::Write().
if (!aActor->GetIPCChannel()->IsCrossProcess()) {
dom::BrowsingContext* bc = *aResult;
NS_IF_RELEASE(bc);
}
return aResult != nullptr;
}
} // namespace ipc
} // namespace mozilla

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

@ -20,6 +20,11 @@
class nsGlobalWindowOuter;
class nsOuterWindowProxy;
class PickleIterator;
namespace IPC {
class Message;
} // namespace IPC
namespace mozilla {
@ -27,9 +32,17 @@ class ErrorResult;
class LogModule;
class OOMReporter;
namespace ipc {
class IProtocol;
template <typename T>
struct IPDLParamTraits;
} // namespace ipc
namespace dom {
class BrowsingContextGroup;
class CanonicalBrowsingContext;
class ContentParent;
template <typename>
struct Nullable;
@ -81,6 +94,9 @@ class BrowsingContext : public nsWrapperCache,
BrowsingContext* aParent, BrowsingContext* aOpener,
const nsAString& aName, uint64_t aId, ContentParent* aOriginProcess);
// Cast this object to a canonical browsing context, and return it.
CanonicalBrowsingContext* Canonical();
// Get the DocShell for this BrowsingContext if it is in-process, or
// null if it's not.
nsIDocShell* GetDocShell() { return mDocShell; }
@ -254,6 +270,17 @@ extern bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
JS::MutableHandle<JSObject*> aRetVal);
} // namespace dom
// Allow sending BrowsingContext objects over IPC.
namespace ipc {
template <>
struct IPDLParamTraits<dom::BrowsingContext> {
static void Write(IPC::Message* aMsg, IProtocol* aActor,
dom::BrowsingContext* aParam);
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
IProtocol* aActor, RefPtr<dom::BrowsingContext>* aResult);
};
} // namespace ipc
} // namespace mozilla
#endif // !defined(mozilla_dom_BrowsingContext_h)

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

@ -977,7 +977,11 @@ nsRect Element::GetClientAreaRect() {
nsIScrollableFrame* sf = GetScrollFrame(&frame);
if (sf) {
return sf->GetScrollPortRect();
nsRect scrollPort = sf->GetScrollPortRect();
// The scroll port value might be expanded to the minimum scale size, we
// should limit the size to the ICB in such cases.
scrollPort.SizeTo(sf->GetLayoutSize());
return scrollPort;
}
if (frame &&

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

@ -166,9 +166,8 @@ BlobURL::Mutate(nsIURIMutator** aMutator) {
// nsIClassInfo methods:
NS_IMETHODIMP
BlobURL::GetInterfaces(uint32_t* count, nsIID*** array) {
*count = 0;
*array = nullptr;
BlobURL::GetInterfaces(nsTArray<nsIID>& array) {
array.Clear();
return NS_OK;
}

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

@ -302,7 +302,8 @@ interface nsIContentSecurityPolicy : nsISerializable
in nsISupports aContext,
in ACString aMimeTypeGuess,
in nsIURI aOriginalURIIfRedirect,
in bool aSendViolationReports);
in bool aSendViolationReports,
in AString aNonce);
%{ C++
// nsIObserver topic to fire when the policy encounters a violation.

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

@ -3590,67 +3590,54 @@ PContentChild::Result ContentChild::OnMessageReceived(const Message& aMsg,
}
mozilla::ipc::IPCResult ContentChild::RecvWindowClose(
const BrowsingContextId& aContextId, const bool& aTrustedCaller) {
RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
if (!bc) {
BrowsingContext* aContext, bool aTrustedCaller) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsCOMPtr<nsPIDOMWindowOuter> window = bc->GetDOMWindow();
nsCOMPtr<nsPIDOMWindowOuter> window = aContext->GetDOMWindow();
nsGlobalWindowOuter::Cast(window)->CloseOuter(aTrustedCaller);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
const BrowsingContextId& aContextId) {
RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
if (!bc) {
mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsCOMPtr<nsPIDOMWindowOuter> window = bc->GetDOMWindow();
nsCOMPtr<nsPIDOMWindowOuter> window = aContext->GetDOMWindow();
nsGlobalWindowOuter::Cast(window)->FocusOuter();
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
const BrowsingContextId& aContextId) {
RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
if (!bc) {
BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
nsCOMPtr<nsPIDOMWindowOuter> window = bc->GetDOMWindow();
nsCOMPtr<nsPIDOMWindowOuter> window = aContext->GetDOMWindow();
nsGlobalWindowOuter::Cast(window)->BlurOuter();
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage(
const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData) {
RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
if (!bc) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
("ChildIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
RefPtr<nsGlobalWindowOuter> window =
nsGlobalWindowOuter::Cast(bc->GetDOMWindow());
nsGlobalWindowOuter::Cast(aContext->GetDOMWindow());
nsCOMPtr<nsIPrincipal> providedPrincipal;
if (!window->GetPrincipalForPostMessage(
aData.targetOrigin(), aData.targetOriginURI(),
@ -3659,11 +3646,10 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage(
return IPC_OK();
}
RefPtr<BrowsingContext> sourceBc = BrowsingContext::Get(aData.source());
RefPtr<BrowsingContext> sourceBc = aData.source();
if (!sourceBc) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to use a dead or detached context 0x%08" PRIx64,
(uint64_t)aData.source()));
("ChildIPC: Trying to use a dead or detached context"));
return IPC_OK();
}

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

@ -714,12 +714,12 @@ class ContentChild final : public PContentChild,
virtual void OnChannelReceivedMessage(const Message& aMsg) override;
mozilla::ipc::IPCResult RecvWindowClose(const BrowsingContextId& aContextId,
const bool& aTrustedCaller);
mozilla::ipc::IPCResult RecvWindowFocus(const BrowsingContextId& aContextId);
mozilla::ipc::IPCResult RecvWindowBlur(const BrowsingContextId& aContextId);
mozilla::ipc::IPCResult RecvWindowClose(BrowsingContext* aContext,
bool aTrustedCaller);
mozilla::ipc::IPCResult RecvWindowFocus(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvWindowBlur(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvWindowPostMessage(
const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData);
#ifdef NIGHTLY_BUILD

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

@ -5609,31 +5609,9 @@ mozilla::ipc::IPCResult ContentParent::RecvStoreUserInteractionAsPermission(
}
mozilla::ipc::IPCResult ContentParent::RecvAttachBrowsingContext(
const BrowsingContextId& aParentId, const BrowsingContextId& aOpenerId,
const BrowsingContextId& aChildId, const nsString& aName) {
RefPtr<CanonicalBrowsingContext> parent =
CanonicalBrowsingContext::Get(aParentId);
if (aParentId && !parent) {
// Unless 'aParentId' is 0 (which it is when the child is a root
// BrowsingContext) there should always be a corresponding
// 'parent'. The only reason for there not beeing one is if the
// parent has already been detached, in which case the
// BrowsingContext that tries to attach itself to the context with
// 'aParentId' is surely doomed and we can safely do nothing.
// TODO(farre): When we start syncing/moving BrowsingContexts to
// other child processes is it possible to get into races where
// constructive operations on already detached BrowsingContexts
// are requested? This needs to be answered/handled, but for now
// return early. [Bug 1471598]
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to attach to already detached parent 0x%08" PRIx64,
(uint64_t)aParentId));
return IPC_OK();
}
if (parent && !parent->IsOwnedByProcess(ChildID())) {
BrowsingContext* aParent, BrowsingContext* aOpener,
BrowsingContextId aChildId, const nsString& aName) {
if (aParent && !aParent->Canonical()->IsOwnedByProcess(ChildID())) {
// Where trying attach a child BrowsingContext to a parent
// BrowsingContext in another process. This is illegal since the
// only thing that could create that child BrowsingContext is a
@ -5648,7 +5626,7 @@ mozilla::ipc::IPCResult ContentParent::RecvAttachBrowsingContext(
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning,
("ParentIPC: Trying to attach to out of process parent context "
"0x%08" PRIx64,
parent->Id()));
aParent->Id()));
return IPC_OK();
}
@ -5663,13 +5641,12 @@ mozilla::ipc::IPCResult ContentParent::RecvAttachBrowsingContext(
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning,
("ParentIPC: Trying to attach already attached 0x%08" PRIx64
" to 0x%08" PRIx64,
child->Id(), (uint64_t)aParentId));
child->Id(), aParent ? aParent->Id() : 0));
return IPC_OK();
}
if (!child) {
RefPtr<BrowsingContext> opener = BrowsingContext::Get(aOpenerId);
child = BrowsingContext::CreateFromIPC(parent, opener, aName,
child = BrowsingContext::CreateFromIPC(aParent, aOpener, aName,
(uint64_t)aChildId, this);
}
@ -5677,18 +5654,14 @@ mozilla::ipc::IPCResult ContentParent::RecvAttachBrowsingContext(
}
mozilla::ipc::IPCResult ContentParent::RecvDetachBrowsingContext(
const BrowsingContextId& aContextId, const bool& aMoveToBFCache) {
RefPtr<CanonicalBrowsingContext> context =
CanonicalBrowsingContext::Get(aContextId);
if (!context) {
BrowsingContext* aContext, bool aMoveToBFCache) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to detach already detached 0x%08" PRIx64,
(uint64_t)aContextId));
("ParentIPC: Trying to detach already detached"));
return IPC_OK();
}
if (!context->IsOwnedByProcess(ChildID())) {
if (!aContext->Canonical()->IsOwnedByProcess(ChildID())) {
// Where trying to detach a child BrowsingContext in another child
// process. This is illegal since the owner of the BrowsingContext
// is the proccess with the in-process docshell, which is tracked
@ -5698,33 +5671,28 @@ mozilla::ipc::IPCResult ContentParent::RecvDetachBrowsingContext(
// above TODO. [Bug 1471598]
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning,
("ParentIPC: Trying to detach out of process context 0x%08" PRIx64,
context->Id()));
aContext->Id()));
return IPC_OK();
}
if (aMoveToBFCache) {
context->CacheChildren();
aContext->CacheChildren();
} else {
context->Detach();
aContext->Detach();
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvSetOpenerBrowsingContext(
const BrowsingContextId& aContextId,
const BrowsingContextId& aOpenerContextId) {
RefPtr<CanonicalBrowsingContext> context =
CanonicalBrowsingContext::Get(aContextId);
if (!context) {
BrowsingContext* aContext, BrowsingContext* aOpener) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to set opener already detached 0x%08" PRIx64,
(uint64_t)aContextId));
("ParentIPC: Trying to set opener already detached"));
return IPC_OK();
}
if (!context->IsOwnedByProcess(ChildID())) {
if (!aContext->Canonical()->IsOwnedByProcess(ChildID())) {
// Where trying to set opener on a child BrowsingContext in
// another child process. This is illegal since the owner of the
// BrowsingContext is the proccess with the in-process docshell,
@ -5735,29 +5703,24 @@ mozilla::ipc::IPCResult ContentParent::RecvSetOpenerBrowsingContext(
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Warning,
("ParentIPC: Trying to set opener on out of process context "
"0x%08" PRIx64,
context->Id()));
aContext->Id()));
return IPC_OK();
}
RefPtr<BrowsingContext> opener = BrowsingContext::Get(aOpenerContextId);
context->SetOpener(opener);
aContext->SetOpener(aOpener);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvSetUserGestureActivation(
const BrowsingContextId& aContextId, const bool& aNewValue) {
RefPtr<CanonicalBrowsingContext> context =
CanonicalBrowsingContext::Get(aContextId);
if (!context) {
BrowsingContext* aContext, bool aNewValue) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to activate wrong context 0x%08" PRIx64,
(uint64_t)aContextId));
("ParentIPC: Trying to activate wrong context"));
return IPC_OK();
}
context->NotifySetUserGestureActivationFromIPC(aNewValue);
aContext->Canonical()->NotifySetUserGestureActivationFromIPC(aNewValue);
return IPC_OK();
}
@ -5782,14 +5745,11 @@ void ContentParent::UnregisterRemoveWorkerActor() {
}
mozilla::ipc::IPCResult ContentParent::RecvWindowClose(
const BrowsingContextId& aContextId, const bool& aTrustedCaller) {
RefPtr<CanonicalBrowsingContext> bc =
CanonicalBrowsingContext::Get(aContextId);
if (!bc) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
BrowsingContext* aContext, bool aTrustedCaller) {
if (!aContext) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
@ -5798,66 +5758,57 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowClose(
// browsing contexts of bc.
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp =
cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
Unused << cp->SendWindowClose(aContextId, aTrustedCaller);
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
Unused << cp->SendWindowClose(aContext, aTrustedCaller);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvWindowFocus(
const BrowsingContextId& aContextId) {
RefPtr<CanonicalBrowsingContext> bc =
CanonicalBrowsingContext::Get(aContextId);
if (!bc) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp =
cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
Unused << cp->SendWindowFocus(aContextId);
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
Unused << cp->SendWindowFocus(aContext);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvWindowBlur(
const BrowsingContextId& aContextId) {
RefPtr<CanonicalBrowsingContext> bc =
CanonicalBrowsingContext::Get(aContextId);
if (!bc) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
BrowsingContext* aContext) {
if (!aContext) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp =
cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
Unused << cp->SendWindowBlur(aContextId);
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
Unused << cp->SendWindowBlur(aContext);
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvWindowPostMessage(
const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData) {
RefPtr<CanonicalBrowsingContext> bc =
CanonicalBrowsingContext::Get(aContextId);
if (!bc) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context "
"0x%08" PRIx64,
(uint64_t)aContextId));
if (!aContext) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
("ParentIPC: Trying to send a message to dead or detached context"));
return IPC_OK();
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp =
cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
StructuredCloneData messageFromChild;
UnpackClonedMessageDataForParent(aMessage, messageFromChild);
ClonedMessageData message;
@ -5865,7 +5816,7 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowPostMessage(
// FIXME Logging?
return IPC_OK();
}
Unused << cp->SendWindowPostMessage(aContextId, message, aData);
Unused << cp->SendWindowPostMessage(aContext, message, aData);
return IPC_OK();
}

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

@ -618,27 +618,25 @@ class ContentParent final : public PContentParent,
static bool IsInputEventQueueSupported();
mozilla::ipc::IPCResult RecvAttachBrowsingContext(
const BrowsingContextId& aParentContextId,
const BrowsingContextId& aOpenerId, const BrowsingContextId& aContextId,
const nsString& aName);
BrowsingContext* aParentContext, BrowsingContext* aOpener,
BrowsingContextId aContextId, const nsString& aName);
mozilla::ipc::IPCResult RecvDetachBrowsingContext(
const BrowsingContextId& aContextId, const bool& aMoveToBFCache);
mozilla::ipc::IPCResult RecvDetachBrowsingContext(BrowsingContext* aContext,
bool aMoveToBFCache);
mozilla::ipc::IPCResult RecvSetOpenerBrowsingContext(
const BrowsingContextId& aContextId,
const BrowsingContextId& aOpenerContextId);
BrowsingContext* aContext, BrowsingContext* aOpener);
mozilla::ipc::IPCResult RecvWindowClose(const BrowsingContextId& aContextId,
const bool& aTrustedCaller);
mozilla::ipc::IPCResult RecvWindowFocus(const BrowsingContextId& aContextId);
mozilla::ipc::IPCResult RecvWindowBlur(const BrowsingContextId& aContextId);
mozilla::ipc::IPCResult RecvWindowClose(BrowsingContext* aContext,
bool aTrustedCaller);
mozilla::ipc::IPCResult RecvWindowFocus(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvWindowBlur(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvWindowPostMessage(
const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
BrowsingContext* aContext, const ClonedMessageData& aMessage,
const PostMessageData& aData);
mozilla::ipc::IPCResult RecvSetUserGestureActivation(
const BrowsingContextId& aContextId, const bool& aNewValue);
BrowsingContext* aContext, bool aNewValue);
protected:
void OnChannelConnected(int32_t pid) override;

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

@ -27,7 +27,7 @@ using mozilla::LayoutDeviceIntPoint from "Units.h";
using hal::ScreenOrientation from "mozilla/HalScreenConfiguration.h";
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
using refcounted class nsIPrincipal from "mozilla/dom/PermissionMessageUtils.h";
using mozilla::dom::BrowsingContextId from "mozilla/dom/ipc/IdType.h";
using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
using refcounted class nsIURI from "mozilla/ipc/URIUtils.h";
namespace mozilla {
@ -189,7 +189,7 @@ struct PerformanceInfo
struct WindowGlobalInit
{
nsIPrincipal principal;
BrowsingContextId browsingContextId;
BrowsingContext browsingContext;
uint64_t innerWindowId;
uint64_t outerWindowId;
};

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

@ -88,7 +88,7 @@ using class mozilla::NativeEventData from "ipc/nsGUIEventIPC.h";
using mozilla::FontRange from "ipc/nsGUIEventIPC.h";
using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h";
using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
using mozilla::dom::BrowsingContextId from "mozilla/dom/ipc/IdType.h";
using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
namespace mozilla {
namespace dom {
@ -621,7 +621,7 @@ parent:
sync SetPrefersReducedMotionOverrideForTest(bool aValue);
sync ResetPrefersReducedMotionOverrideForTest();
async RootBrowsingContext(BrowsingContextId aId);
async RootBrowsingContext(BrowsingContext aContext);
child:
/**

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

@ -102,6 +102,7 @@ using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
using refcounted class nsIInputStream from "mozilla/ipc/IPCStreamUtils.h";
using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
using mozilla::dom::BrowsingContextId from "mozilla/dom/ipc/IdType.h";
union ChromeRegistryItem
@ -308,7 +309,7 @@ struct NotificationEventData
struct PostMessageData
{
BrowsingContextId source;
BrowsingContext source;
nsString origin;
nsString targetOrigin;
nsIURI targetOriginURI;
@ -1219,47 +1220,44 @@ parent:
async StoreUserInteractionAsPermission(Principal aPrincipal);
/**
* Sync the BrowsingContext with id 'aContextId' and name 'aName'
* to the parent, and attach it to the BrowsingContext with id
* 'aParentContextId'. If 'aParentContextId' is '0' the
* BrowsingContext is a root in the BrowsingContext
* tree. AttachBrowsingContext must only be called at most once
* for any child BrowsingContext, and only for BrowsingContexts
* where the parent and the child context contains their
* nsDocShell.
* Sync the BrowsingContext with id 'aContextId' and name 'aName' to the
* parent, and attach it to the BrowsingContext 'aParentContext'. If
* 'aParentContext' is 'nullptr' the BrowsingContext is a root in the
* BrowsingContext tree. AttachBrowsingContext must only be called at most
* once for any child BrowsingContext, and only for BrowsingContexts where
* the parent and the child context contains their nsDocShell.
*/
async AttachBrowsingContext(BrowsingContextId aParentContextId,
BrowsingContextId aOpenerId,
async AttachBrowsingContext(BrowsingContext aParentContext,
BrowsingContext aOpener,
BrowsingContextId aContextId,
nsString aName);
/**
* Remove the synced BrowsingContext with id 'aContextId' from the
* parent. DetachBrowsingContext is only needed to be called once
* for any BrowsingContext, since detaching a node in the
* BrowsingContext detaches the entire sub-tree rooted at that
* node. Calling DetachBrowsingContext with an already detached
* BrowsingContext effectively does nothing. Note that it is not
* an error to call DetachBrowsingContext on a BrowsingContext
* belonging to an already detached subtree. The 'aMoveToBFCache'
* paramater controls if detaching a BrowsingContext should move
* it to the bfcache allowing it to be re-attached if navigated
* Remove the synced BrowsingContext 'aContext' from the parent.
* DetachBrowsingContext is only needed to be called once for any
* BrowsingContext, since detaching a node in the BrowsingContext detaches
* the entire sub-tree rooted at that node. Calling DetachBrowsingContext
* with an already detached BrowsingContext effectively does nothing. Note
* that it is not an error to call DetachBrowsingContext on a
* BrowsingContext belonging to an already detached subtree. The
* 'aMoveToBFCache' paramater controls if detaching a BrowsingContext
* should move it to the bfcache allowing it to be re-attached if navigated
* to.
*/
async DetachBrowsingContext(BrowsingContextId aContextId,
async DetachBrowsingContext(BrowsingContext aContext,
bool aMoveToBFCache);
/**
* Set the opener of browsing context with id 'aContextId' to the
* browsing context with id 'aOpenerId'.
* Set the opener of browsing context 'aContext' to the browsing context
* with id 'aOpenerId'.
*/
async SetOpenerBrowsingContext(BrowsingContextId aContextId,
BrowsingContextId aOpenerContextId);
async SetOpenerBrowsingContext(BrowsingContext aContext,
BrowsingContext aOpenerContext);
/**
* Notify parent to update user gesture activation flag.
*/
async SetUserGestureActivation(BrowsingContextId aContextId,
async SetUserGestureActivation(BrowsingContext aContext,
bool aNewValue);
both:
@ -1279,11 +1277,10 @@ both:
async PushError(nsCString scope, Principal principal, nsString message,
uint32_t flags);
async WindowClose(BrowsingContextId aContextId,
bool aTrustedCaller);
async WindowFocus(BrowsingContextId aContextId);
async WindowBlur(BrowsingContextId aContextId);
async WindowPostMessage(BrowsingContextId aContextId, ClonedMessageData aMessage,
async WindowClose(BrowsingContext aContext, bool aTrustedCaller);
async WindowFocus(BrowsingContext aContext);
async WindowBlur(BrowsingContext aContext);
async WindowPostMessage(BrowsingContext aContext, ClonedMessageData aMessage,
PostMessageData aData);
};

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

@ -554,7 +554,7 @@ nsresult TabChild::Init(mozIDOMWindowProxy* aParent) {
// Send our browsing context to the parent process.
RefPtr<BrowsingContext> browsingContext =
nsDocShell::Cast(docShell)->GetBrowsingContext();
SendRootBrowsingContext(BrowsingContextId(browsingContext->Id()));
SendRootBrowsingContext(browsingContext);
// Few lines before, baseWindow->Create() will end up creating a new
// window root in nsGlobalWindow::SetDocShell.

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

@ -3444,9 +3444,9 @@ mozilla::ipc::IPCResult TabParent::RecvGetSystemFont(nsCString* aFontName) {
}
mozilla::ipc::IPCResult TabParent::RecvRootBrowsingContext(
const BrowsingContextId& aId) {
BrowsingContext* aBrowsingContext) {
MOZ_ASSERT(!mBrowsingContext, "May only set browsing context once!");
mBrowsingContext = CanonicalBrowsingContext::Get(aId);
mBrowsingContext = CanonicalBrowsingContext::Cast(aBrowsingContext);
MOZ_ASSERT(mBrowsingContext, "Invalid ID!");
return IPC_OK();
}

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

@ -257,11 +257,10 @@ class TabParent final : public PBrowserParent,
const nsCursor& aValue, const bool& aHasCustomCursor,
const nsCString& aUri, const uint32_t& aWidth, const uint32_t& aHeight,
const uint32_t& aStride, const gfx::SurfaceFormat& aFormat,
const uint32_t& aHotspotX, const uint32_t& aHotspotY,
const bool& aForce);
const uint32_t& aHotspotX, const uint32_t& aHotspotY, const bool& aForce);
mozilla::ipc::IPCResult RecvSetStatus(
const uint32_t& aType, const nsString& aStatus);
mozilla::ipc::IPCResult RecvSetStatus(const uint32_t& aType,
const nsString& aStatus);
mozilla::ipc::IPCResult RecvShowTooltip(const uint32_t& aX,
const uint32_t& aY,
@ -595,7 +594,7 @@ class TabParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(
const nsCString& aFirstPartyURI, const bool& aHideDoorHanger);
mozilla::ipc::IPCResult RecvRootBrowsingContext(const BrowsingContextId& aId);
mozilla::ipc::IPCResult RecvRootBrowsingContext(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvSetSystemFont(const nsCString& aFontName);
mozilla::ipc::IPCResult RecvGetSystemFont(nsCString* aFontName);

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

@ -39,9 +39,8 @@ already_AddRefed<WindowGlobalChild> WindowGlobalChild::Create(
RefPtr<dom::BrowsingContext> bc = docshell->GetBrowsingContext();
RefPtr<WindowGlobalChild> wgc = new WindowGlobalChild(aWindow, bc);
WindowGlobalInit init(principal,
BrowsingContextId(wgc->BrowsingContext()->Id()),
wgc->mInnerWindowId, wgc->mOuterWindowId);
WindowGlobalInit init(principal, bc, wgc->mInnerWindowId,
wgc->mOuterWindowId);
// Send the link constructor over PInProcessChild or PBrowser.
if (XRE_IsParentProcess()) {

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

@ -37,7 +37,7 @@ WindowGlobalParent::WindowGlobalParent(const WindowGlobalInit& aInit,
MOZ_RELEASE_ASSERT(mDocumentPrincipal, "Must have a valid principal");
// NOTE: mBrowsingContext initialized in Init()
MOZ_RELEASE_ASSERT(aInit.browsingContextId() != 0,
MOZ_RELEASE_ASSERT(aInit.browsingContext(),
"Must be made in BrowsingContext");
}
@ -63,7 +63,7 @@ void WindowGlobalParent::Init(const WindowGlobalInit& aInit) {
processId = static_cast<ContentParent*>(Manager()->Manager())->ChildID();
}
mBrowsingContext = CanonicalBrowsingContext::Get(aInit.browsingContextId());
mBrowsingContext = CanonicalBrowsingContext::Cast(aInit.browsingContext());
MOZ_ASSERT(mBrowsingContext);
// XXX(nika): This won't be the case soon, but for now this is a good

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

@ -22,6 +22,7 @@ namespace dom {
class CanonicalBrowsingContext;
class WindowGlobalChild;
class JSWindowActorParent;
class TabParent;
/**
* A handle in the parent process to a specific nsGlobalWindowInner object.

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

@ -311,6 +311,17 @@ nsresult ScriptLoader::CheckContentPolicy(Document* aDocument,
requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
contentPolicyType);
// snapshot the nonce at load start time for performing CSP checks
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT ||
contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_MODULE) {
nsCOMPtr<Element> element = do_QueryInterface(aContext);
if (element && element->IsHTMLElement()) {
nsAutoString cspNonce;
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
secCheckLoadInfo->SetCspNonce(cspNonce);
}
}
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(
aRequest->mURI, secCheckLoadInfo, NS_LossyConvertUTF16toASCII(aType),
@ -1257,6 +1268,18 @@ nsresult ScriptLoader::StartLoad(ScriptLoadRequest* aRequest) {
NS_ENSURE_SUCCESS(rv, rv);
// snapshot the nonce at load start time for performing CSP checks
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT ||
contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_MODULE) {
nsCOMPtr<Element> element = do_QueryInterface(context);
if (element && element->IsHTMLElement()) {
nsAutoString cspNonce;
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
loadInfo->SetCspNonce(cspNonce);
}
}
// To avoid decoding issues, the build-id is part of the JSBytecodeMimeType
// constant.
aRequest->mCacheInfo = nullptr;

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

@ -121,7 +121,8 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
nsISupports* aRequestContext,
const nsACString& aMimeTypeGuess,
nsIURI* aOriginalURIIfRedirect,
bool aSendViolationReports, int16_t* outDecision) {
bool aSendViolationReports, const nsAString& aNonce,
int16_t* outDecision) {
if (CSPCONTEXTLOGENABLED()) {
CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s",
aContentLocation->GetSpecOrDefault().get()));
@ -155,18 +156,8 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
return NS_OK;
}
nsAutoString nonce;
bool parserCreated = false;
if (!isPreload) {
if (aContentType == nsIContentPolicy::TYPE_SCRIPT ||
aContentType == nsIContentPolicy::TYPE_STYLESHEET) {
nsCOMPtr<Element> element = do_QueryInterface(aRequestContext);
if (element && element->IsHTMLElement()) {
// XXXbz What about SVG elements that can have nonce?
element->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
}
}
nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aRequestContext);
if (script && script->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER) {
parserCreated = true;
@ -177,7 +168,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
permitsInternal(dir,
nullptr, // aTriggeringElement
aCSPEventListener, aContentLocation,
aOriginalURIIfRedirect, nonce, isPreload,
aOriginalURIIfRedirect, aNonce, isPreload,
false, // allow fallback to default-src
aSendViolationReports,
true, // send blocked URI in violation reports

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

@ -172,6 +172,10 @@ CSPService::ShouldLoad(nsIURI *aContentLocation, nsILoadInfo *aLoadInfo,
return NS_OK;
}
nsAutoString cspNonce;
rv = aLoadInfo->GetCspNonce(cspNonce);
NS_ENSURE_SUCCESS(rv, rv);
// 1) Apply speculate CSP for preloads
bool isPreload = nsContentUtils::IsPreloadType(contentType);
@ -186,7 +190,7 @@ CSPService::ShouldLoad(nsIURI *aContentLocation, nsILoadInfo *aLoadInfo,
contentType, cspEventListener, aContentLocation, requestOrigin,
requestContext, aMimeTypeGuess,
nullptr, // no redirect, aOriginal URL is null.
aLoadInfo->GetSendCSPViolationEvents(), aDecision);
aLoadInfo->GetSendCSPViolationEvents(), cspNonce, aDecision);
NS_ENSURE_SUCCESS(rv, rv);
// if the preload policy already denied the load, then there
@ -207,7 +211,8 @@ CSPService::ShouldLoad(nsIURI *aContentLocation, nsILoadInfo *aLoadInfo,
rv = csp->ShouldLoad(contentType, cspEventListener, aContentLocation,
requestOrigin, requestContext, aMimeTypeGuess,
nullptr, // no redirect, aOriginal URL is null.
aLoadInfo->GetSendCSPViolationEvents(), aDecision);
aLoadInfo->GetSendCSPViolationEvents(), cspNonce,
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@ -251,17 +256,6 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIAsyncVerifyRedirectCallback *callback) {
net::nsAsyncRedirectAutoCallback autoCallback(callback);
if (XRE_IsE10sParentProcess()) {
nsCOMPtr<nsIParentChannel> parentChannel;
NS_QueryNotificationCallbacks(oldChannel, parentChannel);
if (parentChannel) {
// This is an IPC'd channel. Don't check it here, because we won't have
// access to the request context; we'll check them in the content
// process instead. Bug 1509738 covers fixing this.
return NS_OK;
}
}
nsCOMPtr<nsIURI> newUri;
nsresult rv = newChannel->GetURI(getter_AddRefs(newUri));
NS_ENSURE_SUCCESS(rv, rv);
@ -303,6 +297,10 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
return rv;
}
nsAutoString cspNonce;
rv = loadInfo->GetCspNonce(cspNonce);
NS_ENSURE_SUCCESS(rv, rv);
bool isPreload = nsContentUtils::IsPreloadType(policyType);
/* On redirect, if the content policy is a preload type, rejecting the preload
@ -330,6 +328,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
EmptyCString(), // ACString - MIME guess
originalUri, // Original nsIURI
true, // aSendViolationReports
cspNonce, // nonce
&aDecision);
// if the preload policy already denied the load, then there
@ -356,6 +355,7 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
EmptyCString(), // ACString - MIME guess
originalUri, // Original nsIURI
true, // aSendViolationReports
cspNonce, // nonce
&aDecision);
}

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

@ -0,0 +1,48 @@
"use strict";
const TEST_FRAME =
`<!DOCTYPE HTML>
<html>
<body>
<script id='myScript' nonce='123456789' type='application/javascript'></script>
<script nonce='123456789'>
let myScript = document.getElementById('myScript');
// 1) start loading the script using the nonce 123456789
myScript.src='file_nonce_snapshot.sjs?redir-script';
// 2) dynamically change the nonce, load should use initial nonce
myScript.setAttribute('nonce','987654321');
</script>
</body>
</html>`;
const SCRIPT = "window.parent.postMessage('script-loaded', '*');";
function handleRequest(request, response)
{
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
let queryString = request.queryString;
if (queryString === "load-frame") {
response.setHeader("Content-Security-Policy", "script-src 'nonce-123456789'", false);
response.setHeader("Content-Type", "text/html", false);
response.write(TEST_FRAME);
return;
}
if (queryString === "redir-script") {
response.setStatusLine("1.1", 302, "Found");
response.setHeader("Location", "file_nonce_snapshot.sjs?load-script", false);
return;
}
if (queryString === "load-script") {
response.setHeader("Content-Type", "application/javascript", false);
response.write(SCRIPT);
return;
}
// we should never get here but just in case return something unexpected
response.write("do'h");
}

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

@ -368,3 +368,6 @@ support-files =
worker_helper.js
main_csp_worker.html
main_csp_worker.html^headers^
[test_nonce_snapshot.html]
support-files =
file_nonce_snapshot.sjs

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

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1509738 - Snapshot nonce at load start time</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the test:
* a) the test starts loading a script using whitelisted nonce
* b) the nonce of the script gets modified
* c) the script hits a 302 server side redirect
* d) we ensure the script still loads and does not use the modified nonce
*/
window.addEventListener("message", receiveMessage);
function receiveMessage(event) {
is(event.data, "script-loaded", "script loaded even though nonce was dynamically modified");
window.removeEventListener("message", receiveMessage);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
let src = "file_nonce_snapshot.sjs?load-frame";
document.getElementById("testframe").src = src;
</script>
</body>
</html>

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

@ -153,7 +153,7 @@ function run_test() {
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
null, // nsICSPEventListener
NetUtil.newURI("http://blocked.test/foo.js"),
null, null, null, null, true);
null, null, null, null, true, null);
});
// test that inline script violations cause a report in report-only policy
@ -206,7 +206,7 @@ function run_test() {
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
null, // nsICSPEventListener
NetUtil.newURI("data:image/png;base64," + base64data),
null, null, null, null, true);
null, null, null, null, true, null);
});
// test that only the uri's scheme is reported for globally unique identifiers
@ -216,7 +216,7 @@ function run_test() {
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SUBDOCUMENT,
null, // nsICSPEventListener
NetUtil.newURI("intent://mymaps.com/maps?um=1&ie=UTF-8&fb=1&sll"),
null, null, null, null, true);
null, null, null, null, true, null);
});
// test fragment removal
@ -227,7 +227,7 @@ function run_test() {
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
null, // nsICSPEventListener
NetUtil.newURI(selfSpec + "#bar"),
null, null, null, null, true);
null, null, null, null, true, null);
});
// test scheme of ftp:
@ -237,6 +237,6 @@ function run_test() {
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
null, // nsICSPEventListener
NetUtil.newURI("ftp://blocked.test/profile.png"),
null, null, null, null, true);
null, null, null, null, true, null);
});
}

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

@ -24,7 +24,7 @@ use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource};
use webrender::DebugFlags;
use webrender::{ApiRecordingReceiver, BinaryRecorder};
use webrender::{AsyncPropertySampler, PipelineInfo, SceneBuilderHooks};
use webrender::{UploadMethod, VertexUsageHint};
use webrender::{UploadMethod, VertexUsageHint, ProfilerHooks, set_profiler_hooks};
use webrender::{Device, Shaders, WrShaders, ShaderPrecacheFlags};
use thread_profiler::register_thread_with_profiler;
use moz2d_renderer::Moz2dBlobImageHandler;
@ -779,6 +779,26 @@ extern "C" {
pub fn gecko_profiler_end_marker(name: *const c_char);
}
/// Simple implementation of the WR ProfilerHooks trait to allow profile
/// markers to be seen in the Gecko profiler.
struct GeckoProfilerHooks;
impl ProfilerHooks for GeckoProfilerHooks {
fn begin_marker(&self, label: &CStr) {
unsafe {
gecko_profiler_start_marker(label.as_ptr());
}
}
fn end_marker(&self, label: &CStr) {
unsafe {
gecko_profiler_end_marker(label.as_ptr());
}
}
}
const PROFILER_HOOKS: GeckoProfilerHooks = GeckoProfilerHooks {};
#[allow(improper_ctypes)] // this is needed so that rustc doesn't complain about passing the &mut Transaction to an extern function
extern "C" {
// These callbacks are invoked from the scene builder thread (aka the APZ
@ -1120,6 +1140,9 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
..Default::default()
};
// Ensure the WR profiler callbacks are hooked up to the Gecko profiler.
set_profiler_hooks(Some(&PROFILER_HOOKS));
let notifier = Box::new(CppNotifier {
window_id: window_id,
});

27
gfx/wr/Cargo.lock сгенерированный
Просмотреть файл

@ -319,6 +319,24 @@ name = "crossbeam-utils"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cstr"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cstr-macros 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cstr-macros"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "deflate"
version = "0.7.18"
@ -1075,6 +1093,11 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "procedural-masquerade"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quick-error"
version = "1.2.1"
@ -1607,6 +1630,7 @@ dependencies = [
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cstr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1883,6 +1907,8 @@ dependencies = [
"checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
"checksum cstr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ee681252c9c0a6e84bbb53257faa3d88a49ce6fb32148ae1a9dc24b588302a71"
"checksum cstr-macros 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5e700cd6ede9b3f81b23ce4cba15f75cc8bf5b5a5dce2db293b1d31f4950ed78"
"checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31"
"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871"
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
@ -1969,6 +1995,7 @@ dependencies = [
"checksum plane-split 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b84b8cf2daa6a829b3e756fb75e0eab8e0d963754de9bfc83a4373a47121323a"
"checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
"checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
"checksum procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1574a51c3fd37b26d2c0032b649d08a7d51d4cca9c41bbc5bf7118fa4509d0"
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"

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

@ -28,6 +28,7 @@ bincode = "1.0"
bitflags = "1.0"
byteorder = "1.0"
cfg-if = "0.1.2"
cstr = "0.1.2"
fxhash = "0.2.1"
gleam = "0.6.8"
image = { optional = true, version = "0.21" }

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

@ -374,6 +374,8 @@ impl FrameBuilder {
);
{
profile_marker!("UpdateVisibility");
let visibility_context = FrameVisibilityContext {
device_pixel_scale,
clip_scroll_tree,
@ -439,15 +441,19 @@ impl FrameBuilder {
)
.unwrap();
self.prim_store.prepare_primitives(
&mut prim_list,
&pic_context,
&mut pic_state,
&frame_context,
&mut frame_state,
data_stores,
scratch,
);
{
profile_marker!("PreparePrims");
self.prim_store.prepare_primitives(
&mut prim_list,
&pic_context,
&mut pic_state,
&frame_context,
&mut frame_state,
data_stores,
scratch,
);
}
let pic = &mut self.prim_store.pictures[self.root_pic_index.0];
pic.restore_context(
@ -500,6 +506,7 @@ impl FrameBuilder {
debug_flags: DebugFlags,
) -> Frame {
profile_scope!("build");
profile_marker!("BuildFrame");
debug_assert!(
DeviceIntRect::new(DeviceIntPoint::zero(), self.window_size)
.contains_rect(&self.screen_rect)
@ -546,79 +553,86 @@ impl FrameBuilder {
debug_flags,
);
resource_cache.block_until_all_resources_added(gpu_cache,
&mut render_tasks,
texture_cache_profile);
{
profile_marker!("BlockOnResources");
resource_cache.block_until_all_resources_added(gpu_cache,
&mut render_tasks,
texture_cache_profile);
}
let mut passes = vec![];
// Add passes as required for our cached render tasks.
if !render_tasks.cacheable_render_tasks.is_empty() {
passes.push(RenderPass::new_off_screen(screen_size));
for cacheable_render_task in &render_tasks.cacheable_render_tasks {
render_tasks.assign_to_passes(
*cacheable_render_task,
0,
screen_size,
&mut passes,
);
}
passes.reverse();
}
if let Some(main_render_task_id) = main_render_task_id {
let passes_start = passes.len();
passes.push(RenderPass::new_main_framebuffer(screen_size));
render_tasks.assign_to_passes(
main_render_task_id,
passes_start,
screen_size,
&mut passes,
);
passes[passes_start..].reverse();
}
let mut deferred_resolves = vec![];
let mut has_texture_cache_tasks = false;
let mut prim_headers = PrimitiveHeaders::new();
// Used to generated a unique z-buffer value per primitive.
let mut z_generator = ZBufferIdGenerator::new();
let use_dual_source_blending = self.config.dual_source_blending_is_enabled &&
self.config.dual_source_blending_is_supported;
for pass in &mut passes {
let mut ctx = RenderTargetContext {
device_pixel_scale,
prim_store: &self.prim_store,
resource_cache,
use_dual_source_blending,
clip_scroll_tree,
data_stores,
surfaces: &surfaces,
scratch,
screen_world_rect,
globals: &self.globals,
};
{
profile_marker!("Batching");
pass.build(
&mut ctx,
gpu_cache,
&mut render_tasks,
&mut deferred_resolves,
&self.clip_store,
&mut transform_palette,
&mut prim_headers,
&mut z_generator,
);
match pass.kind {
RenderPassKind::MainFramebuffer(ref color) => {
has_texture_cache_tasks |= color.must_be_drawn();
// Add passes as required for our cached render tasks.
if !render_tasks.cacheable_render_tasks.is_empty() {
passes.push(RenderPass::new_off_screen(screen_size));
for cacheable_render_task in &render_tasks.cacheable_render_tasks {
render_tasks.assign_to_passes(
*cacheable_render_task,
0,
screen_size,
&mut passes,
);
}
RenderPassKind::OffScreen { ref texture_cache, ref color, .. } => {
has_texture_cache_tasks |= !texture_cache.is_empty();
has_texture_cache_tasks |= color.must_be_drawn();
passes.reverse();
}
if let Some(main_render_task_id) = main_render_task_id {
let passes_start = passes.len();
passes.push(RenderPass::new_main_framebuffer(screen_size));
render_tasks.assign_to_passes(
main_render_task_id,
passes_start,
screen_size,
&mut passes,
);
passes[passes_start..].reverse();
}
// Used to generated a unique z-buffer value per primitive.
let mut z_generator = ZBufferIdGenerator::new();
let use_dual_source_blending = self.config.dual_source_blending_is_enabled &&
self.config.dual_source_blending_is_supported;
for pass in &mut passes {
let mut ctx = RenderTargetContext {
device_pixel_scale,
prim_store: &self.prim_store,
resource_cache,
use_dual_source_blending,
clip_scroll_tree,
data_stores,
surfaces: &surfaces,
scratch,
screen_world_rect,
globals: &self.globals,
};
pass.build(
&mut ctx,
gpu_cache,
&mut render_tasks,
&mut deferred_resolves,
&self.clip_store,
&mut transform_palette,
&mut prim_headers,
&mut z_generator,
);
match pass.kind {
RenderPassKind::MainFramebuffer(ref color) => {
has_texture_cache_tasks |= color.must_be_drawn();
}
RenderPassKind::OffScreen { ref texture_cache, ref color, .. } => {
has_texture_cache_tasks |= !texture_cache.is_empty();
has_texture_cache_tasks |= color.must_be_drawn();
}
}
}
}

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

@ -56,6 +56,8 @@ extern crate bitflags;
#[macro_use]
extern crate cfg_if;
#[macro_use]
extern crate cstr;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
@ -70,6 +72,9 @@ extern crate thread_profiler;
extern crate wr_malloc_size_of;
use wr_malloc_size_of as malloc_size_of;
#[macro_use]
mod profiler;
mod batch;
mod border;
mod box_shadow;
@ -103,7 +108,6 @@ mod internal_types;
mod picture;
mod prim_store;
mod print_tree;
mod profiler;
mod record;
mod render_backend;
mod render_task;
@ -207,6 +211,7 @@ pub use device::{ProgramBinary, ProgramCache, ProgramCacheObserver};
pub use device::Device;
pub use frame_builder::ChasePrimitive;
pub use picture::FRAMES_BEFORE_PICTURE_CACHING;
pub use profiler::{ProfilerHooks, set_profiler_hooks};
pub use renderer::{AsyncPropertySampler, CpuProfile, DebugFlags, OutputImageHandler, RendererKind};
pub use renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource, GpuProfile};
pub use renderer::{GraphicsApi, GraphicsApiInfo, PipelineInfo, Renderer, RendererOptions};

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

@ -1646,6 +1646,8 @@ impl<'a> PictureUpdateState<'a> {
clip_store: &ClipStore,
clip_data_store: &ClipDataStore,
) {
profile_marker!("UpdatePictures");
let mut state = PictureUpdateState {
surfaces,
surface_stack: vec![SurfaceIndex(0)],

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

@ -7,9 +7,10 @@ use debug_render::DebugRenderer;
use device::query::{GpuSampler, GpuTimer, NamedTag};
use euclid::{Point2D, Rect, Size2D, vec2};
use internal_types::FastHashMap;
use renderer::MAX_VERTEX_TEXTURE_WIDTH;
use renderer::{MAX_VERTEX_TEXTURE_WIDTH, wr_has_been_initialized};
use std::collections::vec_deque::VecDeque;
use std::{f32, mem};
use std::ffi::CStr;
use time::precise_time_ns;
const GRAPH_WIDTH: f32 = 1024.0;
@ -20,6 +21,68 @@ const PROFILE_PADDING: f32 = 10.0;
const ONE_SECOND_NS: u64 = 1000000000;
/// Defines the interface for hooking up an external profiler to WR.
pub trait ProfilerHooks : Send + Sync {
/// Called at the beginning of a profile scope. The label must
/// be a C string (null terminated).
fn begin_marker(&self, label: &CStr);
/// Called at the end of a profile scope. The label must
/// be a C string (null terminated).
fn end_marker(&self, label: &CStr);
}
/// The current global profiler callbacks, if set by embedder.
static mut PROFILER_HOOKS: Option<&'static ProfilerHooks> = None;
/// Set the profiler callbacks, or None to disable the profiler.
/// This function must only ever be called before any WR instances
/// have been created, or the hooks will not be set.
pub fn set_profiler_hooks(hooks: Option<&'static ProfilerHooks>) {
if !wr_has_been_initialized() {
unsafe {
PROFILER_HOOKS = hooks;
}
}
}
/// A simple RAII style struct to manage a profile scope.
pub struct ProfileScope {
name: &'static CStr,
}
impl ProfileScope {
/// Begin a new profile scope
pub fn new(name: &'static CStr) -> Self {
unsafe {
if let Some(ref hooks) = PROFILER_HOOKS {
hooks.begin_marker(name);
}
}
ProfileScope {
name,
}
}
}
impl Drop for ProfileScope {
fn drop(&mut self) {
unsafe {
if let Some(ref hooks) = PROFILER_HOOKS {
hooks.end_marker(self.name);
}
}
}
}
/// A helper macro to define profile scopes.
macro_rules! profile_marker {
($string:expr) => {
let _scope = $crate::profiler::ProfileScope::new(cstr!($string));
};
}
#[derive(Debug, Clone)]
pub struct GpuProfileTag {
pub label: &'static str,

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

@ -1252,7 +1252,7 @@ impl RenderTaskCache {
// this in the render task. The renderer will draw this
// task into the appropriate layer and rect of the texture
// cache on this frame.
let (texture_id, texture_layer, uv_rect) =
let (texture_id, texture_layer, uv_rect, _) =
texture_cache.get_cache_location(&entry.handle);
render_task.location = RenderTaskLocation::TextureCache {

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

@ -84,6 +84,7 @@ use std::os::raw::c_void;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Receiver};
use std::thread;
use std::cell::RefCell;
@ -106,6 +107,14 @@ cfg_if! {
}
}
/// Is only false if no WR instances have ever been created.
static HAS_BEEN_INITIALIZED: AtomicBool = AtomicBool::new(false);
/// Returns true if a WR instance has ever been initialized in this process.
pub fn wr_has_been_initialized() -> bool {
HAS_BEEN_INITIALIZED.load(Ordering::SeqCst)
}
pub const MAX_VERTEX_TEXTURE_WIDTH: usize = 1024;
/// Enabling this toggle would force the GPU cache scattered texture to
/// be resized every frame, which enables GPU debuggers to see if this
@ -1629,6 +1638,8 @@ impl Renderer {
mut options: RendererOptions,
shaders: Option<&mut WrShaders>
) -> Result<(Self, RenderApiSender), RendererError> {
HAS_BEEN_INITIALIZED.store(true, Ordering::SeqCst);
let (api_tx, api_rx) = channel::msg_channel()?;
let (payload_tx, payload_rx) = channel::payload_channel()?;
let (result_tx, result_rx) = channel();

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

@ -35,9 +35,9 @@ const TEXTURE_REGION_PIXELS: usize =
enum EntryDetails {
Standalone,
Cache {
// Origin within the texture layer where this item exists.
/// Origin within the texture layer where this item exists.
origin: DeviceIntPoint,
// The layer index of the texture array.
/// The layer index of the texture array.
layer_index: usize,
},
}
@ -121,12 +121,8 @@ impl CacheEntry {
fn update_gpu_cache(&mut self, gpu_cache: &mut GpuCache) {
if let Some(mut request) = gpu_cache.request(&mut self.uv_rect_handle) {
let (origin, layer_index) = match self.details {
EntryDetails::Standalone { .. } => (DeviceIntPoint::zero(), 0.0),
EntryDetails::Cache {
origin,
layer_index,
..
} => (origin, layer_index as f32),
EntryDetails::Standalone => (DeviceIntPoint::zero(), 0.0),
EntryDetails::Cache { origin, layer_index } => (origin, layer_index as f32),
};
let image_source = ImageSource {
p0: origin.to_f32(),
@ -295,10 +291,9 @@ struct EntryHandles {
impl EntryHandles {
/// Mutably borrows the requested handle list.
fn select(&mut self, kind: EntryKind) -> &mut Vec<FreeListHandle<CacheEntryMarker>> {
if kind == EntryKind::Standalone {
&mut self.standalone
} else {
&mut self.shared
match kind {
EntryKind::Standalone => &mut self.standalone,
EntryKind::Shared => &mut self.shared,
}
}
}
@ -811,12 +806,8 @@ impl TextureCache {
// in GPU memory.
if let Some(data) = data {
let (layer_index, origin) = match entry.details {
EntryDetails::Standalone { .. } => (0, DeviceIntPoint::zero()),
EntryDetails::Cache {
layer_index,
origin,
..
} => (layer_index, origin),
EntryDetails::Standalone => (0, DeviceIntPoint::zero()),
EntryDetails::Cache { layer_index, origin } => (layer_index, origin),
};
let op = TextureCacheUpdate::new_update(
@ -844,24 +835,11 @@ impl TextureCache {
// This function will assert in debug modes if the caller
// tries to get a handle that was not requested this frame.
pub fn get(&self, handle: &TextureCacheHandle) -> CacheItem {
let entry = self.entries
.get_opt(handle)
.expect("BUG: was dropped from cache or not updated!");
debug_assert_eq!(entry.last_access, self.now);
let (layer_index, origin) = match entry.details {
EntryDetails::Standalone { .. } => {
(0, DeviceIntPoint::zero())
}
EntryDetails::Cache {
layer_index,
origin,
..
} => (layer_index, origin),
};
let (texture_id, layer_index, uv_rect, uv_rect_handle) = self.get_cache_location(handle);
CacheItem {
uv_rect_handle: entry.uv_rect_handle,
texture_id: TextureSource::TextureCache(entry.texture_id),
uv_rect: DeviceIntRect::new(origin, entry.size),
uv_rect_handle,
texture_id: TextureSource::TextureCache(texture_id),
uv_rect,
texture_layer: layer_index as i32,
}
}
@ -869,11 +847,12 @@ impl TextureCache {
/// A more detailed version of get(). This allows access to the actual
/// device rect of the cache allocation.
///
/// Returns a tuple identifying the texture, the layer, and the region.
/// Returns a tuple identifying the texture, the layer, the region,
/// and its GPU handle.
pub fn get_cache_location(
&self,
handle: &TextureCacheHandle,
) -> (CacheTextureId, LayerIndex, DeviceIntRect) {
) -> (CacheTextureId, LayerIndex, DeviceIntRect, GpuCacheHandle) {
let entry = self.entries
.get_opt(handle)
.expect("BUG: was dropped from cache or not updated!");
@ -890,7 +869,8 @@ impl TextureCache {
};
(entry.texture_id,
layer_index as usize,
DeviceIntRect::new(origin, entry.size))
DeviceIntRect::new(origin, entry.size),
entry.uv_rect_handle)
}
pub fn mark_unused(&mut self, handle: &TextureCacheHandle) {
@ -980,14 +960,11 @@ impl TextureCache {
// Free a cache entry from the standalone list or shared cache.
fn free(&mut self, entry: CacheEntry) {
match entry.details {
EntryDetails::Standalone { .. } => {
EntryDetails::Standalone => {
// This is a standalone texture allocation. Free it directly.
self.pending_updates.push_free(entry.texture_id);
}
EntryDetails::Cache {
origin,
layer_index,
} => {
EntryDetails::Cache { origin, layer_index } => {
// Free the block in the given region.
let texture_array = self.shared_textures.select(entry.format, entry.filter);
let region = &mut texture_array.regions[layer_index];
@ -1202,10 +1179,11 @@ impl TextureCache {
// Handle the rare case than an update moves an entry from
// shared to standalone or vice versa. This involves a linear
// search, but should be rare enough not to matter.
let (from, to) = if new_kind == EntryKind::Standalone {
(&mut self.doc_data.handles.shared, &mut self.doc_data.handles.standalone)
} else {
(&mut self.doc_data.handles.standalone, &mut self.doc_data.handles.shared)
let (from, to) = match new_kind {
EntryKind::Standalone =>
(&mut self.doc_data.handles.shared, &mut self.doc_data.handles.standalone),
EntryKind::Shared =>
(&mut self.doc_data.handles.standalone, &mut self.doc_data.handles.shared),
};
let idx = from.iter().position(|h| h.weak() == *handle).unwrap();
to.push(from.remove(idx));

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

@ -457,6 +457,9 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
ipcController = controller.ref().ToIPC();
}
nsAutoString cspNonce;
Unused << NS_WARN_IF(NS_FAILED(aLoadInfo->GetCspNonce(cspNonce)));
*aOptionalLoadInfoArgs = LoadInfoArgs(
loadingPrincipalInfo, triggeringPrincipalInfo, principalToInheritInfo,
sandboxedLoadingPrincipalInfo, topLevelPrincipalInfo,
@ -484,7 +487,7 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
aLoadInfo->GetIsPreflight(), aLoadInfo->GetLoadTriggeredFromExternal(),
aLoadInfo->GetServiceWorkerTaintingSynthesized(),
aLoadInfo->GetDocumentHasUserInteracted(),
aLoadInfo->GetDocumentHasLoaded(),
aLoadInfo->GetDocumentHasLoaded(), cspNonce,
aLoadInfo->GetIsFromProcessingFrameAttributes());
return NS_OK;
@ -640,7 +643,7 @@ nsresult LoadInfoArgsToLoadInfo(
loadInfoArgs.isPreflight(), loadInfoArgs.loadTriggeredFromExternal(),
loadInfoArgs.serviceWorkerTaintingSynthesized(),
loadInfoArgs.documentHasUserInteracted(),
loadInfoArgs.documentHasLoaded());
loadInfoArgs.documentHasLoaded(), loadInfoArgs.cspNonce());
if (loadInfoArgs.isFromProcessingFrameAttributes()) {
loadInfo->SetIsFromProcessingFrameAttributes();

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

@ -312,6 +312,11 @@ class MessageChannel : HasResultCodes, MessageLoop::DestructionObserver {
sIsPumpingMessages = aIsPumping;
}
/**
* Does this MessageChannel cross process boundaries?
*/
bool IsCrossProcess() const { return mIsCrossProcess; }
#ifdef OS_WIN
struct MOZ_STACK_CLASS SyncStackFrame {
SyncStackFrame(MessageChannel* channel, bool interrupt);

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

@ -646,17 +646,9 @@ info needed by later passes, along with a basic name for the decl."""
self.ipdltype = ipdltype
self.name = name
def isCopyable(self):
return not _cxxTypeNeedsMove(self.ipdltype)
def var(self):
return ExprVar(self.name)
def mayMoveExpr(self):
if self.isCopyable():
return self.var()
return ExprMove(self.var())
def bareType(self, side, fq=False):
"""Return this decl's unqualified C++ type."""
return _cxxBareType(self.ipdltype, side, fq=fq)
@ -1071,7 +1063,13 @@ class MessageDecl(ipdl.ast.MessageDecl):
cxxargs = []
if paramsems == 'move':
cxxargs.extend([p.mayMoveExpr() for p in self.params])
# We don't std::move() RefPtr<T> types because current Recv*()
# implementors take these parameters as T*, and
# std::move(RefPtr<T>) doesn't coerce to T*.
cxxargs.extend([
p.var() if p.ipdltype.isCxx() and p.ipdltype.isRefcounted() else ExprMove(p.var())
for p in self.params
])
elif paramsems == 'in':
cxxargs.extend([p.var() for p in self.params])
else:

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

@ -118,13 +118,9 @@ class nsXPCComponents_Interfaces final : public nsIXPCComponents_Interfaces,
};
NS_IMETHODIMP
nsXPCComponents_Interfaces::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
*aCount = 2;
nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
*aArray = array;
array[0] = NS_GET_IID(nsIXPCComponents_Interfaces).Clone();
array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
nsXPCComponents_Interfaces::GetInterfaces(nsTArray<nsIID>& aArray) {
aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Interfaces),
NS_GET_IID(nsIXPCScriptable)};
return NS_OK;
}
@ -275,13 +271,9 @@ class nsXPCComponents_Classes final : public nsIXPCComponents_Classes,
/***************************************************************************/
NS_IMETHODIMP
nsXPCComponents_Classes::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
*aCount = 2;
nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
*aArray = array;
array[0] = NS_GET_IID(nsIXPCComponents_Classes).Clone();
array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
nsXPCComponents_Classes::GetInterfaces(nsTArray<nsIID>& aArray) {
aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Classes),
NS_GET_IID(nsIXPCScriptable)};
return NS_OK;
}
@ -432,13 +424,9 @@ class nsXPCComponents_Results final : public nsIXPCComponents_Results,
/***************************************************************************/
NS_IMETHODIMP
nsXPCComponents_Results::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
*aCount = 2;
nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
*aArray = array;
array[0] = NS_GET_IID(nsIXPCComponents_Results).Clone();
array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
nsXPCComponents_Results::GetInterfaces(nsTArray<nsIID>& aArray) {
aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Results),
NS_GET_IID(nsIXPCScriptable)};
return NS_OK;
}
@ -577,13 +565,9 @@ class nsXPCComponents_ID final : public nsIXPCComponents_ID,
/***************************************************************************/
NS_IMETHODIMP
nsXPCComponents_ID::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
*aCount = 2;
nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
*aArray = array;
array[0] = NS_GET_IID(nsIXPCComponents_ID).Clone();
array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
nsXPCComponents_ID::GetInterfaces(nsTArray<nsIID>& aArray) {
aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_ID),
NS_GET_IID(nsIXPCScriptable)};
return NS_OK;
}
@ -732,13 +716,9 @@ class nsXPCComponents_Exception final : public nsIXPCComponents_Exception,
/***************************************************************************/
NS_IMETHODIMP
nsXPCComponents_Exception::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
*aCount = 2;
nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
*aArray = array;
array[0] = NS_GET_IID(nsIXPCComponents_Exception).Clone();
array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
nsXPCComponents_Exception::GetInterfaces(nsTArray<nsIID>& aArray) {
aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Exception),
NS_GET_IID(nsIXPCScriptable)};
return NS_OK;
}
@ -1027,13 +1007,9 @@ class nsXPCComponents_Constructor final : public nsIXPCComponents_Constructor,
/***************************************************************************/
NS_IMETHODIMP
nsXPCComponents_Constructor::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
*aCount = 2;
nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
*aArray = array;
array[0] = NS_GET_IID(nsIXPCComponents_Constructor).Clone();
array[1] = NS_GET_IID(nsIXPCScriptable).Clone();
nsXPCComponents_Constructor::GetInterfaces(nsTArray<nsIID>& aArray) {
aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCComponents_Constructor),
NS_GET_IID(nsIXPCScriptable)};
return NS_OK;
}

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

@ -175,7 +175,7 @@ bool XPCConvert::NativeData2JS(MutableHandleValue d, const void* s,
XPC_LOG_ERROR(("XPCConvert::NativeData2JS : void* params not supported"));
return false;
case nsXPTType::T_IID: {
case nsXPTType::T_NSIDPTR: {
nsID* iid2 = *static_cast<nsID* const*>(s);
if (!iid2) {
d.setNull();
@ -185,6 +185,9 @@ bool XPCConvert::NativeData2JS(MutableHandleValue d, const void* s,
return xpc::ID2JSValue(cx, *iid2, d);
}
case nsXPTType::T_NSID:
return xpc::ID2JSValue(cx, *static_cast<const nsID*>(s), d);
case nsXPTType::T_ASTRING: {
const nsAString* p = static_cast<const nsAString*>(s);
if (!p || p->IsVoid()) {
@ -542,13 +545,20 @@ bool XPCConvert::JSData2Native(JSContext* cx, void* d, HandleValue s,
NS_ERROR("void* params not supported");
return false;
case nsXPTType::T_IID:
case nsXPTType::T_NSIDPTR:
if (Maybe<nsID> id = xpc::JSValue2ID(cx, s)) {
*((const nsID**)d) = id.ref().Clone();
return true;
}
return false;
case nsXPTType::T_NSID:
if (Maybe<nsID> id = xpc::JSValue2ID(cx, s)) {
*((nsID*)d) = id.ref();
return true;
}
return false;
case nsXPTType::T_ASTRING: {
nsAString* ws = (nsAString*)d;
if (s.isUndefined() || s.isNull()) {
@ -1615,7 +1625,7 @@ void xpc::InnerCleanupValue(const nsXPTType& aType, void* aValue,
break;
// Pointer Types
case nsXPTType::T_IID:
case nsXPTType::T_NSIDPTR:
case nsXPTType::T_CHAR_STR:
case nsXPTType::T_WCHAR_STR:
case nsXPTType::T_PSTRING_SIZE_IS:
@ -1647,6 +1657,11 @@ void xpc::InnerCleanupValue(const nsXPTType& aType, void* aValue,
break;
}
// Clear nsID& parameters to `0`
case nsXPTType::T_NSID:
((nsID*)aValue)->Clear();
break;
// Clear the JS::Value to `undefined`
case nsXPTType::T_JSVAL:
((JS::Value*)aValue)->setUndefined();

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

@ -71,13 +71,9 @@ BackstagePass::NewEnumerate(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
/***************************************************************************/
NS_IMETHODIMP
BackstagePass::GetInterfaces(uint32_t* aCount, nsIID*** aArray) {
*aCount = 2;
nsIID** array = static_cast<nsIID**>(moz_xmalloc(2 * sizeof(nsIID*)));
*aArray = array;
array[0] = NS_GET_IID(nsIXPCScriptable).Clone();
array[1] = NS_GET_IID(nsIScriptObjectPrincipal).Clone();
BackstagePass::GetInterfaces(nsTArray<nsIID>& aArray) {
aArray = nsTArray<nsIID>{NS_GET_IID(nsIXPCScriptable),
NS_GET_IID(nsIScriptObjectPrincipal)};
return NS_OK;
}

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

@ -231,7 +231,7 @@ bool XPCArrayHomogenizer::GetTypeForArray(JSContext* cx, HandleObject array,
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::PWSTRING);
break;
case tID:
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::PNSIID);
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::NSIDPTR);
break;
case tISup:
*resultType = nsXPTType::MkArrayType(nsXPTType::Idx::INTERFACE_IS_TYPE);
@ -466,7 +466,7 @@ bool XPCVariant::VariantDataToJS(nsIVariant* variant, nsresult* pErr,
return false;
}
nsID* v = &iid;
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, {TD_PNSIID},
return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, {TD_NSIDPTR},
&iid, 0, pErr);
}
case nsIDataType::VTYPE_ASTRING: {
@ -612,7 +612,7 @@ bool XPCVariant::VariantDataToJS(nsIVariant* variant, nsresult* pErr,
xptIndex = nsXPTType::Idx::WCHAR;
break;
case nsIDataType::VTYPE_ID:
xptIndex = nsXPTType::Idx::PNSIID;
xptIndex = nsXPTType::Idx::NSIDPTR;
break;
case nsIDataType::VTYPE_CHAR_STR:
xptIndex = nsXPTType::Idx::PSTRING;

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

@ -559,15 +559,17 @@ bool nsXPCWrappedJSClass::GetInterfaceTypeFromParam(
} else if (inner.Tag() == nsXPTType::T_INTERFACE_IS) {
// Get IID from a passed parameter.
const nsXPTParamInfo& param = method->Param(inner.ArgNum());
if (param.Type().Tag() != nsXPTType::T_IID) {
if (param.Type().Tag() != nsXPTType::T_NSID &&
param.Type().Tag() != nsXPTType::T_NSIDPTR) {
return false;
}
void* ptr = nativeParams[inner.ArgNum()].val.p;
// If the IID is passed indirectly (as an outparam), dereference by an
// extra level.
if (ptr && param.IsIndirect()) {
// If our IID is passed as a pointer outparameter, an extra level of
// dereferencing is required.
if (ptr && param.Type().Tag() == nsXPTType::T_NSIDPTR &&
param.IsIndirect()) {
ptr = *(nsID**)ptr;
}

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

@ -1262,13 +1262,23 @@ bool CallMethodHelper::GetInterfaceTypeFromParam(const nsXPTType& type,
*result = inner.GetInterface()->IID();
} else if (inner.Tag() == nsXPTType::T_INTERFACE_IS) {
nsID* id = (nsID*)GetDispatchParam(inner.ArgNum())->val.p;
if (!id) {
const nsXPTCVariant* param = GetDispatchParam(inner.ArgNum());
if (param->type.Tag() != nsXPTType::T_NSID &&
param->type.Tag() != nsXPTType::T_NSIDPTR) {
return Throw(NS_ERROR_UNEXPECTED, mCallContext);
}
const void* ptr = &param->val;
if (param->type.Tag() == nsXPTType::T_NSIDPTR) {
ptr = *static_cast<nsID* const*>(ptr);
}
if (!ptr) {
return ThrowBadParam(NS_ERROR_XPC_CANT_GET_PARAM_IFACE_INFO,
inner.ArgNum(), mCallContext);
}
*result = *id;
*result = *static_cast<const nsID*>(ptr);
}
return true;
}
@ -1499,9 +1509,9 @@ bool CallMethodHelper::ConvertIndependentParam(uint8_t i) {
// the default value if IsOptional is true.
if (i >= mArgc) {
MOZ_ASSERT(paramInfo.IsOptional(), "missing non-optional argument!");
if (type.Tag() == nsXPTType::T_IID) {
// NOTE: 'const nsIID&' is supported, so it must be allocated.
dp->val.p = new nsIID();
if (type.Tag() == nsXPTType::T_NSID) {
// Use a default value of the null ID for optional NSID objects.
dp->ext.nsid.Clear();
return true;
}
}

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

@ -513,71 +513,50 @@ already_AddRefed<XPCNativeSet> XPCNativeSet::GetNewOrUsed(
return set.forget();
}
nsIID** iidArray = nullptr;
uint32_t iidCount = 0;
if (NS_FAILED(classInfo->GetInterfaces(&iidCount, &iidArray))) {
AutoTArray<nsIID, 4> iids;
if (NS_FAILED(classInfo->GetInterfaces(iids))) {
// Note: I'm making it OK for this call to fail so that one can add
// nsIClassInfo to classes implemented in script without requiring this
// method to be implemented.
// Make sure these are set correctly...
iidArray = nullptr;
iidCount = 0;
iids.Clear();
}
MOZ_ASSERT((iidCount && iidArray) || !(iidCount || iidArray),
"GetInterfaces returned bad array");
// !!! from here on we only exit through the 'out' label !!!
if (iidCount) {
nsTArray<RefPtr<XPCNativeInterface>> interfaceArray(iidCount);
nsIID** currentIID = iidArray;
for (uint32_t i = 0; i < iidCount; i++) {
nsIID* iid = *(currentIID++);
if (!iid) {
NS_ERROR("Null found in classinfo interface list");
continue;
}
RefPtr<XPCNativeInterface> iface = XPCNativeInterface::GetNewOrUsed(iid);
if (!iface) {
// XXX warn here
continue;
}
interfaceArray.AppendElement(iface.forget());
// Try to look up each IID's XPCNativeInterface object.
nsTArray<RefPtr<XPCNativeInterface>> interfaces(iids.Length());
for (auto& iid : iids) {
RefPtr<XPCNativeInterface> iface = XPCNativeInterface::GetNewOrUsed(&iid);
if (iface) {
interfaces.AppendElement(iface.forget());
}
}
if (interfaceArray.Length() > 0) {
set = NewInstance(std::move(interfaceArray));
if (set) {
NativeSetMap* map2 = xpcrt->GetNativeSetMap();
if (!map2) {
goto out;
}
XPCNativeSetKey key(set);
XPCNativeSet* set2 = map2->Add(&key, set);
if (!set2) {
NS_ERROR("failed to add our set!");
set = nullptr;
goto out;
}
// It is okay to find an existing entry here because
// we did not look for one before we called Add().
if (set2 != set) {
set = set2;
}
// Build a set from the interfaces specified here.
if (interfaces.Length() > 0) {
set = NewInstance(std::move(interfaces));
if (set) {
NativeSetMap* map2 = xpcrt->GetNativeSetMap();
if (!map2) {
return set.forget();
}
} else
set = GetNewOrUsed(&NS_GET_IID(nsISupports));
} else
XPCNativeSetKey key(set);
XPCNativeSet* set2 = map2->Add(&key, set);
if (!set2) {
NS_ERROR("failed to add our set");
return nullptr;
}
// It is okay to find an existing entry here because
// we did not look for one before we called Add().
if (set2 != set) {
set = set2;
}
}
} else {
set = GetNewOrUsed(&NS_GET_IID(nsISupports));
}
if (set) {
#ifdef DEBUG
@ -588,11 +567,6 @@ already_AddRefed<XPCNativeSet> XPCNativeSet::GetNewOrUsed(
MOZ_ASSERT(set2 == set, "hashtables inconsistent!");
}
out:
if (iidArray) {
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(iidCount, iidArray);
}
return set.forget();
}

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

@ -2896,7 +2896,7 @@ nsIPrincipal* GetObjectPrincipal(JSObject* obj);
// a pointer to a value described by the type `nsXPTType`.
//
// This method expects a value of the following types:
// TD_PNSIID
// TD_NSIDPTR
// value : nsID* (free)
// TD_ASTRING, TD_CSTRING, TD_UTF8STRING
// value : ns[C]String* (truncate)

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

@ -59,11 +59,7 @@ BlobComponent.prototype =
// nsIClassInfo
flags: 0,
getInterfaces: function getInterfaces(aCount) {
var interfaces = [Ci.nsIClassInfo];
aCount.value = interfaces.length;
return interfaces;
},
interfaces: [Ci.nsIClassInfo],
getScriptableHelper: function getScriptableHelper() {
return null;

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

@ -90,11 +90,7 @@ FileComponent.prototype =
// nsIClassInfo
flags: 0,
getInterfaces: function getInterfaces(aCount) {
var interfaces = [Ci.nsIClassInfo];
aCount.value = interfaces.length;
return interfaces;
},
interfaces: [Ci.nsIClassInfo],
getScriptableHelper: function getScriptableHelper() {
return null;

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

@ -17,9 +17,8 @@ FooComponent.prototype =
// nsIClassInfo
flags: 0,
getInterfaces: function getInterfaces(aCount) {
get interfaces() {
var interfaces = [Ci.nsIClassInfo];
aCount.value = interfaces.length;
// Guerilla test for line numbers hiding in this method
var threw = true;
@ -27,7 +26,7 @@ FooComponent.prototype =
thereIsNoSuchIdentifier;
threw = false;
} catch (ex) {
Assert.ok(ex.lineNumber == 27);
Assert.ok(ex.lineNumber == 26);
}
Assert.ok(threw);
@ -60,11 +59,7 @@ BarComponent.prototype =
// nsIClassInfo
flags: 0,
getInterfaces: function getInterfaces(aCount) {
var interfaces = [Ci.nsIClassInfo];
aCount.value = interfaces.length;
return interfaces;
},
interfaces: [Ci.nsIClassInfo],
getScriptableHelper: function getScriptableHelper() {
return null;

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

@ -75,10 +75,10 @@ function run_test() {
// Call getInterfaces to test line numbers in JS components. But as long as
// we're doing that, why not test what it returns too?
// Kind of odd that this is not returning an array containing the
// number... Or for that matter not returning an array containing an object?
var interfaces = foo.getInterfaces({});
Assert.equal(interfaces, Ci.nsIClassInfo.number);
var interfaces = foo.interfaces;
Assert.ok(Array.isArray(interfaces));
Assert.equal(interfaces.length, 1);
Assert.ok(interfaces[0].equals(Ci.nsIClassInfo))
// try to create another component which doesn't directly implement QI
Assert.ok((contractID + "2") in Cc);

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

@ -380,9 +380,14 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
? mHelper.mMinimumScaleSize
: aState->mInsideBorderSize;
nsSize scrollPortSize =
const nsSize scrollPortSize =
nsSize(std::max(0, layoutSize.width - vScrollbarDesiredWidth),
std::max(0, layoutSize.height - hScrollbarDesiredHeight));
if (mHelper.mIsUsingMinimumScaleSize) {
mHelper.mICBSize =
nsSize(std::max(0, aState->mInsideBorderSize.width - vScrollbarDesiredWidth),
std::max(0, aState->mInsideBorderSize.height - hScrollbarDesiredHeight));
}
nsSize visualViewportSize = scrollPortSize;
nsIPresShell* presShell = PresShell();

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

@ -195,6 +195,12 @@ class ScrollFrameHelper : public nsIReflowCallback {
*/
void UpdateScrollbarPosition();
nsSize GetLayoutSize() const {
if (mIsUsingMinimumScaleSize) {
return mICBSize;
}
return mScrollPort.Size();
}
nsRect GetScrollPortRect() const { return mScrollPort; }
nsPoint GetScrollPosition() const {
return mScrollPort.TopLeft() - mScrolledFrame->GetPosition();
@ -563,6 +569,10 @@ class ScrollFrameHelper : public nsIReflowCallback {
nsRect mScrollPort;
nsSize mMinimumScaleSize;
// Stores the ICB size for the root document if this frame is using the
// minimum scale size for |mScrollPort|.
nsSize mICBSize;
// Where we're currently scrolling to, if we're scrolling asynchronously.
// If we're not in the middle of an asynchronous scroll then this is
// just the current scroll position. ScrollBy will choose its
@ -888,6 +898,9 @@ class nsHTMLScrollFrame : public nsContainerFrame,
nsBoxLayoutState bls(aPresContext, aRC, 0);
return mHelper.GetNondisappearingScrollbarWidth(&bls, aWM);
}
virtual nsSize GetLayoutSize() const override {
return mHelper.GetLayoutSize();
}
virtual nsRect GetScrolledRect() const override {
return mHelper.GetScrolledRect();
}
@ -1362,6 +1375,9 @@ class nsXULScrollFrame final : public nsBoxFrame,
nsBoxLayoutState bls(aPresContext, aRC, 0);
return mHelper.GetNondisappearingScrollbarWidth(&bls, aWM);
}
virtual nsSize GetLayoutSize() const override {
return mHelper.GetLayoutSize();
}
virtual nsRect GetScrolledRect() const override {
return mHelper.GetScrolledRect();
}

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

@ -110,6 +110,15 @@ class nsIScrollableFrame : public nsIScrollbarMediator {
virtual nscoord GetNondisappearingScrollbarWidth(
nsPresContext* aPresContext, gfxContext* aRC,
mozilla::WritingMode aWM) = 0;
/**
* Get the layout size of this frame.
* Note that this is a value which is not expanded by the minimum scale size.
* For scroll frames other than the root content document's scroll frame, this
* value will be the same as GetScrollPortRect().Size().
*
* This value is used for Element.clientWidth and clientHeight.
*/
virtual nsSize GetLayoutSize() const = 0;
/**
* GetScrolledRect is designed to encapsulate deciding which
* directions of overflow should be reachable by scrolling and which

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

@ -858,6 +858,16 @@ nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
aLoadingPrincipal, aTriggeringPrincipal, aRequestingNode,
nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, contentPolicyType);
// snapshot the nonce at load start time for performing CSP checks
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET) {
nsCOMPtr<Element> element = do_QueryInterface(aRequestingNode);
if (element && element->IsHTMLElement()) {
nsAutoString cspNonce;
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
secCheckLoadInfo->SetCspNonce(cspNonce);
}
}
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(
aTargetURI, secCheckLoadInfo, NS_LITERAL_CSTRING("text/css"), &shouldLoad,
@ -1310,6 +1320,18 @@ nsresult Loader::LoadSheet(SheetLoadData* aLoadData,
return rv;
}
// snapshot the nonce at load start time for performing CSP checks
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET) {
nsCOMPtr<Element> element =
do_QueryInterface(aLoadData->mRequestingNode);
if (element && element->IsHTMLElement()) {
nsAutoString cspNonce;
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
loadInfo->SetCspNonce(cspNonce);
}
}
nsCOMPtr<nsIInputStream> stream;
rv = channel->Open(getter_AddRefs(stream));
@ -1438,6 +1460,17 @@ nsresult Loader::LoadSheet(SheetLoadData* aLoadData,
return rv;
}
// snapshot the nonce at load start time for performing CSP checks
if (contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET) {
nsCOMPtr<Element> element = do_QueryInterface(aLoadData->mRequestingNode);
if (element && element->IsHTMLElement()) {
nsAutoString cspNonce;
element->GetAttribute(NS_LITERAL_STRING("nonce"), cspNonce);
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
loadInfo->SetCspNonce(cspNonce);
}
}
if (!aLoadData->ShouldDefer()) {
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
if (cos) {

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

@ -136,9 +136,8 @@ nsJARURI::Write(nsIObjectOutputStream *aOutputStream) {
// nsIClassInfo methods:
NS_IMETHODIMP
nsJARURI::GetInterfaces(uint32_t *count, nsIID ***array) {
*count = 0;
*array = nullptr;
nsJARURI::GetInterfaces(nsTArray<nsIID> &array) {
array.Clear();
return NS_OK;
}

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

@ -478,6 +478,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
mServiceWorkerTaintingSynthesized(false),
mDocumentHasUserInteracted(rhs.mDocumentHasUserInteracted),
mDocumentHasLoaded(rhs.mDocumentHasLoaded),
mCspNonce(rhs.mCspNonce),
mIsFromProcessingFrameAttributes(rhs.mIsFromProcessingFrameAttributes) {}
LoadInfo::LoadInfo(
@ -510,7 +511,7 @@ LoadInfo::LoadInfo(
const nsTArray<nsCString>& aCorsUnsafeHeaders, bool aForcePreflight,
bool aIsPreflight, bool aLoadTriggeredFromExternal,
bool aServiceWorkerTaintingSynthesized, bool aDocumentHasUserInteracted,
bool aDocumentHasLoaded)
bool aDocumentHasLoaded, const nsAString& aCspNonce)
: mLoadingPrincipal(aLoadingPrincipal),
mTriggeringPrincipal(aTriggeringPrincipal),
mPrincipalToInherit(aPrincipalToInherit),
@ -556,6 +557,7 @@ LoadInfo::LoadInfo(
mServiceWorkerTaintingSynthesized(aServiceWorkerTaintingSynthesized),
mDocumentHasUserInteracted(aDocumentHasUserInteracted),
mDocumentHasLoaded(aDocumentHasLoaded),
mCspNonce(aCspNonce),
mIsFromProcessingFrameAttributes(false) {
// Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal
MOZ_ASSERT(mLoadingPrincipal ||
@ -1254,6 +1256,20 @@ LoadInfo::SetDocumentHasLoaded(bool aDocumentHasLoaded) {
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetCspNonce(nsAString& aCspNonce) {
aCspNonce = mCspNonce;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::SetCspNonce(const nsAString& aCspNonce) {
MOZ_ASSERT(!mInitialSecurityCheckDone,
"setting the nonce is only allowed before any sec checks");
mCspNonce = aCspNonce;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetIsTopLevelLoad(bool* aResult) {
*aResult = mFrameOuterWindowID ? mFrameOuterWindowID == mOuterWindowID

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

@ -12,6 +12,7 @@
#include "nsIPrincipal.h"
#include "nsIWeakReferenceUtils.h" // for nsWeakPtr
#include "nsIURI.h"
#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/BasePrincipal.h"
@ -121,7 +122,8 @@ class LoadInfo final : public nsILoadInfo {
const nsTArray<nsCString>& aUnsafeHeaders, bool aForcePreflight,
bool aIsPreflight, bool aLoadTriggeredFromExternal,
bool aServiceWorkerTaintingSynthesized,
bool aDocumentHasUserInteracted, bool aDocumentHasLoaded);
bool aDocumentHasUserInteracted, bool aDocumentHasLoaded,
const nsAString& aCspNonce);
LoadInfo(const LoadInfo& rhs);
NS_IMETHOD GetRedirects(JSContext* aCx,
@ -198,6 +200,7 @@ class LoadInfo final : public nsILoadInfo {
bool mServiceWorkerTaintingSynthesized;
bool mDocumentHasUserInteracted;
bool mDocumentHasLoaded;
nsString mCspNonce;
// Is true if this load was triggered by processing the attributes of the
// browsing context container.

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

@ -1047,6 +1047,14 @@ interface nsILoadInfo : nsISupports
*/
[infallible] attribute boolean documentHasLoaded;
/**
* A snapshot of the nonce at load start time which is used for CSP
* checks and only set for:
* * TYPE_SCRIPT and
* * TYPE_STYLESHEET
*/
attribute AString cspNonce;
/**
* The object in charged to receive CSP violation events. It can be null.
* This attribute will be merged into the CSP object eventually.

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

@ -607,9 +607,8 @@ nsSimpleURI::GetAsciiHost(nsACString &result) {
//----------------------------------------------------------------------------
NS_IMETHODIMP
nsSimpleURI::GetInterfaces(uint32_t *count, nsIID ***array) {
*count = 0;
*array = nullptr;
nsSimpleURI::GetInterfaces(nsTArray<nsIID> &array) {
array.Clear();
return NS_OK;
}

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

@ -2944,8 +2944,8 @@ nsSocketTransport::GetInterface(const nsIID &iid, void **result) {
}
NS_IMETHODIMP
nsSocketTransport::GetInterfaces(uint32_t *count, nsIID ***array) {
return NS_CI_INTERFACE_GETTER_NAME(nsSocketTransport)(count, array);
nsSocketTransport::GetInterfaces(nsTArray<nsIID>& array) {
return NS_CI_INTERFACE_GETTER_NAME(nsSocketTransport)(array);
}
NS_IMETHODIMP

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

@ -3447,9 +3447,8 @@ bool nsStandardURL::Deserialize(const URIParams &aParams) {
//----------------------------------------------------------------------------
NS_IMETHODIMP
nsStandardURL::GetInterfaces(uint32_t *count, nsIID ***array) {
*count = 0;
*array = nullptr;
nsStandardURL::GetInterfaces(nsTArray<nsIID> &array) {
array.Clear();
return NS_OK;
}

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

@ -109,6 +109,7 @@ struct LoadInfoArgs
bool serviceWorkerTaintingSynthesized;
bool documentHasUserInteracted;
bool documentHasLoaded;
nsString cspNonce;
bool isFromProcessingFrameAttributes;
};

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

@ -516,9 +516,8 @@ TransportSecurityInfo::Read(nsIObjectInputStream* aStream) {
}
NS_IMETHODIMP
TransportSecurityInfo::GetInterfaces(uint32_t* count, nsIID*** array) {
*count = 0;
*array = nullptr;
TransportSecurityInfo::GetInterfaces(nsTArray<nsIID>& array) {
array.Clear();
return NS_OK;
}

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

@ -1227,9 +1227,8 @@ nsNSSCertificate::Read(nsIObjectInputStream* aStream) {
}
NS_IMETHODIMP
nsNSSCertificate::GetInterfaces(uint32_t* count, nsIID*** array) {
*count = 0;
*array = nullptr;
nsNSSCertificate::GetInterfaces(nsTArray<nsIID>& array) {
array.Clear();
return NS_OK;
}

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

@ -45,8 +45,8 @@ class AsyncStatementClassInfo : public nsIClassInfo {
NS_DECL_ISUPPORTS_INHERITED
NS_IMETHOD
GetInterfaces(uint32_t *_count, nsIID ***_array) override {
return NS_CI_INTERFACE_GETTER_NAME(AsyncStatement)(_count, _array);
GetInterfaces(nsTArray<nsIID> &_array) override {
return NS_CI_INTERFACE_GETTER_NAME(AsyncStatement)(_array);
}
NS_IMETHOD

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

@ -47,8 +47,8 @@ class StatementClassInfo : public nsIClassInfo {
NS_DECL_ISUPPORTS_INHERITED
NS_IMETHOD
GetInterfaces(uint32_t *_count, nsIID ***_array) override {
return NS_CI_INTERFACE_GETTER_NAME(Statement)(_count, _array);
GetInterfaces(nsTArray<nsIID> &_array) override {
return NS_CI_INTERFACE_GETTER_NAME(Statement)(_array);
}
NS_IMETHOD

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

@ -104,6 +104,7 @@ mochitest-browser-chrome:
by-test-platform:
linux64-.*cov/opt: 7200
windows10-64-ccov/debug: 7200
windows10-aarch64/*: 7200
macosx64-ccov/debug: 10800
linux.*/debug: 5400
default: 3600

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

@ -291,10 +291,12 @@ talos-xperf:
run-as-administrator:
by-test-platform:
windows7-32.*: false
windows10-aarch64.*: false
windows10-64.*: true
run-on-projects:
by-test-platform:
windows7-32(-pgo)?/.*: ['mozilla-beta', 'trunk', 'try']
windows10-aarch64/opt: []
windows10-64.*/opt: ['mozilla-beta', 'trunk', 'try']
default: []
tier:

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

@ -205,6 +205,18 @@ windows10-64/opt:
- mochitest-headless
- raptor-firefox
# windows10-aarch64/opt:
# build-platform: win64-aarch64/opt
# test-sets:
# - awsy
# - desktop-screenshot-capture
# - windows-talos
# - marionette-gpu-tests
# - windows-tests
# - web-platform-tests
# - mochitest-headless
# - raptor-firefox
windows10-64-ux/opt:
build-platform: win64-nightly/opt
test-sets:

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

@ -35,6 +35,7 @@ web-platform-tests:
macosx64.*/opt: 8
macosx64/debug: 16
windows10.*/debug: 18
windows10-aarch64/opt: 12
macosx64-ccov/debug: 24
default: 12
max-run-time:
@ -49,6 +50,7 @@ web-platform-tests:
run-on-projects:
by-test-platform:
android.*: ['mozilla-central', 'try']
windows10-aarch64/opt: ['try', 'mozilla-central']
.*-qr/.*: ['release', 'try'] # skip on integration branches due to high load
default: built-projects
tier:
@ -104,6 +106,7 @@ web-platform-tests-reftests:
run-on-projects:
by-test-platform:
android.*: ['mozilla-central', 'try']
windows10-aarch64/opt: ['try', 'mozilla-central']
linux64-qr/.*: ['release', 'try'] # skip on integration branches due to high load
default: built-projects
tier:
@ -151,6 +154,7 @@ web-platform-tests-wdspec:
- --test-type=wdspec
run-on-projects:
by-test-platform:
windows10-aarch64/opt: ['try', 'mozilla-central']
android.*: ['mozilla-central', 'try']
.*-qr/.*: ['release', 'try'] # skip on integration branches due to high load
default: built-projects

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

@ -23,6 +23,7 @@ job-defaults:
requires-signed-builds:
by-test-platform:
windows10-64-asan/opt: false # No XPCShell on ASAN yet
windows10-aarch64/*: false # No signing on arm64
windows.*: true
default: false
@ -33,6 +34,7 @@ xpcshell:
run-on-projects:
by-test-platform:
windows10-64-asan/opt: [] # No XPCShell on ASAN yet
windows10-aarch64/opt: ['try', 'mozilla-central']
default: built-projects
chunks:
by-test-platform:
@ -41,6 +43,7 @@ xpcshell:
android-em-4.3-arm7-api-16/debug: 12
macosx.*: 1
windows.*: 1
windows10-aarch64/opt: 8
windows10-64-ccov/debug: 8
macosx64-ccov/debug: 8
default: 8

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

@ -77,6 +77,11 @@ WINDOWS_WORKER_TYPES = {
'virtual-with-gpu': 'aws-provisioner-v1/gecko-t-win10-64-gpu',
'hardware': 'releng-hardware/gecko-t-win10-64-hw',
},
'windows10-aarch64': {
'virtual': 'test-provisioner/bitbar',
'virtual-with-gpu': 'test-provisioner/bitbar',
'hardware': 'test-provisioner/bitbar',
},
'windows10-64-ccov': {
'virtual': 'aws-provisioner-v1/gecko-t-win10-64',
'virtual-with-gpu': 'aws-provisioner-v1/gecko-t-win10-64-gpu',
@ -583,6 +588,7 @@ def set_treeherder_machine_platform(config, tests):
'macosx64/debug': 'osx-10-10/debug',
'macosx64/opt': 'osx-10-10/opt',
'win64-asan/opt': 'windows10-64/asan',
'win64-aarch64/opt': 'windows10-aarch64/opt',
'win32-pgo/opt': 'windows7-32/pgo',
'win64-pgo/opt': 'windows10-64/pgo',
# The build names for Android platforms have partially evolved over the
@ -644,6 +650,7 @@ def set_tier(config, tests):
'windows7-32-pgo/opt',
'windows7-32-devedition/opt',
'windows7-32-nightly/opt',
'windows10-aarch64/opt',
'windows10-64/debug',
'windows10-64/opt',
'windows10-64-pgo/opt',

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

@ -34,6 +34,7 @@ WORKER_TYPES = {
'aws-provisioner-v1/gecko-t-win7-32': ('generic-worker', 'windows'),
'aws-provisioner-v1/gecko-t-win7-32-gpu': ('generic-worker', 'windows'),
'releng-hardware/gecko-t-win7-32-hw': ('generic-worker', 'windows'),
'test-provisioner/bitbar': ('generic-worker', 'windows'),
'aws-provisioner-v1/taskcluster-generic': ('docker-worker', 'linux'),
'invalid/invalid': ('invalid', None),
'invalid/always-optimized': ('always-optimized', None),

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

@ -724,7 +724,7 @@ class AndroidEmulator(object):
if not self.substs['TARGET_CPU'].startswith('arm'):
return 'x86-7.0'
else:
return '7.0'
return '4.3'
return 'x86-7.0'

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

@ -132,10 +132,6 @@ class RaptorRunner(MozbuildObject):
'title': socket.gethostname(),
'default_actions': default_actions,
'raptor_cmd_line_args': self.raptor_args,
'python3_manifest': {
'win32': 'python3.manifest',
'win64': 'python3_x64.manifest',
},
'host': self.host,
'power_test': self.power_test,
'is_release_build': self.is_release_build,

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

@ -19,7 +19,7 @@ required_settings = ['apps', 'type', 'page_cycles', 'test_url', 'measure',
'unit', 'lower_is_better', 'alert_threshold']
playback_settings = ['playback_binary_manifest', 'playback_pageset_manifest',
'playback_recordings', 'python3_win_manifest']
'playback_recordings']
def filter_app(tests, values):

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

@ -0,0 +1,10 @@
[
{
"size": 13576786,
"visibility": "public",
"digest": "5d471e470369381f130de28a3c54db27c3724e1e9269c510a593d61c4cf41713c9424da62e46ae98fd1decce00ecca876209ed059487f5a02882ba16a50daed1",
"algorithm": "sha512",
"filename": "mitmdump-win-2.0.2.zip",
"unpack": true
}
]

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

@ -12,6 +12,7 @@ import time
import mozinfo
from mozlog import get_proxy_logger
from mozprocess import ProcessHandler
from .base import Playback
@ -27,11 +28,6 @@ else:
mozharness_dir = os.path.join(here, '../../../mozharness')
sys.path.insert(0, mozharness_dir)
# required for using a python3 virtualenv on win for mitmproxy
from mozharness.base.python import Python3Virtualenv
from mozharness.mozilla.testing.testbase import TestingMixin
from mozharness.base.vcs.vcsbase import MercurialScript
raptor_dir = os.path.join(here, '..')
sys.path.insert(0, raptor_dir)
@ -79,7 +75,7 @@ POLICIES_CONTENT_OFF = '''{
}'''
class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
class Mitmproxy(Playback):
def __init__(self, config):
self.config = config
@ -106,10 +102,6 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
# go ahead and download and setup mitmproxy
self.download()
# on windows we must use a python3 virtualen for mitmproxy
if 'win' in self.config['platform']:
self.setup_py3_virtualenv()
# mitmproxy must be started before setup, so that the CA cert is available
self.start()
self.setup()
@ -119,16 +111,10 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
if not os.path.exists(self.raptor_dir):
os.makedirs(self.raptor_dir)
if 'win' in self.config['platform']:
# on windows we need a python3 environment and use our own package from tooltool
self.py3_path = self.fetch_python3()
LOG.info("python3 path is: %s" % self.py3_path)
else:
# on osx and linux we use pre-built binaries
LOG.info("downloading mitmproxy binary")
_manifest = os.path.join(here, self.config['playback_binary_manifest'])
transformed_manifest = transform_platform(_manifest, self.config['platform'])
tooltool_download(transformed_manifest, self.config['run_local'], self.raptor_dir)
LOG.info("downloading mitmproxy binary")
_manifest = os.path.join(here, self.config['playback_binary_manifest'])
transformed_manifest = transform_platform(_manifest, self.config['platform'])
tooltool_download(transformed_manifest, self.config['run_local'], self.raptor_dir)
# we use one pageset for all platforms
LOG.info("downloading mitmproxy pageset")
@ -137,44 +123,10 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
tooltool_download(transformed_manifest, self.config['run_local'], self.raptor_dir)
return
def fetch_python3(self):
"""Mitmproxy on windows needs Python 3.x"""
python3_path = os.path.join(self.raptor_dir, 'python3.6', 'python')
if not os.path.exists(os.path.dirname(python3_path)):
_manifest = os.path.join(here, self.config['python3_win_manifest'])
transformed_manifest = transform_platform(_manifest, self.config['platform'],
self.config['processor'])
LOG.info("downloading py3 package for mitmproxy windows: %s" % transformed_manifest)
tooltool_download(transformed_manifest, self.config['run_local'], self.raptor_dir)
cmd = [python3_path, '--version']
# just want python3 ver printed in production log
subprocess.Popen(cmd, env=os.environ.copy())
return python3_path
def setup_py3_virtualenv(self):
"""Mitmproxy on windows needs Python 3.x; set up a separate py 3.x env here"""
LOG.info("Setting up python 3.x virtualenv, required for mitmproxy on windows")
# these next two are required for py3_venv_configuration
self.abs_dirs = {'base_work_dir': mozharness_dir}
self.log_obj = None
# now create the py3 venv
venv_path = os.path.join(self.raptor_dir, 'py3venv')
self.py3_venv_configuration(python_path=self.py3_path, venv_path=venv_path)
self.py3_create_venv()
self.py3_install_modules(["cffi==1.10.0"])
requirements = [os.path.join(here, "mitmproxy_requirements.txt")]
self.py3_install_requirement_files(requirements)
# add py3 executables path to system path
sys.path.insert(1, self.py3_path_to_executables())
# install mitmproxy itself
self.py3_install_modules(modules=['mitmproxy'])
self.mitmdump_path = os.path.join(self.py3_path_to_executables(), 'mitmdump')
def start(self):
"""Start playing back the mitmproxy recording. If on windows, the mitmdump_path was
already set when creating py3 env"""
if self.mitmdump_path is None:
self.mitmdump_path = os.path.join(self.raptor_dir, 'mitmdump')
"""Start playing back the mitmproxy recording."""
self.mitmdump_path = os.path.join(self.raptor_dir, 'mitmdump')
recordings_list = self.recordings.split()
self.mitmproxy_proc = self.start_mitmproxy_playback(self.mitmdump_path,
@ -228,7 +180,9 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
LOG.info("Starting mitmproxy playback using command: %s" % ' '.join(command))
# to turn off mitmproxy log output, use these params for Popen:
# Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
mitmproxy_proc = subprocess.Popen(command, env=env)
mitmproxy_proc = ProcessHandler(command, env=env)
mitmproxy_proc.run()
time.sleep(MITMDUMP_SLEEP)
data = mitmproxy_proc.poll()
if data is None: # None value indicates process hasn't terminated
@ -242,10 +196,8 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
"""Stop the mitproxy server playback"""
mitmproxy_proc = self.mitmproxy_proc
LOG.info("Stopping mitmproxy playback, klling process %d" % mitmproxy_proc.pid)
if mozinfo.os == 'win':
mitmproxy_proc.kill()
else:
mitmproxy_proc.terminate()
mitmproxy_proc.kill()
time.sleep(MITMDUMP_SLEEP)
status = mitmproxy_proc.poll()
if status is None: # None value indicates process hasn't terminated
@ -334,8 +286,8 @@ class MitmproxyDesktop(Mitmproxy):
LOG.info("Firefox policies file contents:")
LOG.info(contents)
if (POLICIES_CONTENT_ON % {
'cert': self.cert_path,
'host': self.config['host']}) in contents:
'cert': self.cert_path,
'host': self.config['host']}) in contents:
LOG.info("Verified mitmproxy CA certificate is installed in Firefox")
else:

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

@ -1,10 +0,0 @@
[
{
"size": 15380470,
"visibility": "public",
"digest": "cd78b88d95b69bef99d7192b71dd34118700f44db0a0069a13bfd4943b131e8d7fdac83859f8ac15d873d4b329eef69d8d75d0a6746d06fdcfc5d06da0c9784c",
"algorithm": "sha512",
"unpack": true,
"filename": "python3.6.zip"
}
]

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

@ -1,10 +0,0 @@
[
{
"size": 16026760,
"visibility": "public",
"digest": "379428e3955671213a245ccd9ccf6f9d17d368db68c02da8baed7be629f2691127cd3e3f86807b25e2098d9840083fdc07946ab1bed0c14db4a5b628a47ed9ef",
"algorithm": "sha512",
"unpack": true,
"filename": "python3.6.amd64.zip"
}
]

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

@ -171,7 +171,6 @@ class Raptor(object):
_key = 'playback_pageset_zip_%s' % self.config['platform']
self.config['playback_pageset_zip'] = test.get(_key, None)
self.config['playback_recordings'] = test.get('playback_recordings', None)
self.config['python3_win_manifest'] = test.get('python3_win_manifest', None)
def run_test(self, test, timeout=None):
self.log.info("starting raptor test: %s" % test['name'])

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

@ -8,7 +8,6 @@
type = pageload
playback = mitmproxy
playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
python3_win_manifest = python3{x64}.manifest
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-1.manifest
page_cycles = 25
unit = ms

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

@ -8,7 +8,6 @@
type = pageload
playback = mitmproxy
playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
python3_win_manifest = python3{x64}.manifest
page_cycles = 25
unit = ms
lower_is_better = true

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

@ -8,7 +8,6 @@
type = pageload
playback = mitmproxy
playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
python3_win_manifest = python3{x64}.manifest
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-2.manifest
page_cycles = 25
unit = ms

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