forked from mirrors/gecko-dev
Bug 1669961: Return null from .contentWindow when inner window is inactive. r=nika
Differential Revision: https://phabricator.services.mozilla.com/D93853
This commit is contained in:
parent
61a922522e
commit
cfebcd3fd2
11 changed files with 108 additions and 16 deletions
|
|
@ -360,10 +360,14 @@ async function unregisterServiceWorker(tab, expectedPageUrl) {
|
||||||
async function waitForRegistrationReady(tab, expectedPageUrl) {
|
async function waitForRegistrationReady(tab, expectedPageUrl) {
|
||||||
await asyncWaitUntil(() =>
|
await asyncWaitUntil(() =>
|
||||||
SpecialPowers.spawn(tab.linkedBrowser, [expectedPageUrl], function(_url) {
|
SpecialPowers.spawn(tab.linkedBrowser, [expectedPageUrl], function(_url) {
|
||||||
const win = content.wrappedJSObject;
|
try {
|
||||||
const isExpectedUrl = win.location.href === _url;
|
const win = content.wrappedJSObject;
|
||||||
const hasRegistration = !!win.registration;
|
const isExpectedUrl = win.location.href === _url;
|
||||||
return isExpectedUrl && hasRegistration;
|
const hasRegistration = !!win.registration;
|
||||||
|
return isExpectedUrl && hasRegistration;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ add_task(async function() {
|
||||||
"History listener got called after a content viewer was evicted"
|
"History listener got called after a content viewer was evicted"
|
||||||
);
|
);
|
||||||
legacySHistory.removeSHistoryListener(historyListener);
|
legacySHistory.removeSHistoryListener(historyListener);
|
||||||
delete content._testListener;
|
|
||||||
// 6. Resolve the promise when we got our 'content viewer evicted' event
|
// 6. Resolve the promise when we got our 'content viewer evicted' event
|
||||||
resolve();
|
resolve();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -124,9 +124,17 @@ nsIDocShell* JSWindowActorChild::GetDocShell(ErrorResult& aRv) {
|
||||||
|
|
||||||
Nullable<WindowProxyHolder> JSWindowActorChild::GetContentWindow(
|
Nullable<WindowProxyHolder> JSWindowActorChild::GetContentWindow(
|
||||||
ErrorResult& aRv) {
|
ErrorResult& aRv) {
|
||||||
if (BrowsingContext* bc = GetBrowsingContext(aRv)) {
|
if (!mManager) {
|
||||||
return WindowProxyHolder(bc);
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nsGlobalWindowInner* window = mManager->GetWindowGlobal()) {
|
||||||
|
if (window->IsCurrentInnerWindow()) {
|
||||||
|
return WindowProxyHolder(window->GetBrowsingContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
support-files =
|
support-files =
|
||||||
head.js
|
head.js
|
||||||
|
|
||||||
|
[browser_contentWindow.js]
|
||||||
[browser_crash_report.js]
|
[browser_crash_report.js]
|
||||||
[browser_destroy_callbacks.js]
|
[browser_destroy_callbacks.js]
|
||||||
skip-if = !debug && (os == 'mac') #Bug 1604538
|
skip-if = !debug && (os == 'mac') #Bug 1604538
|
||||||
|
|
|
||||||
47
dom/ipc/tests/JSWindowActor/browser_contentWindow.js
Normal file
47
dom/ipc/tests/JSWindowActor/browser_contentWindow.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
declTest("contentWindow null when inner window inactive", {
|
||||||
|
matches: [TEST_URL + "*"],
|
||||||
|
url: TEST_URL + "?1",
|
||||||
|
|
||||||
|
async test(browser) {
|
||||||
|
{
|
||||||
|
let parent = browser.browsingContext.currentWindowGlobal;
|
||||||
|
let actorParent = parent.getActor("TestWindow");
|
||||||
|
|
||||||
|
await actorParent.sendQuery("storeActor");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let url = TEST_URL + "?2";
|
||||||
|
let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
|
||||||
|
await BrowserTestUtils.loadURI(browser, url);
|
||||||
|
await loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = browser.browsingContext.currentWindowGlobal;
|
||||||
|
let actorParent = parent.getActor("TestWindow");
|
||||||
|
|
||||||
|
let result = await actorParent.sendQuery("checkActor");
|
||||||
|
if (SpecialPowers.useRemoteSubframes) {
|
||||||
|
is(
|
||||||
|
result.status,
|
||||||
|
"error",
|
||||||
|
"Should get an error when bfcache is disabled for Fission"
|
||||||
|
);
|
||||||
|
is(
|
||||||
|
result.errorType,
|
||||||
|
"InvalidStateError",
|
||||||
|
"Should get an InvalidStateError without bfcache"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
is(result.status, "success", "Should succeed when bfcache is enabled");
|
||||||
|
ok(
|
||||||
|
result.valueIsNull,
|
||||||
|
"Should get a null contentWindow when inner window is inactive"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -35,7 +35,7 @@ declTest("sendQuery Error", {
|
||||||
is(error.name, "SyntaxError", "Error should have the correct name");
|
is(error.name, "SyntaxError", "Error should have the correct name");
|
||||||
is(
|
is(
|
||||||
error.stack,
|
error.stack,
|
||||||
"receiveMessage@resource://testing-common/TestWindowChild.jsm:33:31\n" +
|
"receiveMessage@resource://testing-common/TestWindowChild.jsm:35:31\n" +
|
||||||
asyncStack,
|
asyncStack,
|
||||||
"Error should have the correct stack"
|
"Error should have the correct stack"
|
||||||
);
|
);
|
||||||
|
|
@ -63,7 +63,7 @@ declTest("sendQuery Exception", {
|
||||||
);
|
);
|
||||||
is(
|
is(
|
||||||
error.stack,
|
error.stack,
|
||||||
"receiveMessage@resource://testing-common/TestWindowChild.jsm:36:22\n" +
|
"receiveMessage@resource://testing-common/TestWindowChild.jsm:38:22\n" +
|
||||||
asyncStack,
|
asyncStack,
|
||||||
"Error should have the correct stack"
|
"Error should have the correct stack"
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,10 @@ async function openPage(enableDialogs) {
|
||||||
const { Services } = ChromeUtils.import(
|
const { Services } = ChromeUtils.import(
|
||||||
"resource://gre/modules/Services.jsm"
|
"resource://gre/modules/Services.jsm"
|
||||||
);
|
);
|
||||||
|
let win = content;
|
||||||
Services.obs.addObserver(doc => {
|
Services.obs.addObserver(doc => {
|
||||||
if (content && doc == content.document) {
|
if (doc == win.document) {
|
||||||
content.windowUtils[name]();
|
win.windowUtils[name]();
|
||||||
}
|
}
|
||||||
}, "document-element-inserted");
|
}, "document-element-inserted");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,11 @@ class ReftestFissionChild extends JSWindowActorChild {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flushWindow(this.contentWindow);
|
// `contentWindow` will be null if the inner window for this actor
|
||||||
|
// has been navigated away from.
|
||||||
|
if (this.contentWindow) {
|
||||||
|
flushWindow(this.contentWindow);
|
||||||
|
}
|
||||||
|
|
||||||
if (anyPendingPaintsGeneratedInDescendants &&
|
if (anyPendingPaintsGeneratedInDescendants &&
|
||||||
!this.contentWindow.windowUtils.isMozAfterPaintPending) {
|
!this.contentWindow.windowUtils.isMozAfterPaintPending) {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["TestWindowChild"];
|
var EXPORTED_SYMBOLS = ["TestWindowChild"];
|
||||||
|
|
||||||
|
var docShellThunks = new Map();
|
||||||
|
|
||||||
class TestWindowChild extends JSWindowActorChild {
|
class TestWindowChild extends JSWindowActorChild {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
@ -41,6 +43,31 @@ class TestWindowChild extends JSWindowActorChild {
|
||||||
case "noncloneReply":
|
case "noncloneReply":
|
||||||
// Return a value which is non-cloneable, like a WindowProxy.
|
// Return a value which is non-cloneable, like a WindowProxy.
|
||||||
return this.contentWindow;
|
return this.contentWindow;
|
||||||
|
case "storeActor":
|
||||||
|
docShellThunks.set(this.docShell, this);
|
||||||
|
break;
|
||||||
|
case "checkActor": {
|
||||||
|
let actor = docShellThunks.get(this.docShell);
|
||||||
|
docShellThunks.delete(this.docShell);
|
||||||
|
|
||||||
|
let contentWindow;
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
contentWindow = actor.contentWindow;
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
return {
|
||||||
|
status: "error",
|
||||||
|
errorType: error.name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
status: "success",
|
||||||
|
valueIsNull: contentWindow === null,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
||||||
|
|
@ -267,10 +267,10 @@ async function submitForm(browser) {
|
||||||
await SpecialPowers.spawn(browser, [], async function() {
|
await SpecialPowers.spawn(browser, [], async function() {
|
||||||
content.document.querySelector("form").submit();
|
content.document.querySelector("form").submit();
|
||||||
|
|
||||||
|
let win = content;
|
||||||
await ContentTaskUtils.waitForCondition(() => {
|
await ContentTaskUtils.waitForCondition(() => {
|
||||||
return (
|
return (
|
||||||
content.location.pathname == "/" &&
|
win.location.pathname == "/" && win.document.readyState == "complete"
|
||||||
content.document.readyState == "complete"
|
|
||||||
);
|
);
|
||||||
}, "Wait for form submission load");
|
}, "Wait for form submission load");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -457,10 +457,11 @@ async function submitForm(browser, action = "") {
|
||||||
info("Submitting form to:" + form.action);
|
info("Submitting form to:" + form.action);
|
||||||
form.submit();
|
form.submit();
|
||||||
|
|
||||||
|
let win = content;
|
||||||
await ContentTaskUtils.waitForCondition(() => {
|
await ContentTaskUtils.waitForCondition(() => {
|
||||||
return (
|
return (
|
||||||
content.location.pathname == actionPathname &&
|
win.location.pathname == actionPathname &&
|
||||||
content.document.readyState == "complete"
|
win.document.readyState == "complete"
|
||||||
);
|
);
|
||||||
}, "Wait for form submission load");
|
}, "Wait for form submission load");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue