Merge autoland to mozilla-central. a=merge

This commit is contained in:
Csoregi Natalia 2020-01-16 23:44:43 +02:00
Родитель ffc90b2ec8 99cf823836
Коммит cf4fe0aaee
186 изменённых файлов: 2301 добавлений и 1548 удалений

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

@ -511,7 +511,6 @@ module.exports = {
"dom/base/test/chrome/test_bug683852.xhtml",
"dom/base/test/chrome/test_bug780529.xhtml",
"dom/base/test/chrome/test_bug800386.xhtml",
"dom/base/test/chrome/test_bug814638.xhtml",
"dom/base/test/chrome/test_bug884693.xhtml",
"dom/base/test/chrome/test_document-element-inserted.xhtml",
"dom/base/test/chrome/test_domparsing.xhtml",

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

@ -710,17 +710,9 @@
obj = {
role: ROLE_SPINBUTTON,
interfaces: [ nsIAccessibleValue ],
interfaces: [ nsIAccessibleValue, nsIAccessibleText, nsIAccessibleEditableText ],
children: [
{ role: ROLE_TEXT_LEAF },
{
role: ROLE_PUSHBUTTON,
actions: "press",
},
{
role: ROLE_PUSHBUTTON,
actions: "press",
},
],
};
testElm("input_number", obj);

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

@ -62,11 +62,7 @@
testAccessibleTree("range", accTree);
// input@type="number"
accTree =
{ SPINBUTTON: [
{ PUSHBUTTON: [ ] },
{ PUSHBUTTON: [ ] },
] };
accTree = { SPINBUTTON: [ ] };
testAccessibleTree("number", accTree);
// output

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

@ -2293,13 +2293,6 @@ pref("devtools.debugger.features.map-await-expression", true);
// about:devtools-toolbox tabs unusable by mistake.
pref("devtools.popup.disable_autohide", false);
// Load the DevTools toolbox in a frame with type=content instead of type=chrome
// See Bug 1539979 for more details.
// We keep the option of running devtools in a chrome frame while we fix racy
// tests that started failing when using type=content, but this ultimately
// should be removed.
pref("devtools.toolbox.content-frame", true);
// Visibility switch preference for the WhatsNew panel.
pref("devtools.whatsnew.enabled", true);

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

@ -74,7 +74,7 @@ body {
%endif
}
:root[customize-entered] {
:root[customizing] {
min-width: -moz-fit-content;
}
@ -788,7 +788,6 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks {
toolbarpaletteitem[place=toolbar][id^=wrapper-customizableui-special-spring],
toolbarspring {
-moz-box-flex: 1;
min-width: 1px;
max-width: 112px;
}

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

@ -2893,7 +2893,10 @@ function focusAndSelectUrlBar() {
// finished leaving customize mode, and the url bar will still be disabled.
// We can't focus it when it's disabled, so we need to re-run ourselves when
// we've finished leaving customize mode.
if (CustomizationHandler.isCustomizing()) {
if (
CustomizationHandler.isCustomizing() ||
CustomizationHandler.isExitingCustomizeMode
) {
gNavToolbox.addEventListener("aftercustomization", focusAndSelectUrlBar, {
once: true,
});

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

@ -2634,12 +2634,17 @@
this.tabContainer.getAttribute("overflow") != "true" &&
this.animationsEnabled;
// Related tab inherits current tab's user context unless a different
// usercontextid is specified
if (userContextId == null && openerTab) {
userContextId = openerTab.getAttribute("usercontextid") || 0;
}
this.setTabAttributes(t, {
animate,
noInitialLabel,
aURI,
userContextId,
openerTab,
skipBackgroundNotify,
pinned,
skipAnimation,
@ -3111,7 +3116,6 @@
noInitialLabel,
aURI,
userContextId,
openerTab,
skipBackgroundNotify,
pinned,
skipAnimation,
@ -3126,12 +3130,6 @@
}
}
// Related tab inherits current tab's user context unless a different
// usercontextid is specified
if (userContextId == null && openerTab) {
userContextId = openerTab.getAttribute("usercontextid") || 0;
}
if (userContextId) {
tab.setAttribute("usercontextid", userContextId);
ContextualIdentityService.setTabStyle(tab);

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

@ -1,9 +1,14 @@
[DEFAULT]
support-files =
head.js
open_and_focus_helper.html
[browser_bug1557041.js]
skip-if = os == 'linux' # Bug 1561973
[browser_fullscreen_permissions_prompt.js]
skip-if = debug && os == 'mac' # Bug 1568570
[browser_fullscreen_cross_origin.js]
support-files = fullscreen.html fullscreen_frame.html
[browser_fullscreen_window_open.js]
skip-if = debug && os == 'mac' # Bug 1568570
[browser_fullscreen_window_focus.js]
skip-if = debug && os == 'mac' # Bug 1568570

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

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// This test tends to trigger a race in the fullscreen time telemetry,
// where the fullscreen enter and fullscreen exit events (which use the
// same histogram ID) overlap. That causes TelemetryStopwatch to log an
// error.
SimpleTest.ignoreAllUncaughtExceptions(true);
const TEST_URL =
"http://example.com/browser/browser/base/content/test/fullscreen/open_and_focus_helper.html";
const IFRAME_ID = "testIframe";
async function testWindowFocus(iframeID) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
info("Calling window.open()");
let popup = await jsWindowOpen(tab.linkedBrowser, iframeID);
info("re-focusing main window");
await waitForFocus();
info("Entering full-screen");
await changeFullscreen(tab.linkedBrowser, true);
await testExpectFullScreenExit(tab.linkedBrowser, true, async () => {
info("Calling window.focus()");
await jsWindowFocus(tab.linkedBrowser, iframeID);
});
// Cleanup
popup.close();
BrowserTestUtils.removeTab(tab);
}
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [
["dom.disable_open_during_load", false], // Allow window.focus calls without user interaction
["browser.link.open_newwindow.disabled_in_fullscreen", false],
],
});
});
add_task(function test_parentWindowFocus() {
return testWindowFocus();
});
add_task(function test_iframeWindowFocus() {
return testWindowFocus(IFRAME_ID);
});

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

@ -0,0 +1,48 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// This test tends to trigger a race in the fullscreen time telemetry,
// where the fullscreen enter and fullscreen exit events (which use the
// same histogram ID) overlap. That causes TelemetryStopwatch to log an
// error.
SimpleTest.ignoreAllUncaughtExceptions(true);
SimpleTest.requestLongerTimeout(2);
const TEST_URL =
"http://example.com/browser/browser/base/content/test/fullscreen/open_and_focus_helper.html";
const IFRAME_ID = "testIframe";
async function testWindowOpen(iframeID) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
info("Entering full-screen");
await changeFullscreen(tab.linkedBrowser, true);
let popup;
await testExpectFullScreenExit(tab.linkedBrowser, true, async () => {
info("Calling window.open()");
popup = await jsWindowOpen(tab.linkedBrowser, iframeID);
});
// Cleanup
await BrowserTestUtils.closeWindow(popup);
BrowserTestUtils.removeTab(tab);
}
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [
["dom.disable_open_during_load", false], // Allow window.open calls without user interaction
["browser.link.open_newwindow.disabled_in_fullscreen", false],
],
});
});
add_task(function test_parentWindowOpen() {
return testWindowOpen();
});
add_task(function test_iframeWindowOpen() {
return testWindowOpen(IFRAME_ID);
});

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

@ -2,7 +2,6 @@ const { ContentTaskUtils } = ChromeUtils.import(
"resource://testing-common/ContentTaskUtils.jsm"
);
function waitForFullScreenState(browser, state) {
info("inside waitforfullscreenstate");
return new Promise(resolve => {
let eventReceived = false;
@ -15,7 +14,7 @@ function waitForFullScreenState(browser, state) {
};
Services.obs.addObserver(observe, "fullscreen-painted");
window.addEventListener(
browser.ownerGlobal.addEventListener(
`MozDOMFullscreen:${state ? "Entered" : "Exited"}`,
() => {
eventReceived = true;
@ -50,3 +49,78 @@ async function changeFullscreen(browser, fullScreenState) {
});
return fullScreenChange;
}
async function testExpectFullScreenExit(browser, leaveFS, action) {
let fsPromise = waitForFullScreenState(browser, !leaveFS);
if (leaveFS) {
if (action) {
await action();
}
await fsPromise;
ok(true, "Should leave full-screen");
} else {
if (action) {
await action();
}
let result = await Promise.race([
fsPromise,
new Promise(resolve => {
SimpleTest.requestFlakyTimeout("Wait for failure condition");
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
setTimeout(() => resolve(true), 2500);
}),
]);
ok(result, "Should not leave full-screen");
}
}
function jsWindowFocus(browser, iframeId) {
return ContentTask.spawn(browser, { iframeId }, async args => {
let destWin = content;
if (args.iframeId) {
let iframe = content.document.getElementById(args.iframeId);
if (!iframe) {
throw new Error("iframe not set");
}
destWin = iframe.contentWindow;
}
await content.wrappedJSObject.sendMessage(destWin, "focus");
});
}
async function jsWindowOpen(browser, iframeId) {
let windowOpened = BrowserTestUtils.waitForNewWindow();
ContentTask.spawn(browser, { iframeId }, async args => {
let destWin = content;
if (args.iframeId) {
// Create a cross origin iframe
destWin = (await content.wrappedJSObject.createIframe(
args.iframeId,
true
)).contentWindow;
}
// Send message to either the iframe or the current page to open a popup
await content.wrappedJSObject.sendMessage(destWin, "open");
});
return windowOpened;
}
function waitForFocus(...args) {
return new Promise(resolve => SimpleTest.waitForFocus(resolve, ...args));
}
function waitForBrowserWindowActive(win) {
return new Promise(resolve => {
if (Services.focus.activeWindow == win) {
resolve();
} else {
win.addEventListener(
"activate",
() => {
resolve();
},
{ once: true }
);
}
});
}

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

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
</head>
<body>
<script>
const MY_ORIGIN = window.location.origin;
const CROSS_ORIGIN = "https://example.org";
// Creates an iframe with message channel to trigger window open and focus
window.createIframe = function(id, crossOrigin = false) {
return new Promise(resolve => {
const origin = crossOrigin ? CROSS_ORIGIN : MY_ORIGIN;
let iframe = document.createElement("iframe");
iframe.id = id;
iframe.src = origin + window.location.pathname;
iframe.onload = () => resolve(iframe);
document.body.appendChild(iframe);
});
}
window.sendMessage = function(destWin, msg) {
return new Promise(resolve => {
let channel = new MessageChannel();
channel.port1.onmessage = resolve;
destWin.postMessage(msg, "*", [channel.port2]);
});
}
window.onMessage = function(event) {
let canReply = event.ports && !!event.ports.length;
if(event.data === "open") {
window.popup = window.open('https://example.com', '', 'top=0,height=1, width=300');
if (canReply) event.ports[0].postMessage('opened');
} else if(event.data === "focus") {
window.popup.focus();
if (canReply) event.ports[0].postMessage('focused');
}
}
window.addEventListener('message', window.onMessage);
</script>
</body>
</html>

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

@ -775,12 +775,14 @@ async function runUrlbarTest(
// So we just whitelist the whole urlbar. We don't check the bottom of
// the rect because the result view height varies depending on the
// results.
// We use floor/ceil because the Urlbar dimensions aren't always
// integers.
return rects.filter(
r =>
!(
r.x1 >= urlbarRect.left - SHADOW_SIZE &&
r.x2 <= urlbarRect.right + SHADOW_SIZE &&
r.y1 >= urlbarRect.top - SHADOW_SIZE
r.x1 >= Math.floor(urlbarRect.left) - SHADOW_SIZE &&
r.x2 <= Math.ceil(urlbarRect.right) + SHADOW_SIZE &&
r.y1 >= Math.floor(urlbarRect.top) - SHADOW_SIZE
)
);
},
@ -800,16 +802,16 @@ async function runUrlbarTest(
r =>
!// We put text into the urlbar so expect its textbox to change.
(
(r.x1 >= textBoxRect.left &&
r.x2 <= textBoxRect.right &&
r.y1 >= textBoxRect.top &&
r.y2 <= textBoxRect.bottom) ||
(r.x1 >= Math.floor(textBoxRect.left) &&
r.x2 <= Math.ceil(textBoxRect.right) &&
r.y1 >= Math.floor(textBoxRect.top) &&
r.y2 <= Math.ceil(textBoxRect.bottom)) ||
// The dropmarker is displayed as active during some of the test.
// dropmarkerRect.left isn't always an integer, hence the - 1 and + 1
(r.x1 >= dropmarkerRect.left - 1 &&
r.x2 <= dropmarkerRect.right + 1 &&
r.y1 >= dropmarkerRect.top &&
r.y2 <= dropmarkerRect.bottom)
// dropmarkerRect.left isn't always an integer.
(r.x1 >= Math.floor(dropmarkerRect.left) &&
r.x2 <= Math.ceil(dropmarkerRect.right) &&
r.y1 >= Math.floor(dropmarkerRect.top) &&
r.y2 <= Math.ceil(dropmarkerRect.bottom))
)
),
};

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

@ -23,6 +23,11 @@ add_task(async function() {
1,
"Related tab (relatedToCurrent) inherits current tab's usercontextid"
);
is(
relatedTab.linkedBrowser.contentPrincipal.userContextId,
1,
"Related tab's browser actually inherits the current tab's usercontextid"
);
BrowserTestUtils.removeTab(relatedTab);
gBrowser.selectedTab = tab;
@ -35,6 +40,11 @@ add_task(async function() {
2,
"Related tab (relatedToCurrent) with overridden usercontextid"
);
is(
relatedTab.linkedBrowser.contentPrincipal.userContextId,
2,
"Related tab's browser actually gets overridden usercontextid"
);
BrowserTestUtils.removeTab(relatedTab);
gBrowser.selectedTab = tab;
@ -51,6 +61,11 @@ add_task(async function() {
1,
"Related tab (referrer) inherits current tab's usercontextid"
);
is(
relatedTab.linkedBrowser.contentPrincipal.userContextId,
1,
"Related tab's browser (referrer) actually inherits the current tab's usercontextid"
);
BrowserTestUtils.removeTab(relatedTab);
gBrowser.selectedTab = tab;
@ -68,6 +83,11 @@ add_task(async function() {
2,
"Related tab (referrer) with overridden usercontextid"
);
is(
relatedTab.linkedBrowser.contentPrincipal.userContextId,
2,
"Related tab's browser (referrer) actually gets overridden usercontextid"
);
BrowserTestUtils.removeTab(relatedTab);
BrowserTestUtils.removeTab(tab);

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

@ -377,6 +377,8 @@ CustomizeMode.prototype = {
this._wrapToolbarItemSync(CustomizableUI.AREA_TABSTRIP);
this.document.documentElement.setAttribute("customizing", true);
let customizableToolbars = document.querySelectorAll(
"toolbar[customizable=true]:not([autohide=true]):not([collapsed=true])"
);
@ -386,8 +388,6 @@ CustomizeMode.prototype = {
this._updateOverflowPanelArrowOffset();
await this._doTransition(true);
// Let everybody in this window know that we're about to customize.
CustomizableUI.dispatchToolboxEvent("customizationstarting", {}, window);
@ -489,15 +489,17 @@ CustomizeMode.prototype = {
(async () => {
await this.depopulatePalette();
await this._doTransition(false);
// We need to set this._customizing to false and remove the `customizing`
// attribute before removing the tab or else
// XULBrowserWindow.onLocationChange might think that we're still in
// customization mode and need to exit it for a second time.
this._customizing = false;
this.document.documentElement.removeAttribute("customizing");
if (this.browser.selectedTab == gTab) {
if (gTab.linkedBrowser.currentURI.spec == "about:blank") {
closeGlobalTab();
} else {
unregisterGlobalTab();
}
closeGlobalTab();
}
let customizer = document.getElementById("customization-container");
let browser = document.getElementById("browser");
customizer.hidden = true;
@ -525,11 +527,6 @@ CustomizeMode.prototype = {
let panelContextMenu = document.getElementById(kPanelItemContextMenu);
this._previousPanelContextMenuParent.appendChild(panelContextMenu);
// We need to set this._customizing to false before removing the tab
// or the TabSelect event handler will think that we are exiting
// customization mode for a second time.
this._customizing = false;
let customizableToolbars = document.querySelectorAll(
"toolbar[customizable=true]:not([autohide=true])"
);
@ -555,40 +552,6 @@ CustomizeMode.prototype = {
});
},
/**
* The customize mode transition has 4 phases when entering:
* 1) Pre-customization mode
* This is the starting phase of the browser.
* 2) LWT swapping
* This is where we swap some of the lightweight theme styles in order
* to make them work in customize mode. We set/unset a customization-
* lwtheme attribute iff we're using a lightweight theme.
* 3) customize-entering
* This phase is a transition, optimized for smoothness.
* 4) customize-entered
* After the transition completes, this phase draws all of the
* expensive detail that isn't necessary during the second phase.
*
* Exiting customization mode has a similar set of phases, but in reverse
* order - customize-entered, customize-exiting, remove LWT swapping,
* pre-customization mode.
*
* When in the customize-entering, customize-entered, or customize-exiting
* phases, there is a "customizing" attribute set on the main-window to simplify
* excluding certain styles while in any phase of customize mode.
*/
_doTransition(aEntering) {
let docEl = this.document.documentElement;
if (aEntering) {
docEl.setAttribute("customizing", true);
docEl.setAttribute("customize-entered", true);
} else {
docEl.removeAttribute("customizing");
docEl.removeAttribute("customize-entered");
}
return Promise.resolve();
},
/**
* The overflow panel in customize mode should have its arrow pointing
* at the overflow button. In order to do this correctly, we pass the

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

@ -245,37 +245,24 @@ function endCustomizing(aWindow = window) {
if (aWindow.document.documentElement.getAttribute("customizing") != "true") {
return true;
}
return new Promise(resolve => {
function onCustomizationEnds() {
aWindow.gNavToolbox.removeEventListener(
"aftercustomization",
onCustomizationEnds
);
resolve();
}
aWindow.gNavToolbox.addEventListener(
"aftercustomization",
onCustomizationEnds
);
aWindow.gCustomizeMode.exit();
});
let afterCustomizationPromise = BrowserTestUtils.waitForEvent(
aWindow.gNavToolbox,
"aftercustomization"
);
aWindow.gCustomizeMode.exit();
return afterCustomizationPromise;
}
function startCustomizing(aWindow = window) {
if (aWindow.document.documentElement.getAttribute("customizing") == "true") {
return null;
}
return new Promise(resolve => {
function onCustomizing() {
aWindow.gNavToolbox.removeEventListener(
"customizationready",
onCustomizing
);
resolve();
}
aWindow.gNavToolbox.addEventListener("customizationready", onCustomizing);
aWindow.gCustomizeMode.enter();
});
let customizationReadyPromise = BrowserTestUtils.waitForEvent(
aWindow.gNavToolbox,
"customizationready"
);
aWindow.gCustomizeMode.enter();
return customizationReadyPromise;
}
function promiseObserverNotified(aTopic) {

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

@ -110,11 +110,11 @@ Event Value
``topsites``. To know whether the user actually picked a top site, check
check that ``numChars`` == 0. If ``numChars`` > 0, the user initially opened
top sites, but then they started typing and confirmed a different result.
``returned``. The user abandoned a search, for example by switching to
- ``returned``: The user abandoned a search, for example by switching to
another tab/window, or focusing something else, then came back to it
and continued. We consider a search continued if the user kept at least the
first char of the original search string.
``restarted``. The user abandoned a search, for example by switching to
- ``restarted``: The user abandoned a search, for example by switching to
another tab/window, or focusing something else, then came back to it,
cleared it and then typed a new string.

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

@ -639,7 +639,9 @@ const tests = [
async function() {
info("Retained result: type, blur, focus, confirm.");
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update1", true]],
});
await promiseAutocompleteResultPopup("search", window, true);
await UrlbarTestUtils.promisePopupClose(window, () => {
gURLBar.blur();
@ -651,6 +653,7 @@ const tests = [
let promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
EventUtils.synthesizeKey("VK_RETURN");
await promise;
await SpecialPowers.popPrefEnv();
return [
{
category: "urlbar",
@ -700,7 +703,9 @@ const tests = [
async function() {
info("Retained result: type, blur, focus, backspace, type, confirm.");
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update1", true]],
});
await promiseAutocompleteResultPopup("search", window, true);
await UrlbarTestUtils.promisePopupClose(window, () => {
gURLBar.blur();
@ -715,6 +720,7 @@ const tests = [
let promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
EventUtils.synthesizeKey("VK_RETURN");
await promise;
await SpecialPowers.popPrefEnv();
return [
{
category: "urlbar",
@ -743,7 +749,9 @@ const tests = [
async function() {
info("Retained result: type, blur, focus, type (overwrite), confirm.");
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.update1", true]],
});
await promiseAutocompleteResultPopup("search", window, true);
await UrlbarTestUtils.promisePopupClose(window, () => {
gURLBar.blur();
@ -756,6 +764,7 @@ const tests = [
let promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
EventUtils.synthesizeKey("VK_RETURN");
await promise;
await SpecialPowers.popPrefEnv();
return [
{
category: "urlbar",

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

@ -1,6 +1,7 @@
TOOLTOOL_DIR=${topsrcdir}
export MAKECAB=$TOOLTOOL_DIR/makecab.exe
export LLVM_CONFIG="${MOZ_FETCHES_DIR}/clang/bin/llvm-config"
export DUMP_SYMS="${MOZ_FETCHES_DIR}/dump_syms/dump_syms.exe"
RUSTC="${MOZ_FETCHES_DIR}/rustc/bin/rustc"
CARGO="${MOZ_FETCHES_DIR}/rustc/bin/cargo"

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

@ -126,7 +126,7 @@
/* Draw the bottom border of the tabs toolbar when it's not using
-moz-appearance: toolbar. */
:root:-moz-any([sizemode="fullscreen"],[customize-entered]) #nav-bar:not([tabs-hidden="true"]),
:root:-moz-any([sizemode="fullscreen"],[customizing]) #nav-bar:not([tabs-hidden="true"]),
:root:not([tabsintitlebar]) #nav-bar:not([tabs-hidden="true"]),
#nav-bar:not([tabs-hidden="true"]):-moz-lwtheme {
box-shadow: 0 calc(-1 * var(--tabs-navbar-shadow-size)) 0 var(--tabs-border-color);

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

@ -226,7 +226,7 @@
@keyframes urlbar-grow {
0% {
transform: scaleX(.98) scaleY(.9);
transform: scaleX(.99) scaleY(.95);
}
100% {
transform: scale(1.0);

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

@ -714,6 +714,7 @@ def toolchain_search_path_for(host_or_target):
os.path.join(mozbuild_state_path, *rest) for rest in (
['clang', 'bin'],
['cbindgen'],
['dump_syms'],
['nasm'],
['lucetc'],
)]

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

@ -19,6 +19,7 @@ unset RUSTDOC
unset RUSTFMT
unset CBINDGEN
unset MAKECAB
unset DUMP_SYMS
unset TOOLCHAIN_PREFIX
unset BINDGEN_CFLAGS
unset LLVM_CONFIG

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

@ -4,6 +4,7 @@
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
export MAKECAB=$TOOLTOOL_DIR/makecab.exe
export DUMP_SYMS="${MOZ_FETCHES_DIR}/dump_syms/dump_syms.exe"
if [ -z "$USE_ARTIFACT" ]; then
if [ -n "$TASKCLUSTER_PGO_PROFILE_USE" ]; then

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

@ -419,14 +419,8 @@ function focusTab(tab) {
* Create an iframe that can be used to load DevTools via about:devtools-toolbox.
*/
function createDevToolsFrame(doc, className) {
let frame;
if (Services.prefs.getBoolPref("devtools.toolbox.content-frame", false)) {
frame = doc.createXULElement("browser");
frame.setAttribute("type", "content");
} else {
frame = doc.createXULElement("iframe");
}
const frame = doc.createXULElement("browser");
frame.setAttribute("type", "content");
frame.flex = 1; // Required to be able to shrink when the window shrinks
frame.className = className;
frame.tooltip = "aHTMLTooltip";

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

@ -516,7 +516,7 @@ html #webconsole-notificationbox {
}
.eager-evaluation-result .objectBox {
height: 15px;
height: 18px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

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

@ -238,7 +238,7 @@ function terminalInputChanged(expression) {
let mapped;
({ expression, mapped } = await getMappedExpression(hud, expression));
const { frameActor, webConsoleFront } = webConsoleUI.getFrameActor();
const { frameActor, webConsoleFront } = await webConsoleUI.getFrameActor();
const response = await client.evaluateJSAsync(expression, {
frameActor,

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

@ -75,6 +75,7 @@ skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1
[browser_jsterm_ctrl_key_nav.js]
skip-if = os != 'mac' # The tested ctrl+key shortcuts are OSX only
[browser_jsterm_document_no_xray.js]
[browser_jsterm_eager_evaluation_in_debugger_stackframe.js]
[browser_jsterm_eager_evaluation.js]
[browser_jsterm_editor.js]
[browser_jsterm_editor_disabled_history_nav_with_keyboard.js]

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

@ -0,0 +1,54 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Test that eager evaluation works as expected when paused in the debugger.
const TEST_URI = `data:text/html;charset=utf-8,
<script>
var x = "global";
function pauseInDebugger(param) {
let x = "local";
debugger;
}
</script>
`;
const EAGER_EVALUATION_PREF = "devtools.webconsole.input.eagerEvaluation";
add_task(async function() {
await pushPref(EAGER_EVALUATION_PREF, true);
const hud = await openNewTabAndConsole(TEST_URI);
const target = await TargetFactory.forTab(gBrowser.selectedTab);
const toolbox = gDevTools.getToolbox(target);
setInputValue(hud, "x");
await waitForEagerEvaluationResult(hud, `"global"`);
info("Open Debugger");
await openDebugger();
const dbg = createDebuggerContext(toolbox);
info("Pause in Debugger");
SpecialPowers.spawn(gBrowser.selectedBrowser, [], function() {
content.wrappedJSObject.pauseInDebugger("myParam");
});
await pauseDebugger(dbg);
info("Opening Console");
await toolbox.selectTool("webconsole");
info("Check that the parameter is eagerly evaluated as expected");
setInputValue(hud, "param");
await waitForEagerEvaluationResult(hud, `"myParam"`);
setInputValue(hud, "x");
await waitForEagerEvaluationResult(hud, `"local"`);
await resume(dbg);
});

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

@ -511,81 +511,6 @@ function writeFile(fileName, content) {
}
}
function connectPipeTracing() {
return new TracingTransport(DebuggerServer.connectPipe());
}
function TracingTransport(childTransport) {
this.hooks = null;
this.child = childTransport;
this.child.hooks = this;
this.expectations = [];
this.packets = [];
this.checkIndex = 0;
}
TracingTransport.prototype = {
// Remove actor names
normalize: function(packet) {
return JSON.parse(
JSON.stringify(packet, (key, value) => {
if (key === "to" || key === "from" || key === "actor") {
return "<actorid>";
}
return value;
})
);
},
send: function(packet) {
this.packets.push({
type: "sent",
packet: this.normalize(packet),
});
return this.child.send(packet);
},
close: function() {
return this.child.close();
},
ready: function() {
return this.child.ready();
},
onPacket: function(packet) {
this.packets.push({
type: "received",
packet: this.normalize(packet),
});
this.hooks.onPacket(packet);
},
onClosed: function() {
this.hooks.onClosed();
},
expectSend: function(expected) {
const packet = this.packets[this.checkIndex++];
Assert.equal(packet.type, "sent");
deepEqual(packet.packet, this.normalize(expected));
},
expectReceive: function(expected) {
const packet = this.packets[this.checkIndex++];
Assert.equal(packet.type, "received");
deepEqual(packet.packet, this.normalize(expected));
},
// Write your tests, call dumpLog at the end, inspect the output,
// then sprinkle the calls through the right places in your test.
dumpLog: function() {
for (const entry of this.packets) {
if (entry.type === "sent") {
dumpn("trace.expectSend(" + entry.packet + ");");
} else {
dumpn("trace.expectReceive(" + entry.packet + ");");
}
}
},
};
function StubTransport() {}
StubTransport.prototype.ready = function() {};
StubTransport.prototype.send = function() {};

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

@ -1,671 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-disable max-nested-callbacks */
"use strict";
/**
* Test simple requests using the protocol helpers.
*/
var protocol = require("devtools/shared/protocol");
var { types, Arg, RetVal } = protocol;
var EventEmitter = require("devtools/shared/event-emitter");
function simpleHello() {
return {
from: "root",
applicationType: "xpcshell-tests",
traits: [],
};
}
// Predeclaring the actor type so that it can be used in the
// implementation of the child actor.
types.addActorType("childActor");
const childSpec = protocol.generateActorSpec({
typeName: "childActor",
events: {
event1: {
a: Arg(0),
b: Arg(1),
c: Arg(2),
},
event2: {
a: Arg(0),
b: Arg(1),
c: Arg(2),
},
"named-event": {
type: "namedEvent",
a: Arg(0),
b: Arg(1),
c: Arg(2),
},
"object-event": {
type: "objectEvent",
detail: Arg(0, "childActor#actorid"),
},
"array-object-event": {
type: "arrayObjectEvent",
detail: Arg(0, "array:childActor#actorid"),
},
},
methods: {
echo: {
request: { str: Arg(0) },
response: { str: RetVal("string") },
},
getDetail1: {
response: {
child: RetVal("childActor#actorid"),
},
},
getDetail2: {
response: {
child: RetVal("childActor#actorid"),
},
},
getIDDetail: {
response: {
idDetail: RetVal("childActor#actorid"),
},
},
getIntArray: {
request: { inputArray: Arg(0, "array:number") },
response: RetVal("array:number"),
},
getSibling: {
request: { id: Arg(0) },
response: { sibling: RetVal("childActor") },
},
emitEvents: {
response: { value: RetVal("string") },
},
release: {
release: true,
},
},
});
var ChildActor = protocol.ActorClassWithSpec(childSpec, {
// Actors returned by this actor should be owned by the root actor.
marshallPool: function() {
return this.parent();
},
toString: function() {
return "[ChildActor " + this.childID + "]";
},
initialize: function(conn, id) {
protocol.Actor.prototype.initialize.call(this, conn);
this.childID = id;
},
destroy: function() {
protocol.Actor.prototype.destroy.call(this);
this.destroyed = true;
},
form: function() {
return {
actor: this.actorID,
childID: this.childID,
};
},
echo: function(str) {
return str;
},
getDetail1: function() {
return this;
},
getDetail2: function() {
return this;
},
getIDDetail: function() {
return this;
},
getIntArray: function(inputArray) {
// Test that protocol.js converts an iterator to an array.
const f = function*() {
for (const i of inputArray) {
yield 2 * i;
}
};
return f();
},
getSibling: function(id) {
return this.parent().getChild(id);
},
emitEvents: function() {
EventEmitter.emit(this, "event1", 1, 2, 3);
EventEmitter.emit(this, "event2", 4, 5, 6);
EventEmitter.emit(this, "named-event", 1, 2, 3);
EventEmitter.emit(this, "object-event", this);
EventEmitter.emit(this, "array-object-event", [this]);
return "correct response";
},
release: function() {},
});
class ChildFront extends protocol.FrontClassWithSpec(childSpec) {
constructor(client) {
super(client);
this.before("event1", this.onEvent1.bind(this));
this.before("event2", this.onEvent2a.bind(this));
this.on("event2", this.onEvent2b.bind(this));
}
destroy() {
this.destroyed = true;
super.destroy();
}
marshallPool() {
return this.parent();
}
toString() {
return "[child front " + this.childID + "]";
}
form(form) {
this.childID = form.childID;
}
onEvent1(a, b, c) {
this.event1arg3 = c;
}
onEvent2a(a, b, c) {
return Promise.resolve().then(() => {
this.event2arg3 = c;
});
}
onEvent2b(a, b, c) {
this.event2arg2 = b;
}
}
protocol.registerFront(ChildFront);
types.addDictType("manyChildrenDict", {
child5: "childActor",
more: "array:childActor",
});
types.addLifetime("temp", "_temporaryHolder");
const rootSpec = protocol.generateActorSpec({
typeName: "root",
methods: {
getChild: {
request: { str: Arg(0) },
response: { actor: RetVal("childActor") },
},
getChildren: {
request: { ids: Arg(0, "array:string") },
response: { children: RetVal("array:childActor") },
},
getChildren2: {
request: { ids: Arg(0, "array:childActor") },
response: { children: RetVal("array:childActor") },
},
getManyChildren: {
response: RetVal("manyChildrenDict"),
},
getTemporaryChild: {
request: { id: Arg(0) },
response: { child: RetVal("temp:childActor") },
},
clearTemporaryChildren: {},
},
});
var rootActor = null;
var RootActor = protocol.ActorClassWithSpec(rootSpec, {
toString: function() {
return "[root actor]";
},
initialize: function(conn) {
rootActor = this;
this.actorID = "root";
this._children = {};
protocol.Actor.prototype.initialize.call(this, conn);
},
sayHello: simpleHello,
getChild: function(id) {
if (id in this._children) {
return this._children[id];
}
const child = new ChildActor(this.conn, id);
this._children[id] = child;
return child;
},
getChildren: function(ids) {
return ids.map(id => this.getChild(id));
},
getChildren2: function(ids) {
const f = function*() {
for (const c of ids) {
yield c;
}
};
return f();
},
getManyChildren: function() {
return {
// note that this isn't in the specialization array.
foo: "bar",
child5: this.getChild("child5"),
more: [this.getChild("child6"), this.getChild("child7")],
};
},
// This should remind you of a pause actor.
getTemporaryChild: function(id) {
if (!this._temporaryHolder) {
this._temporaryHolder = new protocol.Actor(this.conn);
this.manage(this._temporaryHolder);
}
return new ChildActor(this.conn, id);
},
clearTemporaryChildren: function(id) {
if (!this._temporaryHolder) {
return;
}
this._temporaryHolder.destroy();
delete this._temporaryHolder;
},
});
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
constructor(client) {
super(client);
this.actorID = "root";
// Root actor owns itself.
this.manage(this);
}
toString() {
return "[root front]";
}
getTemporaryChild(id) {
if (!this._temporaryHolder) {
this._temporaryHolder = new protocol.Front(this.conn);
this._temporaryHolder.actorID = this.actorID + "_temp";
this.manage(this._temporaryHolder);
}
return super.getTemporaryChild(id);
}
clearTemporaryChildren() {
if (!this._temporaryHolder) {
return Promise.resolve(undefined);
}
this._temporaryHolder.destroy();
delete this._temporaryHolder;
return super.clearTemporaryChildren();
}
}
function run_test() {
DebuggerServer.createRootActor = conn => {
return RootActor(conn);
};
DebuggerServer.init();
const trace = connectPipeTracing();
const client = new DebuggerClient(trace);
client.connect().then(([applicationType, traits]) => {
trace.expectReceive({
from: "<actorid>",
applicationType: "xpcshell-tests",
traits: [],
});
Assert.equal(applicationType, "xpcshell-tests");
const rootFront = new RootFront(client);
let childFront = null;
const expectRootChildren = size => {
Assert.equal(rootActor._poolMap.size, size);
Assert.equal(rootFront._poolMap.size, size + 1);
if (childFront) {
Assert.equal(childFront._poolMap.size, 0);
}
};
rootFront
.getChild("child1")
.then(ret => {
trace.expectSend({ type: "getChild", str: "child1", to: "<actorid>" });
trace.expectReceive({ actor: "<actorid>", from: "<actorid>" });
childFront = ret;
Assert.ok(childFront instanceof ChildFront);
Assert.equal(childFront.childID, "child1");
expectRootChildren(1);
})
.then(() => {
// Request the child again, make sure the same is returned.
return rootFront.getChild("child1");
})
.then(ret => {
trace.expectSend({ type: "getChild", str: "child1", to: "<actorid>" });
trace.expectReceive({ actor: "<actorid>", from: "<actorid>" });
expectRootChildren(1);
Assert.ok(ret === childFront);
})
.then(() => {
return childFront.echo("hello");
})
.then(ret => {
trace.expectSend({ type: "echo", str: "hello", to: "<actorid>" });
trace.expectReceive({ str: "hello", from: "<actorid>" });
Assert.equal(ret, "hello");
})
.then(() => {
return childFront.getDetail1();
})
.then(ret => {
trace.expectSend({ type: "getDetail1", to: "<actorid>" });
trace.expectReceive({ child: childFront.actorID, from: "<actorid>" });
Assert.ok(ret === childFront);
})
.then(() => {
return childFront.getDetail2();
})
.then(ret => {
trace.expectSend({ type: "getDetail2", to: "<actorid>" });
trace.expectReceive({ child: childFront.actorID, from: "<actorid>" });
Assert.ok(ret === childFront);
})
.then(() => {
return childFront.getIDDetail();
})
.then(ret => {
trace.expectSend({ type: "getIDDetail", to: "<actorid>" });
trace.expectReceive({
idDetail: childFront.actorID,
from: "<actorid>",
});
Assert.ok(ret === childFront);
})
.then(() => {
return childFront.getSibling("siblingID");
})
.then(ret => {
trace.expectSend({
type: "getSibling",
id: "siblingID",
to: "<actorid>",
});
trace.expectReceive({
sibling: { actor: "<actorid>", childID: "siblingID" },
from: "<actorid>",
});
expectRootChildren(2);
})
.then(ret => {
return rootFront.getTemporaryChild("temp1").then(temp1 => {
trace.expectSend({
type: "getTemporaryChild",
id: "temp1",
to: "<actorid>",
});
trace.expectReceive({
child: { actor: "<actorid>", childID: "temp1" },
from: "<actorid>",
});
// At this point we expect two direct children, plus the temporary holder
// which should hold 1 itself.
Assert.equal(rootActor._temporaryHolder.__poolMap.size, 1);
Assert.equal(rootFront._temporaryHolder.__poolMap.size, 1);
expectRootChildren(3);
return rootFront.getTemporaryChild("temp2").then(temp2 => {
trace.expectSend({
type: "getTemporaryChild",
id: "temp2",
to: "<actorid>",
});
trace.expectReceive({
child: { actor: "<actorid>", childID: "temp2" },
from: "<actorid>",
});
// Same amount of direct children, and an extra in the temporary holder.
expectRootChildren(3);
Assert.equal(rootActor._temporaryHolder.__poolMap.size, 2);
Assert.equal(rootFront._temporaryHolder.__poolMap.size, 2);
// Get the children of the temporary holder...
const checkActors = rootActor._temporaryHolder.__poolMap.values();
// Now release the temporary holders and expect them to drop again.
return rootFront.clearTemporaryChildren().then(() => {
trace.expectSend({
type: "clearTemporaryChildren",
to: "<actorid>",
});
trace.expectReceive({ from: "<actorid>" });
expectRootChildren(2);
Assert.ok(!rootActor._temporaryHolder);
Assert.ok(!rootFront._temporaryHolder);
for (const checkActor of checkActors) {
Assert.ok(checkActor.destroyed);
Assert.ok(checkActor.destroyed);
}
});
});
});
})
.then(ret => {
return rootFront.getChildren(["child1", "child2"]);
})
.then(ret => {
trace.expectSend({
type: "getChildren",
ids: ["child1", "child2"],
to: "<actorid>",
});
trace.expectReceive({
children: [
{ actor: "<actorid>", childID: "child1" },
{ actor: "<actorid>", childID: "child2" },
],
from: "<actorid>",
});
expectRootChildren(3);
Assert.ok(ret[0] === childFront);
Assert.ok(ret[1] !== childFront);
Assert.ok(ret[1] instanceof ChildFront);
// On both children, listen to events. We're only
// going to trigger events on the first child, so an event
// triggered on the second should cause immediate failures.
const set = new Set([
"event1",
"event2",
"named-event",
"object-event",
"array-object-event",
]);
childFront.on("event1", (a, b, c) => {
Assert.equal(a, 1);
Assert.equal(b, 2);
Assert.equal(c, 3);
// Verify that the pre-event handler was called.
Assert.equal(childFront.event1arg3, 3);
set.delete("event1");
});
childFront.on("event2", (a, b, c) => {
Assert.equal(a, 4);
Assert.equal(b, 5);
Assert.equal(c, 6);
// Verify that the async pre-event handler was called,
// setting the property before this handler was called.
Assert.equal(childFront.event2arg3, 6);
// And check that the sync preEvent with the same name is also
// executed
Assert.equal(childFront.event2arg2, 5);
set.delete("event2");
});
childFront.on("named-event", (a, b, c) => {
Assert.equal(a, 1);
Assert.equal(b, 2);
Assert.equal(c, 3);
set.delete("named-event");
});
childFront.on("object-event", obj => {
Assert.ok(obj === childFront);
set.delete("object-event");
});
childFront.on("array-object-event", array => {
Assert.ok(array[0] === childFront);
set.delete("array-object-event");
});
const fail = function() {
do_throw("Unexpected event");
};
ret[1].on("event1", fail);
ret[1].on("event2", fail);
ret[1].on("named-event", fail);
ret[1].on("object-event", fail);
ret[1].on("array-object-event", fail);
return childFront.emitEvents().then(() => {
trace.expectSend({ type: "emitEvents", to: "<actorid>" });
trace.expectReceive({
type: "event1",
a: 1,
b: 2,
c: 3,
from: "<actorid>",
});
trace.expectReceive({
type: "event2",
a: 4,
b: 5,
c: 6,
from: "<actorid>",
});
trace.expectReceive({
type: "namedEvent",
a: 1,
b: 2,
c: 3,
from: "<actorid>",
});
trace.expectReceive({
type: "objectEvent",
detail: childFront.actorID,
from: "<actorid>",
});
trace.expectReceive({
type: "arrayObjectEvent",
detail: [childFront.actorID],
from: "<actorid>",
});
trace.expectReceive({ value: "correct response", from: "<actorid>" });
Assert.equal(set.size, 0);
});
})
.then(ret => {
return rootFront.getManyChildren();
})
.then(ret => {
trace.expectSend({ type: "getManyChildren", to: "<actorid>" });
trace.expectReceive({
foo: "bar",
child5: { actor: "<actorid>", childID: "child5" },
more: [
{ actor: "<actorid>", childID: "child6" },
{ actor: "<actorid>", childID: "child7" },
],
from: "<actorid>",
});
// Check all the crazy stuff we did in getManyChildren
Assert.equal(ret.foo, "bar");
Assert.equal(ret.child5.childID, "child5");
Assert.equal(ret.more[0].childID, "child6");
Assert.equal(ret.more[1].childID, "child7");
})
.then(() => {
// Test accepting a generator.
const f = function*() {
for (const i of [1, 2, 3, 4, 5]) {
yield i;
}
};
return childFront.getIntArray(f());
})
.then(ret => {
Assert.equal(ret.length, 5);
const expected = [2, 4, 6, 8, 10];
for (let i = 0; i < 5; ++i) {
Assert.equal(ret[i], expected[i]);
}
})
.then(() => {
return rootFront.getChildren(["child1", "child2"]);
})
.then(ids => {
const f = function*() {
for (const id of ids) {
yield id;
}
};
return rootFront.getChildren2(f());
})
.then(ret => {
Assert.equal(ret.length, 2);
Assert.ok(ret[0] === childFront);
Assert.ok(ret[1] !== childFront);
Assert.ok(ret[1] instanceof ChildFront);
})
.then(() => {
client.close().then(() => {
do_test_finished();
});
})
.catch(err => {
do_report_unexpected_exception(err, "Failure executing test");
});
});
do_test_pending();
}

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

@ -81,14 +81,6 @@ support-files =
[test_nativewrappers.js]
[test_nodelistactor.js]
[test_format_command.js]
[test_protocol_abort.js]
[test_protocol_async.js]
[test_protocol_children.js]
[test_protocol_longstring.js]
[test_protocol_simple.js]
[test_protocol_stack.js]
[test_protocol_unregister.js]
[test_protocol_watchFronts.js]
[test_breakpoint-01.js]
[test_register_actor.js]
[test_breakpoint-02.js]

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

@ -18,3 +18,5 @@ DevToolsModules(
'types.js',
'utils.js',
)
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']

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

@ -0,0 +1,6 @@
"use strict";
module.exports = {
// Extend from the common devtools xpcshell eslintrc config.
"extends": "../../../../.eslintrc.xpcshell.js"
};

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

@ -0,0 +1,94 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const Services = require("Services");
const { DebuggerServer } = require("devtools/server/debugger-server");
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
const defer = require("devtools/shared/defer");
function dumpn(msg) {
dump("DBG-TEST: " + msg + "\n");
}
function connectPipeTracing() {
return new TracingTransport(DebuggerServer.connectPipe());
}
/**
* Mock the `Transport` class in order to intercept all the packet
* getting in and out and then being able to assert them and dump them.
*/
function TracingTransport(childTransport) {
this.hooks = null;
this.child = childTransport;
this.child.hooks = this;
this.expectations = [];
this.packets = [];
this.checkIndex = 0;
}
TracingTransport.prototype = {
// Remove actor names
normalize: function(packet) {
return JSON.parse(
JSON.stringify(packet, (key, value) => {
if (key === "to" || key === "from" || key === "actor") {
return "<actorid>";
}
return value;
})
);
},
send: function(packet) {
this.packets.push({
type: "sent",
packet: this.normalize(packet),
});
return this.child.send(packet);
},
close: function() {
return this.child.close();
},
ready: function() {
return this.child.ready();
},
onPacket: function(packet) {
this.packets.push({
type: "received",
packet: this.normalize(packet),
});
this.hooks.onPacket(packet);
},
onClosed: function() {
this.hooks.onClosed();
},
expectSend: function(expected) {
const packet = this.packets[this.checkIndex++];
Assert.equal(packet.type, "sent");
deepEqual(packet.packet, this.normalize(expected));
},
expectReceive: function(expected) {
const packet = this.packets[this.checkIndex++];
Assert.equal(packet.type, "received");
deepEqual(packet.packet, this.normalize(expected));
},
// Write your tests, call dumpLog at the end, inspect the output,
// then sprinkle the calls through the right places in your test.
dumpLog: function() {
for (const entry of this.packets) {
if (entry.type === "sent") {
dumpn("trace.expectSend(" + entry.packet + ");");
} else {
dumpn("trace.expectReceive(" + entry.packet + ");");
}
}
},
};

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

@ -0,0 +1,714 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-disable max-nested-callbacks */
"use strict";
/**
* Test simple requests using the protocol helpers.
*/
const protocol = require("devtools/shared/protocol");
const { types, Arg, RetVal } = protocol;
function simpleHello() {
return {
from: "root",
applicationType: "xpcshell-tests",
traits: [],
};
}
// Predeclaring the actor type so that it can be used in the
// implementation of the child actor.
types.addActorType("childActor");
types.addActorType("otherChildActor");
types.addPolymorphicType("polytype", ["childActor", "otherChildActor"]);
const childSpec = protocol.generateActorSpec({
typeName: "childActor",
events: {
event1: {
a: Arg(0),
b: Arg(1),
c: Arg(2),
},
event2: {
a: Arg(0),
b: Arg(1),
c: Arg(2),
},
"named-event": {
type: "namedEvent",
a: Arg(0),
b: Arg(1),
c: Arg(2),
},
"object-event": {
type: "objectEvent",
detail: Arg(0, "childActor#actorid"),
},
"array-object-event": {
type: "arrayObjectEvent",
detail: Arg(0, "array:childActor#actorid"),
},
},
methods: {
echo: {
request: { str: Arg(0) },
response: { str: RetVal("string") },
},
getDetail1: {
response: {
child: RetVal("childActor#actorid"),
},
},
getDetail2: {
response: {
child: RetVal("childActor#actorid"),
},
},
getIDDetail: {
response: {
idDetail: RetVal("childActor#actorid"),
},
},
getIntArray: {
request: { inputArray: Arg(0, "array:number") },
response: RetVal("array:number"),
},
getSibling: {
request: { id: Arg(0) },
response: { sibling: RetVal("childActor") },
},
emitEvents: {
response: { value: RetVal("string") },
},
release: {
release: true,
},
},
});
var ChildActor = protocol.ActorClassWithSpec(childSpec, {
// Actors returned by this actor should be owned by the root actor.
marshallPool() {
return this.parent();
},
toString() {
return "[ChildActor " + this.childID + "]";
},
initialize(conn, id) {
protocol.Actor.prototype.initialize.call(this, conn);
this.childID = id;
},
destroy() {
protocol.Actor.prototype.destroy.call(this);
this.destroyed = true;
},
form() {
return {
actor: this.actorID,
childID: this.childID,
};
},
echo(str) {
return str;
},
getDetail1() {
return this;
},
getDetail2() {
return this;
},
getIDDetail() {
return this;
},
getIntArray(inputArray) {
// Test that protocol.js converts an iterator to an array.
const f = function*() {
for (const i of inputArray) {
yield 2 * i;
}
};
return f();
},
getSibling(id) {
return this.parent().getChild(id);
},
emitEvents() {
this.emit("event1", 1, 2, 3);
this.emit("event2", 4, 5, 6);
this.emit("named-event", 1, 2, 3);
this.emit("object-event", this);
this.emit("array-object-event", [this]);
return "correct response";
},
release() {},
});
class ChildFront extends protocol.FrontClassWithSpec(childSpec) {
constructor(client) {
super(client);
this.before("event1", this.onEvent1.bind(this));
this.before("event2", this.onEvent2a.bind(this));
this.on("event2", this.onEvent2b.bind(this));
}
destroy() {
this.destroyed = true;
super.destroy();
}
marshallPool() {
return this.parent();
}
toString() {
return "[child front " + this.childID + "]";
}
form(form) {
this.childID = form.childID;
}
onEvent1(a, b, c) {
this.event1arg3 = c;
}
onEvent2a(a, b, c) {
return Promise.resolve().then(() => {
this.event2arg3 = c;
});
}
onEvent2b(a, b, c) {
this.event2arg2 = b;
}
}
protocol.registerFront(ChildFront);
const otherChildSpec = protocol.generateActorSpec({
typeName: "otherChildActor",
methods: {},
events: {},
});
const OtherChildActor = protocol.ActorClassWithSpec(otherChildSpec, {});
class OtherChildFront extends protocol.FrontClassWithSpec(otherChildSpec) {}
protocol.registerFront(OtherChildFront);
types.addDictType("manyChildrenDict", {
child5: "childActor",
more: "array:childActor",
});
types.addLifetime("temp", "_temporaryHolder");
const rootSpec = protocol.generateActorSpec({
typeName: "root",
methods: {
getChild: {
request: { str: Arg(0) },
response: { actor: RetVal("childActor") },
},
getChildren: {
request: { ids: Arg(0, "array:string") },
response: { children: RetVal("array:childActor") },
},
getChildren2: {
request: { ids: Arg(0, "array:childActor") },
response: { children: RetVal("array:childActor") },
},
getManyChildren: {
response: RetVal("manyChildrenDict"),
},
getTemporaryChild: {
request: { id: Arg(0) },
response: { child: RetVal("temp:childActor") },
},
getPolymorphism: {
request: { id: Arg(0, "number") },
response: { child: RetVal("polytype") },
},
requestPolymorphism: {
request: {
id: Arg(0, "number"),
actor: Arg(1, "polytype"),
},
response: { child: RetVal("polytype") },
},
clearTemporaryChildren: {},
},
});
let rootActor = null;
const RootActor = protocol.ActorClassWithSpec(rootSpec, {
toString() {
return "[root actor]";
},
initialize(conn) {
rootActor = this;
this.actorID = "root";
this._children = {};
protocol.Actor.prototype.initialize.call(this, conn);
},
sayHello: simpleHello,
getChild(id) {
if (id in this._children) {
return this._children[id];
}
const child = new ChildActor(this.conn, id);
this._children[id] = child;
return child;
},
getChildren(ids) {
return ids.map(id => this.getChild(id));
},
getChildren2(ids) {
const f = function*() {
for (const c of ids) {
yield c;
}
};
return f();
},
getManyChildren() {
return {
// note that this isn't in the specialization array.
foo: "bar",
child5: this.getChild("child5"),
more: [this.getChild("child6"), this.getChild("child7")],
};
},
// This should remind you of a pause actor.
getTemporaryChild(id) {
if (!this._temporaryHolder) {
this._temporaryHolder = new protocol.Actor(this.conn);
this.manage(this._temporaryHolder);
}
return new ChildActor(this.conn, id);
},
clearTemporaryChildren(id) {
if (!this._temporaryHolder) {
return;
}
this._temporaryHolder.destroy();
delete this._temporaryHolder;
},
getPolymorphism: function(id) {
if (id == 0) {
return new ChildActor(this.conn, id);
} else if (id == 1) {
return new OtherChildActor(this.conn);
}
throw new Error("Unexpected id");
},
requestPolymorphism: function(id, actor) {
if (id == 0 && actor instanceof ChildActor) {
return actor;
} else if (id == 1 && actor instanceof OtherChildActor) {
return actor;
}
throw new Error("Unexpected id or actor");
},
});
class RootFront extends protocol.FrontClassWithSpec(rootSpec) {
constructor(client) {
super(client);
this.actorID = "root";
// Root actor owns itself.
this.manage(this);
}
toString() {
return "[root front]";
}
getTemporaryChild(id) {
if (!this._temporaryHolder) {
this._temporaryHolder = new protocol.Front(this.conn);
this._temporaryHolder.actorID = this.actorID + "_temp";
this.manage(this._temporaryHolder);
}
return super.getTemporaryChild(id);
}
clearTemporaryChildren() {
if (!this._temporaryHolder) {
return Promise.resolve(undefined);
}
this._temporaryHolder.destroy();
delete this._temporaryHolder;
return super.clearTemporaryChildren();
}
}
let rootFront, childFront;
function expectRootChildren(size) {
Assert.equal(rootActor._poolMap.size, size);
Assert.equal(rootFront._poolMap.size, size + 1);
if (childFront) {
Assert.equal(childFront._poolMap.size, 0);
}
}
add_task(async function() {
DebuggerServer.createRootActor = conn => {
return RootActor(conn);
};
DebuggerServer.init();
const trace = connectPipeTracing();
const client = new DebuggerClient(trace);
const [applicationType] = await client.connect();
trace.expectReceive({
from: "<actorid>",
applicationType: "xpcshell-tests",
traits: [],
});
Assert.equal(applicationType, "xpcshell-tests");
rootFront = new RootFront(client);
await testSimpleChildren(trace);
await testDetail(trace);
await testSibling(trace);
await testTemporary(trace);
await testEvents(trace);
await testManyChildren(trace);
await testGenerator(trace);
await testPolymorphism(trace);
await client.close();
});
async function testSimpleChildren(trace) {
childFront = await rootFront.getChild("child1");
trace.expectSend({ type: "getChild", str: "child1", to: "<actorid>" });
trace.expectReceive({ actor: "<actorid>", from: "<actorid>" });
Assert.ok(childFront instanceof ChildFront);
Assert.equal(childFront.childID, "child1");
expectRootChildren(1);
// Request the child again, make sure the same is returned.
let ret = await rootFront.getChild("child1");
trace.expectSend({ type: "getChild", str: "child1", to: "<actorid>" });
trace.expectReceive({ actor: "<actorid>", from: "<actorid>" });
expectRootChildren(1);
Assert.ok(ret === childFront);
ret = await childFront.echo("hello");
trace.expectSend({ type: "echo", str: "hello", to: "<actorid>" });
trace.expectReceive({ str: "hello", from: "<actorid>" });
Assert.equal(ret, "hello");
}
async function testDetail(trace) {
let ret = await childFront.getDetail1();
trace.expectSend({ type: "getDetail1", to: "<actorid>" });
trace.expectReceive({ child: childFront.actorID, from: "<actorid>" });
Assert.ok(ret === childFront);
ret = await childFront.getDetail2();
trace.expectSend({ type: "getDetail2", to: "<actorid>" });
trace.expectReceive({ child: childFront.actorID, from: "<actorid>" });
Assert.ok(ret === childFront);
ret = await childFront.getIDDetail();
trace.expectSend({ type: "getIDDetail", to: "<actorid>" });
trace.expectReceive({
idDetail: childFront.actorID,
from: "<actorid>",
});
Assert.ok(ret === childFront);
}
async function testSibling(trace) {
await childFront.getSibling("siblingID");
trace.expectSend({
type: "getSibling",
id: "siblingID",
to: "<actorid>",
});
trace.expectReceive({
sibling: { actor: "<actorid>", childID: "siblingID" },
from: "<actorid>",
});
expectRootChildren(2);
}
async function testTemporary(trace) {
await rootFront.getTemporaryChild("temp1");
trace.expectSend({
type: "getTemporaryChild",
id: "temp1",
to: "<actorid>",
});
trace.expectReceive({
child: { actor: "<actorid>", childID: "temp1" },
from: "<actorid>",
});
// At this point we expect two direct children, plus the temporary holder
// which should hold 1 itself.
Assert.equal(rootActor._temporaryHolder.__poolMap.size, 1);
Assert.equal(rootFront._temporaryHolder.__poolMap.size, 1);
expectRootChildren(3);
await rootFront.getTemporaryChild("temp2");
trace.expectSend({
type: "getTemporaryChild",
id: "temp2",
to: "<actorid>",
});
trace.expectReceive({
child: { actor: "<actorid>", childID: "temp2" },
from: "<actorid>",
});
// Same amount of direct children, and an extra in the temporary holder.
expectRootChildren(3);
Assert.equal(rootActor._temporaryHolder.__poolMap.size, 2);
Assert.equal(rootFront._temporaryHolder.__poolMap.size, 2);
// Get the children of the temporary holder...
const checkActors = rootActor._temporaryHolder.__poolMap.values();
// Now release the temporary holders and expect them to drop again.
await rootFront.clearTemporaryChildren();
trace.expectSend({
type: "clearTemporaryChildren",
to: "<actorid>",
});
trace.expectReceive({ from: "<actorid>" });
expectRootChildren(2);
Assert.ok(!rootActor._temporaryHolder);
Assert.ok(!rootFront._temporaryHolder);
for (const checkActor of checkActors) {
Assert.ok(checkActor.destroyed);
Assert.ok(checkActor.destroyed);
}
}
async function testEvents(trace) {
const ret = await rootFront.getChildren(["child1", "child2"]);
trace.expectSend({
type: "getChildren",
ids: ["child1", "child2"],
to: "<actorid>",
});
trace.expectReceive({
children: [
{ actor: "<actorid>", childID: "child1" },
{ actor: "<actorid>", childID: "child2" },
],
from: "<actorid>",
});
expectRootChildren(3);
Assert.ok(ret[0] === childFront);
Assert.ok(ret[1] !== childFront);
Assert.ok(ret[1] instanceof ChildFront);
// On both children, listen to events. We're only
// going to trigger events on the first child, so an event
// triggered on the second should cause immediate failures.
const set = new Set([
"event1",
"event2",
"named-event",
"object-event",
"array-object-event",
]);
childFront.on("event1", (a, b, c) => {
Assert.equal(a, 1);
Assert.equal(b, 2);
Assert.equal(c, 3);
// Verify that the pre-event handler was called.
Assert.equal(childFront.event1arg3, 3);
set.delete("event1");
});
childFront.on("event2", (a, b, c) => {
Assert.equal(a, 4);
Assert.equal(b, 5);
Assert.equal(c, 6);
// Verify that the async pre-event handler was called,
// setting the property before this handler was called.
Assert.equal(childFront.event2arg3, 6);
// And check that the sync preEvent with the same name is also
// executed
Assert.equal(childFront.event2arg2, 5);
set.delete("event2");
});
childFront.on("named-event", (a, b, c) => {
Assert.equal(a, 1);
Assert.equal(b, 2);
Assert.equal(c, 3);
set.delete("named-event");
});
childFront.on("object-event", obj => {
Assert.ok(obj === childFront);
set.delete("object-event");
});
childFront.on("array-object-event", array => {
Assert.ok(array[0] === childFront);
set.delete("array-object-event");
});
const fail = function() {
do_throw("Unexpected event");
};
ret[1].on("event1", fail);
ret[1].on("event2", fail);
ret[1].on("named-event", fail);
ret[1].on("object-event", fail);
ret[1].on("array-object-event", fail);
await childFront.emitEvents();
trace.expectSend({ type: "emitEvents", to: "<actorid>" });
trace.expectReceive({
type: "event1",
a: 1,
b: 2,
c: 3,
from: "<actorid>",
});
trace.expectReceive({
type: "event2",
a: 4,
b: 5,
c: 6,
from: "<actorid>",
});
trace.expectReceive({
type: "namedEvent",
a: 1,
b: 2,
c: 3,
from: "<actorid>",
});
trace.expectReceive({
type: "objectEvent",
detail: childFront.actorID,
from: "<actorid>",
});
trace.expectReceive({
type: "arrayObjectEvent",
detail: [childFront.actorID],
from: "<actorid>",
});
trace.expectReceive({ value: "correct response", from: "<actorid>" });
Assert.equal(set.size, 0);
}
async function testManyChildren(trace) {
const ret = await rootFront.getManyChildren();
trace.expectSend({ type: "getManyChildren", to: "<actorid>" });
trace.expectReceive({
foo: "bar",
child5: { actor: "<actorid>", childID: "child5" },
more: [
{ actor: "<actorid>", childID: "child6" },
{ actor: "<actorid>", childID: "child7" },
],
from: "<actorid>",
});
// Check all the crazy stuff we did in getManyChildren
Assert.equal(ret.foo, "bar");
Assert.equal(ret.child5.childID, "child5");
Assert.equal(ret.more[0].childID, "child6");
Assert.equal(ret.more[1].childID, "child7");
}
async function testGenerator(trace) {
// Test accepting a generator.
const f = function*() {
for (const i of [1, 2, 3, 4, 5]) {
yield i;
}
};
let ret = await childFront.getIntArray(f());
Assert.equal(ret.length, 5);
const expected = [2, 4, 6, 8, 10];
for (let i = 0; i < 5; ++i) {
Assert.equal(ret[i], expected[i]);
}
const ids = await rootFront.getChildren(["child1", "child2"]);
const f2 = function*() {
for (const id of ids) {
yield id;
}
};
ret = await rootFront.getChildren2(f2());
Assert.equal(ret.length, 2);
Assert.ok(ret[0] === childFront);
Assert.ok(ret[1] !== childFront);
Assert.ok(ret[1] instanceof ChildFront);
}
async function testPolymorphism(trace) {
// Check polymorphic types returned by an actor
const firstChild = await rootFront.getPolymorphism(0);
Assert.ok(firstChild instanceof ChildFront);
// Check polymorphic types passed to a front
const sameFirstChild = await rootFront.requestPolymorphism(0, firstChild);
Assert.ok(sameFirstChild instanceof ChildFront);
Assert.equal(sameFirstChild, firstChild);
// Same with the second possible type
const secondChild = await rootFront.getPolymorphism(1);
Assert.ok(secondChild instanceof OtherChildFront);
const sameSecondChild = await rootFront.requestPolymorphism(1, secondChild);
Assert.ok(sameSecondChild instanceof OtherChildFront);
Assert.equal(sameSecondChild, secondChild);
// Check that any other type is rejected
Assert.throws(() => {
rootFront.requestPolymorphism(0, null);
}, /Was expecting one of these actors 'childActor,otherChildActor' but instead got an empty value/);
Assert.throws(() => {
rootFront.requestPolymorphism(0, 42);
}, /Was expecting one of these actors 'childActor,otherChildActor' but instead got value: '42'/);
Assert.throws(() => {
rootFront.requestPolymorphism(0, rootFront);
}, /Was expecting one of these actors 'childActor,otherChildActor' but instead got an actor of type: 'root'/);
}

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

@ -0,0 +1,65 @@
"use strict";
const { types } = require("devtools/shared/protocol");
function run_test() {
types.addActorType("myActor1");
types.addActorType("myActor2");
types.addActorType("myActor3");
types.addPolymorphicType("ptype1", ["myActor1", "myActor2"]);
const ptype1 = types.getType("ptype1");
Assert.equal(ptype1.name, "ptype1");
Assert.equal(ptype1.category, "polymorphic");
types.addPolymorphicType("ptype2", ["myActor1", "myActor2", "myActor3"]);
const ptype2 = types.getType("ptype2");
Assert.equal(ptype2.name, "ptype2");
Assert.equal(ptype2.category, "polymorphic");
// Polymorphic types only accept actor types
try {
types.addPolymorphicType("ptype", ["myActor1", "myActor4"]);
Assert.ok(false, "getType should fail");
} catch (ex) {
Assert.equal(ex.toString(), "Error: Unknown type: myActor4");
}
try {
types.addPolymorphicType("ptype", ["myActor1", "string"]);
Assert.ok(false, "getType should fail");
} catch (ex) {
Assert.equal(
ex.toString(),
"Error: In polymorphic type 'myActor1,string', the type 'string' isn't an actor"
);
}
try {
types.addPolymorphicType("ptype", ["myActor1", "boolean"]);
Assert.ok(false, "getType should fail");
} catch (ex) {
Assert.equal(
ex.toString(),
"Error: In polymorphic type 'myActor1,boolean', the type 'boolean' isn't an actor"
);
}
// Polymorphic types are not compatible with array or nullables
try {
types.addPolymorphicType("ptype", ["array:myActor1", "myActor2"]);
Assert.ok(false, "addType should fail");
} catch (ex) {
Assert.equal(
ex.toString(),
"Error: In polymorphic type 'array:myActor1,myActor2', the type 'array:myActor1' isn't an actor"
);
}
try {
types.addPolymorphicType("ptype", ["nullable:myActor1", "myActor2"]);
Assert.ok(false, "addType should fail");
} catch (ex) {
Assert.equal(
ex.toString(),
"Error: In polymorphic type 'nullable:myActor1,myActor2', the type 'nullable:myActor1' isn't an actor"
);
}
}

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

@ -0,0 +1,17 @@
[DEFAULT]
tags = devtools
head = head.js
firefox-appdir = browser
skip-if = toolkit == 'android'
support-files =
[test_protocol_abort.js]
[test_protocol_async.js]
[test_protocol_children.js]
[test_protocol_index.js]
[test_protocol_longstring.js]
[test_protocol_simple.js]
[test_protocol_stack.js]
[test_protocol_types.js]
[test_protocol_unregister.js]
[test_protocol_watchFronts.js]

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

@ -370,6 +370,68 @@ types.addActorType = function(name) {
return type;
};
types.addPolymorphicType = function(name, subtypes) {
// Assert that all subtypes are actors, as the marshalling implementation depends on that.
for (const subTypeName of subtypes) {
const subtype = types.getType(subTypeName);
if (subtype.category != "actor") {
throw new Error(
`In polymorphic type '${subtypes.join(
","
)}', the type '${subTypeName}' isn't an actor`
);
}
}
return types.addType(name, {
category: "polymorphic",
read: (value, ctx) => {
// `value` is either a string which is an Actor ID or a form object
// where `actor` is an actor ID
const actorID = typeof value === "string" ? value : value.actor;
if (!actorID) {
throw new Error(
`Was expecting one of these actors '${subtypes}' but instead got value: '${value}'`
);
}
// Extract the typeName out of the actor ID, which should be composed like this
// ${DebuggerServerConnectionPrefix}.${typeName}${Number}
const typeName = actorID.match(/\.([a-zA-Z]+)\d+$/)[1];
if (!subtypes.includes(typeName)) {
throw new Error(
`Was expecting one of these actors '${subtypes}' but instead got an actor of type: '${typeName}'`
);
}
const subtype = types.getType(typeName);
return subtype.read(value, ctx);
},
write: (value, ctx) => {
if (!value) {
throw new Error(
`Was expecting one of these actors '${subtypes}' but instead got an empty value.`
);
}
// value is either an `Actor` or a `Front` and both classes exposes a `typeName`
const typeName = value.typeName;
if (!typeName) {
throw new Error(
`Was expecting one of these actors '${subtypes}' but instead got value: '${value}'. Did you pass a form instead of an Actor?`
);
}
if (!subtypes.includes(typeName)) {
throw new Error(
`Was expecting one of these actors '${subtypes}' but instead got an actor of type: '${typeName}'`
);
}
const subtype = types.getType(typeName);
return subtype.write(value, ctx);
},
});
};
types.addNullableType = function(subtype) {
subtype = types.getType(subtype);
return types.addType("nullable:" + subtype.name, {

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

@ -42,4 +42,3 @@ run-if = nightly_build
[test_stack.js]
[test_defer.js]
[test_executeSoon.js]
[test_protocol_index.js]

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

@ -303,29 +303,6 @@ void BrowsingContext::SetEmbedderElement(Element* aEmbedder) {
// Notify the parent process of the embedding status. We don't need to do
// this when clearing our embedder, as we're being destroyed either way.
if (aEmbedder) {
// If our embedder element is being mutated to a different embedder, and we
// have a parent edge, bad things might be happening!
//
// XXX: This is a workaround to some parent edges not being immutable in the
// parent process. It can be fixed once bug 1539979 has been fixed.
if (mParent && mEmbedderElement && mEmbedderElement != aEmbedder) {
NS_WARNING("Non root content frameLoader swap! This will crash soon!");
MOZ_DIAGNOSTIC_ASSERT(mType == Type::Chrome, "must be chrome");
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess(), "must be in parent");
MOZ_DIAGNOSTIC_ASSERT(!mGroup->IsContextCached(this),
"cannot be in bfcache");
RefPtr<BrowsingContext> kungFuDeathGrip(this);
RefPtr<BrowsingContext> newParent(
aEmbedder->OwnerDoc()->GetBrowsingContext());
mParent->mChildren.RemoveElement(this);
if (newParent) {
newParent->mChildren.AppendElement(this);
}
mParent = newParent;
}
if (nsCOMPtr<nsPIDOMWindowInner> inner =
do_QueryInterface(aEmbedder->GetOwnerGlobal())) {
SetEmbedderInnerWindowId(inner->WindowID());
@ -949,7 +926,7 @@ nsresult BrowsingContext::InternalLoad(BrowsingContext* aAccessor,
// the same as how the tab first opened.
nsCOMPtr<nsPIDOMWindowOuter> domWin = GetDOMWindow();
if (isActive && domWin) {
nsFocusManager::FocusWindow(domWin);
nsFocusManager::FocusWindow(domWin, CallerType::System);
}
// Else we ran out of memory, or were a popup and got blocked,
@ -1023,11 +1000,11 @@ void BrowsingContext::Close(CallerType aCallerType, ErrorResult& aError) {
}
}
void BrowsingContext::Focus(ErrorResult& aError) {
void BrowsingContext::Focus(CallerType aCallerType, ErrorResult& aError) {
if (ContentChild* cc = ContentChild::GetSingleton()) {
cc->SendWindowFocus(this);
cc->SendWindowFocus(this, aCallerType);
} else if (ContentParent* cp = Canonical()->GetContentParent()) {
Unused << cp->SendWindowFocus(this);
Unused << cp->SendWindowFocus(this, aCallerType);
}
}

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

@ -390,7 +390,7 @@ class BrowsingContext : public nsISupports,
ErrorResult& aError);
void Close(CallerType aCallerType, ErrorResult& aError);
bool GetClosed(ErrorResult&) { return mClosed; }
void Focus(ErrorResult& aError);
void Focus(CallerType aCallerType, ErrorResult& aError);
void Blur(ErrorResult& aError);
WindowProxyHolder GetFrames(ErrorResult& aError);
int32_t Length() const { return mChildren.Length(); }

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

@ -190,7 +190,7 @@ nsDSURIContentListener::DoContent(const nsACString& aContentType,
nsCOMPtr<nsPIDOMWindowOuter> domWindow =
mDocShell ? mDocShell->GetWindow() : nullptr;
NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
domWindow->Focus();
domWindow->Focus(mozilla::dom::CallerType::System);
}
return NS_OK;

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

@ -88,7 +88,7 @@ nsresult DOMImplementation::CreateDocument(const nsAString& aNamespaceURI,
rv = NS_NewDOMDocument(getter_AddRefs(doc), aNamespaceURI, aQualifiedName,
aDoctype, mDocumentURI, mBaseURI,
mOwner->NodePrincipal(), true, scriptHandlingObject,
DocumentFlavorLegacyGuess);
DocumentFlavorXML);
NS_ENSURE_SUCCESS(rv, rv);
// When DOMImplementation's createDocument method is invoked with

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

@ -21,6 +21,7 @@
#include "mozilla/BasePrincipal.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/NullPrincipal.h"
#include "NullPrincipalURI.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ScriptSettings.h"
@ -250,8 +251,8 @@ already_AddRefed<DOMParser> DOMParser::Constructor(const GlobalObject& aOwner,
nsCOMPtr<nsIURI> documentURI;
nsIURI* baseURI = nullptr;
if (docPrincipal->IsSystemPrincipal()) {
docPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
docPrincipal->GetURI(getter_AddRefs(documentURI));
documentURI = new NullPrincipalURI();
docPrincipal = NullPrincipal::Create(OriginAttributes(), documentURI);
} else {
// Grab document and base URIs off the window our constructor was
// called on. Error out if anything untoward happens.
@ -280,10 +281,9 @@ already_AddRefed<DOMParser> DOMParser::Constructor(const GlobalObject& aOwner,
// static
already_AddRefed<DOMParser> DOMParser::CreateWithoutGlobal(ErrorResult& aRv) {
nsCOMPtr<nsIURI> documentURI = new NullPrincipalURI();
nsCOMPtr<nsIPrincipal> docPrincipal =
NullPrincipal::CreateWithoutOriginAttributes();
nsCOMPtr<nsIURI> documentURI;
docPrincipal->GetURI(getter_AddRefs(documentURI));
NullPrincipal::Create(OriginAttributes(), documentURI);
if (!documentURI) {
aRv.Throw(NS_ERROR_UNEXPECTED);

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

@ -11739,7 +11739,7 @@ class nsAutoFocusEvent : public Runnable {
FocusOptions options;
ErrorResult rv;
mElement->Focus(options, rv);
mElement->Focus(options, CallerType::System, rv);
return rv.StealNSResult();
}

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

@ -5467,6 +5467,7 @@ enum DocumentFlavor {
DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
DocumentFlavorSVG, // SVGDocument
DocumentFlavorXML, // XMLDocument
DocumentFlavorPlain, // Just a Document
};

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

@ -336,7 +336,8 @@ int32_t Element::TabIndex() {
return TabIndexDefault();
}
void Element::Focus(const FocusOptions& aOptions, ErrorResult& aError) {
void Element::Focus(const FocusOptions& aOptions, CallerType aCallerType,
ErrorResult& aError) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
// Also other browsers seem to have the hack to not re-focus (and flush) when
// the element is already focused.
@ -348,9 +349,13 @@ void Element::Focus(const FocusOptions& aOptions, ErrorResult& aError) {
if (fm->CanSkipFocus(this)) {
fm->NeedsFlushBeforeEventHandling(this);
} else {
aError = fm->SetFocus(
this, nsIFocusManager::FLAG_BYELEMENTFOCUS |
nsFocusManager::FocusOptionsToFocusManagerFlags(aOptions));
uint32_t fmFlags =
nsIFocusManager::FLAG_BYELEMENTFOCUS |
nsFocusManager::FocusOptionsToFocusManagerFlags(aOptions);
if (aCallerType == CallerType::NonSystem) {
fmFlags = nsIFocusManager::FLAG_NONSYSTEMCALLER | fmFlags;
}
aError = fm->SetFocus(this, fmFlags);
}
}
}

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

@ -234,7 +234,8 @@ class Element : public FragmentOrElement {
/**
* Make focus on this element.
*/
virtual void Focus(const FocusOptions& aOptions, ErrorResult& aError);
virtual void Focus(const FocusOptions& aOptions, const CallerType aCallerType,
ErrorResult& aError);
/**
* Show blur and clear focus.

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

@ -4339,7 +4339,8 @@ nsresult nsContentUtils::DispatchChromeEvent(
return err.StealNSResult();
}
void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise) {
void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
CallerType aCallerType) {
RefPtr<Element> target = &aFrameElement;
bool defaultAction = true;
if (aCanRaise) {
@ -4361,6 +4362,10 @@ void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise) {
flags |= nsIFocusManager::FLAG_RAISE;
}
if (aCallerType == CallerType::NonSystem) {
flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER;
}
fm->SetFocus(target, flags);
}

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

@ -1580,7 +1580,8 @@ class nsContentUtils {
* Helper to dispatch a "framefocusrequested" event to chrome, which will only
* bring the window to the foreground and switch tabs if aCanRaise is true.
*/
static void RequestFrameFocus(Element& aFrameElement, bool aCanRaise);
static void RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
mozilla::dom::CallerType aCallerType);
/**
* This method creates and dispatches a trusted event.

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

@ -30,6 +30,7 @@
#include "mozilla/dom/Selection.h"
#include "nsXULPopupManager.h"
#include "nsMenuPopupFrame.h"
#include "nsIScriptError.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIPrincipal.h"
#include "nsIObserverService.h"
@ -39,6 +40,7 @@
#include "nsHTMLDocument.h"
#include "nsNetUtil.h"
#include "nsRange.h"
#include "nsFrameLoaderOwner.h"
#include "mozilla/AccessibleCaretEventHub.h"
#include "mozilla/ContentEvents.h"
@ -49,6 +51,7 @@
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/BrowserBridgeChild.h"
#include "mozilla/dom/Text.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/EventStates.h"
@ -59,6 +62,7 @@
#include "mozilla/PresShell.h"
#include "mozilla/Services.h"
#include "mozilla/Unused.h"
#include "mozilla/StaticPrefs_full_screen_api.h"
#include <algorithm>
#ifdef MOZ_XUL
@ -69,10 +73,6 @@
# include "nsAccessibilityService.h"
#endif
#ifndef XP_MACOSX
# include "nsIScriptError.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::widget;
@ -351,21 +351,27 @@ nsFocusManager::GetActiveWindow(mozIDOMWindowProxy** aWindow) {
return NS_OK;
}
void nsFocusManager::FocusWindow(nsPIDOMWindowOuter* aWindow) {
void nsFocusManager::FocusWindow(nsPIDOMWindowOuter* aWindow,
CallerType aCallerType) {
if (RefPtr<nsFocusManager> fm = sInstance) {
fm->SetFocusedWindow(aWindow);
fm->SetFocusedWindowWithCallerType(aWindow, aCallerType);
}
}
NS_IMETHODIMP nsFocusManager::SetActiveWindow(mozIDOMWindowProxy* aWindow) {
return SetActiveWindowWithCallerType(aWindow, CallerType::System);
}
NS_IMETHODIMP
nsFocusManager::SetActiveWindow(mozIDOMWindowProxy* aWindow) {
nsFocusManager::SetActiveWindowWithCallerType(mozIDOMWindowProxy* aWindow,
CallerType aCallerType) {
NS_ENSURE_STATE(aWindow);
// only top-level windows can be made active
nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(aWindow);
NS_ENSURE_TRUE(piWindow == piWindow->GetPrivateRoot(), NS_ERROR_INVALID_ARG);
RaiseWindow(piWindow);
RaiseWindow(piWindow, aCallerType);
return NS_OK;
}
@ -375,8 +381,8 @@ nsFocusManager::GetFocusedWindow(mozIDOMWindowProxy** aFocusedWindow) {
return NS_OK;
}
NS_IMETHODIMP nsFocusManager::SetFocusedWindow(
mozIDOMWindowProxy* aWindowToFocus) {
NS_IMETHODIMP nsFocusManager::SetFocusedWindowWithCallerType(
mozIDOMWindowProxy* aWindowToFocus, CallerType aCallerType) {
LOGFOCUS(("<<SetFocusedWindow begin>>"));
nsCOMPtr<nsPIDOMWindowOuter> windowToFocus =
@ -401,13 +407,18 @@ NS_IMETHODIMP nsFocusManager::SetFocusedWindow(
}
nsCOMPtr<nsPIDOMWindowOuter> rootWindow = windowToFocus->GetPrivateRoot();
if (rootWindow) RaiseWindow(rootWindow);
if (rootWindow) RaiseWindow(rootWindow, aCallerType);
LOGFOCUS(("<<SetFocusedWindow end>>"));
return NS_OK;
}
NS_IMETHODIMP nsFocusManager::SetFocusedWindow(
mozIDOMWindowProxy* aWindowToFocus) {
return SetFocusedWindowWithCallerType(aWindowToFocus, CallerType::System);
}
NS_IMETHODIMP
nsFocusManager::GetFocusedElement(Element** aFocusedElement) {
RefPtr<Element> focusedElement = mFocusedElement;
@ -629,7 +640,7 @@ nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) {
// of the child we want. We solve this by calling SetFocus to ensure that
// what the focus manager thinks should be the current widget is actually
// focused.
EnsureCurrentWidgetFocused();
EnsureCurrentWidgetFocused(CallerType::System);
return NS_OK;
}
@ -844,7 +855,7 @@ nsFocusManager::WindowShown(mozIDOMWindowProxy* aWindow, bool aNeedsFocus) {
// Sometimes, an element in a window can be focused before the window is
// visible, which would mean that the widget may not be properly focused.
// When the window becomes visible, make sure the right widget is focused.
EnsureCurrentWidgetFocused();
EnsureCurrentWidgetFocused(CallerType::System);
}
return NS_OK;
@ -1058,7 +1069,7 @@ void nsFocusManager::NotifyFocusStateChange(nsIContent* aContent,
}
// static
void nsFocusManager::EnsureCurrentWidgetFocused() {
void nsFocusManager::EnsureCurrentWidgetFocused(CallerType aCallerType) {
if (!mFocusedWindow || sTestMode) return;
// get the main child widget for the focused window and ensure that the
@ -1080,7 +1091,7 @@ void nsFocusManager::EnsureCurrentWidgetFocused() {
if (!widget) {
return;
}
widget->SetFocus(nsIWidget::Raise::No);
widget->SetFocus(nsIWidget::Raise::No, aCallerType);
}
void nsFocusManager::ActivateOrDeactivate(nsPIDOMWindowOuter* aWindow,
@ -1111,6 +1122,37 @@ void nsFocusManager::ActivateOrDeactivate(nsPIDOMWindowOuter* aWindow,
});
}
// Retrieves innerWindowId of the window of the last focused element to
// log a warning to the website console.
void LogWarningFullscreenWindowRaise(Element* aElement) {
nsCOMPtr<nsFrameLoaderOwner> frameLoaderOwner(do_QueryInterface(aElement));
NS_ENSURE_TRUE_VOID(frameLoaderOwner);
RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
NS_ENSURE_TRUE_VOID(frameLoaderOwner);
RefPtr<BrowsingContext> browsingContext = frameLoader->GetBrowsingContext();
NS_ENSURE_TRUE_VOID(browsingContext);
WindowGlobalParent* windowGlobalParent =
browsingContext->Canonical()->GetCurrentWindowGlobal();
NS_ENSURE_TRUE_VOID(windowGlobalParent);
// Log to console
nsAutoString localizedMsg;
nsTArray<nsString> params;
nsresult rv = nsContentUtils::FormatLocalizedString(
nsContentUtils::eDOM_PROPERTIES, "FullscreenExitWindowFocus", params,
localizedMsg);
NS_ENSURE_SUCCESS_VOID(rv);
Unused << nsContentUtils::ReportToConsoleByWindowID(
localizedMsg, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM"),
windowGlobalParent->InnerWindowId(),
windowGlobalParent->GetDocumentURI());
}
void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
bool aFocusChanged, bool aAdjustWidget) {
// if the element is not focusable, just return and leave the focus as is
@ -1201,6 +1243,20 @@ void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
isElementInActiveWindow = (mActiveWindow && newRootWindow == mActiveWindow);
}
// Exit fullscreen if a website focuses another window
if (StaticPrefs::full_screen_api_exit_on_windowRaise() &&
!isElementInActiveWindow &&
aFlags & (FLAG_RAISE | FLAG_NONSYSTEMCALLER)) {
if (Document* doc = mActiveWindow ? mActiveWindow->GetDoc() : nullptr) {
if (doc->GetFullscreenElement()) {
if (XRE_IsParentProcess()) {
LogWarningFullscreenWindowRaise(mFocusedElement);
}
Document::AsyncExitFullscreen(doc);
}
}
}
// Exit fullscreen if we're focusing a windowed plugin on a non-MacOSX
// system. We don't control event dispatch to windowed plugins on non-MacOSX,
// so we can't display the "Press ESC to leave fullscreen mode" warning on
@ -1307,7 +1363,10 @@ void nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
if (allowFrameSwitch)
newWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
if (aFlags & FLAG_RAISE) RaiseWindow(newRootWindow);
if (aFlags & FLAG_RAISE)
RaiseWindow(newRootWindow, aFlags & FLAG_NONSYSTEMCALLER
? CallerType::NonSystem
: CallerType::System);
}
}
@ -1607,7 +1666,7 @@ bool nsFocusManager::Blur(nsPIDOMWindowOuter* aWindowToClear,
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) {
// set focus to the top level window but don't raise it.
widget->SetFocus(nsIWidget::Raise::No);
widget->SetFocus(nsIWidget::Raise::No, CallerType::System);
}
}
}
@ -1800,7 +1859,10 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
if (nsViewManager* vm = presShell->GetViewManager()) {
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) widget->SetFocus(nsIWidget::Raise::No);
if (widget)
widget->SetFocus(nsIWidget::Raise::No, aFlags & FLAG_NONSYSTEMCALLER
? CallerType::NonSystem
: CallerType::System);
}
}
@ -1854,7 +1916,10 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
// fired above when aIsNewDocument.
if (presShell->GetDocument() == aElement->GetComposedDoc()) {
if (aAdjustWidgets && objectFrameWidget && !sTestMode) {
objectFrameWidget->SetFocus(nsIWidget::Raise::No);
objectFrameWidget->SetFocus(nsIWidget::Raise::No,
aFlags & FLAG_NONSYSTEMCALLER
? CallerType::NonSystem
: CallerType::System);
}
// if the object being focused is a remote browser, activate remote
@ -1891,7 +1956,9 @@ void nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow, Element* aElement,
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) {
widget->SetFocus(nsIWidget::Raise::No);
widget->SetFocus(nsIWidget::Raise::No, aFlags & FLAG_NONSYSTEMCALLER
? CallerType::NonSystem
: CallerType::System);
}
}
}
@ -2124,7 +2191,8 @@ void nsFocusManager::ScrollIntoView(PresShell* aPresShell, nsIContent* aContent,
}
}
void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow) {
void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow,
CallerType aCallerType) {
// don't raise windows that are already raised or are in the process of
// being lowered
if (!aWindow || aWindow == mActiveWindow || aWindow == mWindowBeingLowered)
@ -2169,7 +2237,7 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow) {
if (nsViewManager* vm = presShell->GetViewManager()) {
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) widget->SetFocus(nsIWidget::Raise::Yes);
if (widget) widget->SetFocus(nsIWidget::Raise::Yes, aCallerType);
}
#else
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin =
@ -2177,7 +2245,7 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow) {
if (treeOwnerAsWin) {
nsCOMPtr<nsIWidget> widget;
treeOwnerAsWin->GetMainWidget(getter_AddRefs(widget));
if (widget) widget->SetFocus(nsIWidget::Raise::Yes);
if (widget) widget->SetFocus(nsIWidget::Raise::Yes, aCallerType);
}
#endif
}

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

@ -60,7 +60,8 @@ class nsFocusManager final : public nsIFocusManager,
// Simple helper to call SetFocusedWindow on the instance.
//
// This raises the window and switches to the tab as needed.
static void FocusWindow(nsPIDOMWindowOuter* aWindow);
static void FocusWindow(nsPIDOMWindowOuter* aWindow,
mozilla::dom::CallerType aCallerType);
static void PrefChanged(const char* aPref, void* aSelf);
void PrefChanged(const char* aPref);
@ -202,7 +203,7 @@ class nsFocusManager final : public nsIFocusManager,
* Ensure that the widget associated with the currently focused window is
* focused at the widget level.
*/
void EnsureCurrentWidgetFocused();
void EnsureCurrentWidgetFocused(mozilla::dom::CallerType aCallerType);
/**
* Activate or deactivate the window and send the activate/deactivate events.
@ -350,7 +351,6 @@ class nsFocusManager final : public nsIFocusManager,
Document* aDocument, nsISupports* aTarget, uint32_t aFocusMethod,
bool aWindowRaised, bool aIsRefocus = false,
mozilla::dom::EventTarget* aRelatedTarget = nullptr);
/**
* Fire a focus or blur event at aTarget.
*
@ -397,7 +397,8 @@ class nsFocusManager final : public nsIFocusManager,
/**
* Raises the top-level window aWindow at the widget level.
*/
void RaiseWindow(nsPIDOMWindowOuter* aWindow);
void RaiseWindow(nsPIDOMWindowOuter* aWindow,
mozilla::dom::CallerType aCallerType);
/**
* Updates the caret positon and visibility to match the focus.

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

@ -3451,13 +3451,13 @@ void nsGlobalWindowInner::Prompt(const nsAString& aMessage,
aError, );
}
void nsGlobalWindowInner::Focus(ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(FocusOuter, (), aError, );
void nsGlobalWindowInner::Focus(CallerType aCallerType, ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(FocusOuter, (aCallerType), aError, );
}
nsresult nsGlobalWindowInner::Focus() {
nsresult nsGlobalWindowInner::Focus(CallerType aCallerType) {
ErrorResult rv;
Focus(rv);
Focus(aCallerType, rv);
return rv.StealNSResult();
}

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

@ -601,8 +601,9 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
nsresult Close() override;
bool GetClosed(mozilla::ErrorResult& aError);
void Stop(mozilla::ErrorResult& aError);
void Focus(mozilla::ErrorResult& aError);
nsresult Focus() override;
void Focus(mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
nsresult Focus(mozilla::dom::CallerType aCallerType) override;
void Blur(mozilla::ErrorResult& aError);
mozilla::dom::WindowProxyHolder GetFrames(mozilla::ErrorResult& aError);
uint32_t Length();

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

@ -4830,7 +4830,7 @@ void nsGlobalWindowOuter::PromptOuter(const nsAString& aMessage,
}
}
void nsGlobalWindowOuter::FocusOuter() {
void nsGlobalWindowOuter::FocusOuter(CallerType aCallerType) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (!fm) {
return;
@ -4899,7 +4899,7 @@ void nsGlobalWindowOuter::FocusOuter() {
}
if (Element* frame = parentdoc->FindContentForSubDocument(mDoc)) {
nsContentUtils::RequestFrameFocus(*frame, canFocus);
nsContentUtils::RequestFrameFocus(*frame, canFocus, aCallerType);
}
return;
}
@ -4908,15 +4908,17 @@ void nsGlobalWindowOuter::FocusOuter() {
// if there is no parent, this must be a toplevel window, so raise the
// window if canFocus is true. If this is a child process, the raise
// window request will get forwarded to the parent by the puppet widget.
DebugOnly<nsresult> rv = fm->SetActiveWindow(this);
DebugOnly<nsresult> rv =
fm->SetActiveWindowWithCallerType(this, aCallerType);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"SetActiveWindow only fails if passed null or a non-toplevel "
"SetActiveWindowWithCallerType only fails if passed null or a "
"non-toplevel "
"window, which is not the case here.");
}
}
nsresult nsGlobalWindowOuter::Focus() {
FORWARD_TO_INNER(Focus, (), NS_ERROR_UNEXPECTED);
nsresult nsGlobalWindowOuter::Focus(CallerType aCallerType) {
FORWARD_TO_INNER(Focus, (aCallerType), NS_ERROR_UNEXPECTED);
}
void nsGlobalWindowOuter::BlurOuter() {

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

@ -542,8 +542,8 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
bool GetClosedOuter();
bool Closed() override;
void StopOuter(mozilla::ErrorResult& aError);
void FocusOuter();
nsresult Focus() override;
void FocusOuter(mozilla::dom::CallerType aCallerType);
nsresult Focus(mozilla::dom::CallerType aCallerType) override;
void BlurOuter();
mozilla::dom::WindowProxyHolder GetFramesOuter();
uint32_t Length();

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

@ -544,7 +544,7 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
virtual bool GetFullScreen() = 0;
virtual nsresult Focus() = 0;
virtual nsresult Focus(mozilla::dom::CallerType aCallerType) = 0;
virtual nsresult Close() = 0;
mozilla::dom::DocGroup* GetDocGroup() const;
@ -1033,7 +1033,7 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
virtual bool GetFullScreen() = 0;
virtual nsresult SetFullScreen(bool aFullscreen) = 0;
virtual nsresult Focus() = 0;
virtual nsresult Focus(mozilla::dom::CallerType aCallerType) = 0;
virtual nsresult Close() = 0;
virtual nsresult MoveBy(int32_t aXDif, int32_t aYDif) = 0;

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

@ -16,10 +16,8 @@ support-files =
file_bug1139964.xhtml
file_bug1209621.xhtml
fileconstructor_file.png
frame_bug814638.xhtml
frame_custom_element_content.html
custom_element_ep.js
host_bug814638.xhtml
window_nsITextInputProcessor.xhtml
title_window.xhtml
window_swapFrameLoaders.xhtml
@ -53,7 +51,6 @@ skip-if = verify
[test_bug780199.xhtml]
[test_bug780529.xhtml]
[test_bug800386.xhtml]
[test_bug814638.xhtml]
[test_bug816340.xhtml]
[test_bug884693.xhtml]
[test_bug914381.html]

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

@ -1,15 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=814638
-->
<window title="Mozilla Bug 814638"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<keyset>
<key key="T" modifiers="control" oncommand="receivedKeyEvent()"/>
</keyset>
<iframe flex="1" src="about:mozilla"/>
</window>

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

@ -1,9 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=814638
-->
<window title="Mozilla Bug 814638"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<iframe flex="1" src="frame_bug814638.xhtml"/>
</window>

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

@ -1,63 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=814638
-->
<window title="Mozilla Bug 814638"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=814638"
target="_blank" id="link">Mozilla Bug 814638</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 814638 **/
SimpleTest.waitForExplicitFinish();
function startTest() {
let hostURL = "chrome://mochitests/content/chrome/dom/base/test/chrome/host_bug814638.xhtml";
let host1 = docShell.rootTreeItem.domWindow.open(hostURL, "_blank", "chrome");
let host2 = docShell.rootTreeItem.domWindow.open(hostURL, "_blank", "chrome");
let isHost1Loaded = isHost2Loaded = false
host1.onload = function() {
isHost1Loaded = true;
if (isHost2Loaded) swapFrames();
}
host2.onload = function() {
isHost2Loaded = true;
if (isHost1Loaded) swapFrames();
}
function swapFrames() {
let iframe1 = host1.document.querySelector("iframe");
let iframe2 = host2.document.querySelector("iframe");
iframe2.swapFrameLoaders(iframe1);
setTimeout(function() {
iframe2.contentWindow.receivedKeyEvent = receivedKeyEvent;
let innerIframe2 = iframe2.contentDocument.querySelector("iframe");
let e = innerIframe2.contentDocument.createEvent("KeyboardEvent");
e.initKeyEvent("keypress", true, true, null, true, false, false, false, 0, "t".charCodeAt(0));
innerIframe2.contentDocument.documentElement.dispatchEvent(e);
host1.close();
host2.close();
}, 0);
}
}
function receivedKeyEvent() {
ok(true, "Received key event");
SimpleTest.finish();
}
addLoadEvent(startTest);
]]>
</script>
</window>

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

@ -20,40 +20,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=450160
/** Test for Bug 450160 **/
function testHTMLDocuments(ids, isXHTML) {
for (var i = 0; i < ids.length; ++i) {
var docType1 =
document.implementation.createDocumentType(isXHTML ? "html" : "HTML",
ids[i],
null);
ok(docType1, "No doctype?");
ok(docType1.ownerDocument, "docType should have ownerDocument!");
var doc1 = document.implementation.createDocument(null, null, docType1);
is(docType1.ownerDocument, doc1, "docType should have ownerDocument!");
ok(!doc1.documentElement, "Document shouldn't have document element!");
is(doc1.body, null, "Shouldn't have .body!");
ok(doc1 instanceof HTMLDocument,
"Document should be an HTML document!");
var docType2 =
document.implementation.createDocumentType(isXHTML ? "html" : "HTML",
ids[i],
null);
var doc2 = document.implementation.createDocument(
"http://www.w3.org/1999/xhtml", "html", docType2);
is(docType2.ownerDocument, doc2, "docType should have ownerDocument!");
ok(doc2.documentElement, "Document should have document element!");
is(doc2.documentElement.localName, "html", "Wrong document element!");
is(doc2.body, null, "Shouldn't have .body!");
doc2.documentElement.appendChild(doc2.createElement("body"));
is(doc2.body, doc2.documentElement.firstChild, "Should have .body!");
if (isXHTML) {
doc2.body.appendChild(doc2.createElementNS("http://www.w3.org/1999/xhtml", "form"));
} else {
doc2.body.appendChild(doc2.createElement("form"));
}
is(doc2.forms.length, 1, "Form wasn't added .forms");
}
function testHTMLDocument() {
var doc = document.implementation.createHTMLDocument();
ok(!!doc.documentElement, "Document should have document element!");
ok(!!doc.body, "Should have .body!");
ok(doc instanceof HTMLDocument,
"Document should be an HTML document!");
}
function testSVGDocument() {
@ -117,21 +89,7 @@ function testNullDocTypeDocument() {
is(doc2.documentElement.localName, "FooBar", "Wrong localName!");
}
var htmlPublicIDs =
[ "-//W3C//DTD HTML 4.01//EN",
"-//W3C//DTD HTML 4.01 Transitional//EN",
"-//W3C//DTD HTML 4.01 Frameset//EN",
"-//W3C//DTD HTML 4.0//EN",
"-//W3C//DTD HTML 4.0 Transitional//EN",
"-//W3C//DTD HTML 4.0 Frameset//EN" ];
var xhtmlPublicIDs =
[ "-//W3C//DTD XHTML 1.0 Strict//EN",
"-//W3C//DTD XHTML 1.0 Transitional//EN",
"-//W3C//DTD XHTML 1.0 Frameset//EN" ];
testHTMLDocuments(htmlPublicIDs, false);
testHTMLDocuments(xhtmlPublicIDs, true);
testHTMLDocument();
testSVGDocument();
testFooBarDocument();
testNullDocTypeDocument();

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

@ -23,10 +23,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=562652
var testCount = 0;
function createHTMLDoc() {
var dtd = document.implementation.createDocumentType("HTML", "-//W3C//DTD HTML 4.01//EN", null);
var d = document.implementation.createDocument(null, null, dtd);
d.appendChild(d.createElement("html"));
d.documentElement.appendChild(d.createElement("body"));
var d = document.implementation.createHTMLDocument();
d.body.setAttribute("id", "testtarget");
return d;
}

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

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef _mozilla_dom_BindingIPCUtils_h
#define _mozilla_dom_BindingIPCUtils_h
#include "mozilla/dom/BindingDeclarations.h"
#include "ipc/IPCMessageUtils.h"
namespace IPC {
template <>
struct ParamTraits<mozilla::dom::CallerType>
: public ContiguousEnumSerializerInclusive<
mozilla::dom::CallerType, mozilla::dom::CallerType::System,
mozilla::dom::CallerType::NonSystem> {};
} // namespace IPC
#endif // _mozilla_dom_BindingIPCUtils_h

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

@ -28,6 +28,7 @@ EXPORTS.mozilla += [
EXPORTS.mozilla.dom += [
'AtomList.h',
'BindingDeclarations.h',
'BindingIPCUtils.h',
'BindingUtils.h',
'CallbackFunction.h',
'CallbackInterface.h',

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

@ -26,7 +26,7 @@ WebGLSampler::~WebGLSampler() {
static bool ValidateSamplerParameterParams(WebGLContext* webgl, GLenum pname,
const FloatOrInt& param) {
const auto& paramInt = param.i;
bool pnameValid = true;
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_FILTER:
switch (paramInt) {
@ -100,9 +100,22 @@ static bool ValidateSamplerParameterParams(WebGLContext* webgl, GLenum pname,
}
break;
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY:
if (webgl->IsExtensionEnabled(
WebGLExtensionID::EXT_texture_filter_anisotropic)) {
return true;
}
pnameValid = false;
break;
default:
webgl->ErrorInvalidEnumInfo("pname", pname);
return false;
pnameValid = false;
break;
}
if (!pnameValid) {
webgl->ErrorInvalidEnumInfo("pname", pname);
return false;
}
webgl->ErrorInvalidEnumInfo("param", paramInt);

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

@ -126,7 +126,8 @@ bool Client::Focused() const {
return mData->state().get_IPCClientWindowState().focused();
}
already_AddRefed<Promise> Client::Focus(ErrorResult& aRv) {
already_AddRefed<Promise> Client::Focus(CallerType aCallerType,
ErrorResult& aRv) {
MOZ_ASSERT(!NS_IsMainThread());
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
@ -149,7 +150,7 @@ already_AddRefed<Promise> Client::Focus(ErrorResult& aRv) {
auto holder =
MakeRefPtr<DOMMozPromiseRequestHolder<ClientStatePromise>>(mGlobal);
mHandle->Focus()
mHandle->Focus(aCallerType)
->Then(
mGlobal->EventTargetFor(TaskCategory::Other), __func__,
[ipcClientInfo, holder, outerPromise](const ClientState& aResult) {

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

@ -69,7 +69,7 @@ class Client final : public nsISupports, public nsWrapperCache {
bool Focused() const;
already_AddRefed<Promise> Focus(ErrorResult& aRv);
already_AddRefed<Promise> Focus(CallerType aCallerType, ErrorResult& aRv);
already_AddRefed<Promise> Navigate(const nsAString& aURL, ErrorResult& aRv);

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

@ -122,12 +122,12 @@ RefPtr<GenericPromise> ClientHandle::Control(
return outerPromise.forget();
}
RefPtr<ClientStatePromise> ClientHandle::Focus() {
RefPtr<ClientStatePromise> ClientHandle::Focus(CallerType aCallerType) {
RefPtr<ClientStatePromise::Private> outerPromise =
new ClientStatePromise::Private(__func__);
StartOp(
ClientFocusArgs(),
ClientFocusArgs(aCallerType),
[outerPromise](const ClientOpResult& aResult) {
outerPromise->Resolve(
ClientState::FromIPC(aResult.get_IPCClientState()), __func__);

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

@ -76,7 +76,7 @@ class ClientHandle final : public ClientThing<ClientHandleChild> {
// Focus the Client if possible. If successful the promise will resolve with
// a new ClientState snapshot after focus has completed. If focusing fails
// for any reason then the promise will reject.
RefPtr<ClientStatePromise> Focus();
RefPtr<ClientStatePromise> Focus(CallerType aCallerType);
// Send a postMessage() call to the target Client. Currently this only
// supports sending from a ServiceWorker source and the MessageEvent is

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

@ -12,6 +12,7 @@ using ClientType from "mozilla/dom/ClientIPCUtils.h";
using FrameType from "mozilla/dom/ClientIPCUtils.h";
using mozilla::StorageAccess from "mozilla/dom/ClientIPCUtils.h";
using VisibilityState from "mozilla/dom/ClientIPCUtils.h";
using CallerType from "mozilla/dom/BindingIPCUtils.h";
namespace mozilla {
namespace dom {
@ -75,6 +76,7 @@ struct ClientControlledArgs
struct ClientFocusArgs
{
CallerType callerType;
};
struct ClientNavigateArgs

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

@ -262,7 +262,7 @@ void WaitForLoad(const ClientOpenWindowArgs& aArgs,
RefPtr<ClientOpPromise::Private> promise = aPromise;
nsFocusManager::FocusWindow(aOuterWindow);
nsFocusManager::FocusWindow(aOuterWindow, CallerType::NonSystem);
nsCOMPtr<nsIURI> baseURI;
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), aArgs.baseURL());

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

@ -555,7 +555,7 @@ RefPtr<ClientOpPromise> ClientSource::Focus(const ClientFocusArgs& aArgs) {
}
MOZ_ASSERT(NS_IsMainThread());
nsFocusManager::FocusWindow(outer);
nsFocusManager::FocusWindow(outer, aArgs.callerType());
ClientState state;
nsresult rv = SnapshotState(&state);

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

@ -1080,7 +1080,7 @@ bool EventStateManager::LookForAccessKeyAndExecute(
nsCOMPtr<nsIBrowserChild> child =
docShell ? docShell->GetBrowserChild() : nullptr;
if (child) {
child->SendRequestFocus(false);
child->SendRequestFocus(false, CallerType::System);
}
}

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

@ -2932,7 +2932,7 @@ void HTMLInputElement::Blur(ErrorResult& aError) {
}
void HTMLInputElement::Focus(const FocusOptions& aOptions,
ErrorResult& aError) {
CallerType aCallerType, ErrorResult& aError) {
if ((mType == NS_FORM_INPUT_TIME || mType == NS_FORM_INPUT_DATE) &&
!IsExperimentalMobileType(mType)) {
if (Element* dateTimeBoxElement = GetDateTimeBoxElement()) {
@ -2944,7 +2944,7 @@ void HTMLInputElement::Focus(const FocusOptions& aOptions,
}
}
nsGenericHTMLElement::Focus(aOptions, aError);
nsGenericHTMLElement::Focus(aOptions, aCallerType, aError);
}
#if !defined(ANDROID) && !defined(XP_MACOSX)
@ -3798,7 +3798,8 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
FocusOptions options;
ErrorResult error;
selectedRadioButton->Focus(options, error);
selectedRadioButton->Focus(options, CallerType::System,
error);
rv = error.StealNSResult();
if (NS_SUCCEEDED(rv)) {
rv = DispatchSimulatedClick(selectedRadioButton,

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

@ -142,7 +142,7 @@ class HTMLInputElement final : public TextControlElement,
virtual int32_t TabIndexDefault() override;
using nsGenericHTMLElement::Focus;
virtual void Blur(ErrorResult& aError) override;
virtual void Focus(const FocusOptions& aOptions,
virtual void Focus(const FocusOptions& aOptions, const CallerType aCallerType,
ErrorResult& aError) override;
// nsINode

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

@ -51,6 +51,7 @@ HTMLFormElement* HTMLLabelElement::GetForm() const {
}
void HTMLLabelElement::Focus(const FocusOptions& aOptions,
const CallerType aCallerType,
ErrorResult& aError) {
// retarget the focus method at the for content
nsIFocusManager* fm = nsFocusManager::GetFocusManager();

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

@ -44,6 +44,7 @@ class HTMLLabelElement final : public nsGenericHTMLElement {
using nsGenericHTMLElement::Focus;
virtual void Focus(const FocusOptions& aOptions,
const mozilla::dom::CallerType aCallerType,
ErrorResult& aError) override;
// nsIContent

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

@ -67,6 +67,7 @@ void HTMLLegendElement::UnbindFromTree(bool aNullParent) {
}
void HTMLLegendElement::Focus(const FocusOptions& aOptions,
const mozilla::dom::CallerType aCallerType,
ErrorResult& aError) {
nsIFrame* frame = GetPrimaryFrame();
if (!frame) {
@ -75,7 +76,7 @@ void HTMLLegendElement::Focus(const FocusOptions& aOptions,
int32_t tabIndex;
if (frame->IsFocusable(&tabIndex, false)) {
nsGenericHTMLElement::Focus(aOptions, aError);
nsGenericHTMLElement::Focus(aOptions, aCallerType, aError);
return;
}
@ -100,7 +101,7 @@ bool HTMLLegendElement::PerformAccesskey(bool aKeyCausesActivation,
FocusOptions options;
ErrorResult rv;
Focus(options, rv);
Focus(options, CallerType::System, rv);
return NS_SUCCEEDED(rv.StealNSResult());
}

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

@ -24,6 +24,7 @@ class HTMLLegendElement final : public nsGenericHTMLElement {
using nsGenericHTMLElement::Focus;
virtual void Focus(const FocusOptions& aOptions,
const mozilla::dom::CallerType aCallerType,
ErrorResult& aError) override;
virtual bool PerformAccesskey(bool aKeyCausesActivation,

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

@ -28,7 +28,8 @@ SimpleTest.requestFlakyTimeout("untriaged");
// run in an iframe, which by default will not have the allowfullscreen
// attribute set, so full-screen won't work.
var gTestWindows = [
{ test: "file_fullscreen-multiple.html" },
{ test: "file_fullscreen-multiple.html",
prefs: [["full-screen-api.exit-on.windowRaise", false], ["full-screen-api.exit-on.windowOpen", false]] },
{ test: "file_fullscreen-rollback.html" },
{ test: "file_fullscreen-esc-exit.html" },
{ test: "file_fullscreen-denied.html" },

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

@ -10,6 +10,8 @@ interface nsIWebBrowserChrome3;
webidl ContentFrameMessageManager;
native CallerType(mozilla::dom::CallerType);
native CommandsArray(nsTArray<nsCString>);
[ref] native CommandsArrayRef(nsTArray<nsCString>);
@ -20,7 +22,7 @@ interface nsIBrowserChild : nsISupports
attribute nsIWebBrowserChrome3 webBrowserChrome;
[notxpcom] void sendRequestFocus(in boolean canFocus);
[notxpcom] void sendRequestFocus(in boolean canFocus, in CallerType aCallerType);
[noscript, notxpcom] void enableDisableCommands(in AString action,
in CommandsArrayRef enabledCommands,

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

@ -10,6 +10,8 @@ interface mozIDOMWindowProxy;
webidl Document;
webidl Element;
native CallerType(mozilla::dom::CallerType);
/**
* The focus manager deals with all focus related behaviour. Only one element
* in the entire application may have the focus at a time; this element
@ -47,9 +49,15 @@ interface nsIFocusManager : nsISupports
* focuses the current child window's current element, if any. Setting this
* to null or to a non-top-level window throws an NS_ERROR_INVALID_ARG
* exception.
* The setter for this attribute defaults to CallerType::System.
*/
attribute mozIDOMWindowProxy activeWindow;
/**
* Setter for activeWindow with CallerType
*/
[noscript] void SetActiveWindowWithCallerType(in mozIDOMWindowProxy aWindow, in CallerType aCallerType);
/**
* The child window within the activeWindow that is focused. This will
* always be activeWindow, a child window of activeWindow or null if no
@ -59,9 +67,15 @@ interface nsIFocusManager : nsISupports
* will actually be set to the child window and the current element within
* that set as the focused element. This process repeats downwards until a
* non-frame element is found.
* The setter for this attribute defaults to CallerType::System.
*/
attribute mozIDOMWindowProxy focusedWindow;
/**
* Setter for focusedWindow with CallerType
*/
[noscript] void SetFocusedWindowWithCallerType(in mozIDOMWindowProxy aWindow, in CallerType aCallerType);
/**
* The element that is currently focused. This will always be an element
* within the document loaded in focusedWindow or null if no element in that
@ -176,6 +190,12 @@ interface nsIFocusManager : nsISupports
*/
const unsigned long FLAG_NOPARENTFRAME = 8;
/**
* This flag is used for window and element focus operations to signal
* wether the caller is system or non system.
*/
const unsigned long FLAG_NONSYSTEMCALLER = 16;
/**
* Focus is changing due to a mouse operation, for instance the mouse was
* clicked on an element.

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

@ -117,13 +117,13 @@ IPCResult BrowserBridgeChild::RecvSetLayersId(
}
mozilla::ipc::IPCResult BrowserBridgeChild::RecvRequestFocus(
const bool& aCanRaise) {
const bool& aCanRaise, const CallerType aCallerType) {
// Adapted from BrowserParent
RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
if (!owner) {
return IPC_OK();
}
nsContentUtils::RequestFrameFocus(*owner, aCanRaise);
nsContentUtils::RequestFrameFocus(*owner, aCanRaise, aCallerType);
return IPC_OK();
}

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

@ -77,7 +77,8 @@ class BrowserBridgeChild : public PBrowserBridgeChild {
mozilla::ipc::IPCResult RecvSetLayersId(
const mozilla::layers::LayersId& aLayersId);
mozilla::ipc::IPCResult RecvRequestFocus(const bool& aCanRaise);
mozilla::ipc::IPCResult RecvRequestFocus(const bool& aCanRaise,
const CallerType aCallerType);
mozilla::ipc::IPCResult RecvMoveFocus(const bool& aForward,
const bool& aForDocumentNavigation);

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

@ -2652,7 +2652,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvNavigateByKey(
nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
}
SendRequestFocus(false);
SendRequestFocus(false, CallerType::System);
}
return IPC_OK();
@ -2981,8 +2981,8 @@ BrowserChild::SetWebBrowserChrome(nsIWebBrowserChrome3* aWebBrowserChrome) {
return NS_OK;
}
void BrowserChild::SendRequestFocus(bool aCanFocus) {
PBrowserChild::SendRequestFocus(aCanFocus);
void BrowserChild::SendRequestFocus(bool aCanFocus, CallerType aCallerType) {
PBrowserChild::SendRequestFocus(aCanFocus, aCallerType);
}
void BrowserChild::EnableDisableCommands(

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

@ -2229,10 +2229,11 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnWindowedPluginKeyEvent(
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserParent::RecvRequestFocus(const bool& aCanRaise) {
mozilla::ipc::IPCResult BrowserParent::RecvRequestFocus(
const bool& aCanRaise, const CallerType aCallerType) {
LOGBROWSERFOCUS(("RecvRequestFocus %p, aCanRaise: %d", this, aCanRaise));
if (BrowserBridgeParent* bridgeParent = GetBrowserBridgeParent()) {
mozilla::Unused << bridgeParent->SendRequestFocus(aCanRaise);
mozilla::Unused << bridgeParent->SendRequestFocus(aCanRaise, aCallerType);
return IPC_OK();
}
@ -2240,7 +2241,7 @@ mozilla::ipc::IPCResult BrowserParent::RecvRequestFocus(const bool& aCanRaise) {
return IPC_OK();
}
nsContentUtils::RequestFrameFocus(*mFrameElement, aCanRaise);
nsContentUtils::RequestFrameFocus(*mFrameElement, aCanRaise, aCallerType);
return IPC_OK();
}
@ -3138,7 +3139,7 @@ mozilla::ipc::IPCResult BrowserParent::RecvSetNativeChildOfShareableWindow(
mozilla::ipc::IPCResult BrowserParent::RecvDispatchFocusToTopLevelWindow() {
if (nsCOMPtr<nsIWidget> widget = GetTopLevelWidget()) {
widget->SetFocus(nsIWidget::Raise::No);
widget->SetFocus(nsIWidget::Raise::No, CallerType::System);
}
return IPC_OK();
}

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

@ -424,7 +424,8 @@ class BrowserParent final : public PBrowserParent,
mozilla::ipc::IPCResult RecvOnWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData);
mozilla::ipc::IPCResult RecvRequestFocus(const bool& aCanRaise);
mozilla::ipc::IPCResult RecvRequestFocus(const bool& aCanRaise,
const CallerType aCallerType);
mozilla::ipc::IPCResult RecvLookUpDictionary(
const nsString& aText, nsTArray<mozilla::FontRange>&& aFontRangeArray,

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

@ -4047,8 +4047,8 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowClose(BrowsingContext* aContext,
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
BrowsingContext* aContext) {
mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(BrowsingContext* aContext,
CallerType aCallerType) {
if (!aContext) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
@ -4062,7 +4062,7 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
("ChildIPC: Trying to send a message to a context without a window"));
return IPC_OK();
}
nsGlobalWindowOuter::Cast(window)->FocusOuter();
nsGlobalWindowOuter::Cast(window)->FocusOuter(aCallerType);
return IPC_OK();
}
@ -4213,7 +4213,7 @@ mozilla::ipc::IPCResult ContentChild::RecvInternalLoad(
if (aTakeFocus) {
if (nsCOMPtr<nsPIDOMWindowOuter> domWin = aContext->GetDOMWindow()) {
nsFocusManager::FocusWindow(domWin);
nsFocusManager::FocusWindow(domWin, CallerType::System);
}
}

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

@ -751,7 +751,8 @@ class ContentChild final
mozilla::ipc::IPCResult RecvWindowClose(BrowsingContext* aContext,
bool aTrustedCaller);
mozilla::ipc::IPCResult RecvWindowFocus(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvWindowFocus(BrowsingContext* aContext,
CallerType aCallerType);
mozilla::ipc::IPCResult RecvWindowBlur(BrowsingContext* aContext);
mozilla::ipc::IPCResult RecvWindowPostMessage(
BrowsingContext* aContext, const ClonedMessageData& aMessage,

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

@ -6289,7 +6289,7 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowClose(
}
mozilla::ipc::IPCResult ContentParent::RecvWindowFocus(
BrowsingContext* aContext) {
BrowsingContext* aContext, CallerType aCallerType) {
if (!aContext || aContext->IsDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
@ -6300,7 +6300,7 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowFocus(
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp = cpm->GetContentProcessById(
ContentParentId(aContext->Canonical()->OwnerProcessId()));
Unused << cp->SendWindowFocus(aContext);
Unused << cp->SendWindowFocus(aContext, aCallerType);
return IPC_OK();
}

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