зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
27b1fa7259
Коммит
3cf334a80a
|
@ -360,10 +360,14 @@ async function unregisterServiceWorker(tab, expectedPageUrl) {
|
|||
async function waitForRegistrationReady(tab, expectedPageUrl) {
|
||||
await asyncWaitUntil(() =>
|
||||
SpecialPowers.spawn(tab.linkedBrowser, [expectedPageUrl], function(_url) {
|
||||
const win = content.wrappedJSObject;
|
||||
const isExpectedUrl = win.location.href === _url;
|
||||
const hasRegistration = !!win.registration;
|
||||
return isExpectedUrl && hasRegistration;
|
||||
try {
|
||||
const win = content.wrappedJSObject;
|
||||
const isExpectedUrl = win.location.href === _url;
|
||||
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"
|
||||
);
|
||||
legacySHistory.removeSHistoryListener(historyListener);
|
||||
delete content._testListener;
|
||||
// 6. Resolve the promise when we got our 'content viewer evicted' event
|
||||
resolve();
|
||||
},
|
||||
|
|
|
@ -125,9 +125,17 @@ nsIDocShell* JSWindowActorChild::GetDocShell(ErrorResult& aRv) {
|
|||
|
||||
Nullable<WindowProxyHolder> JSWindowActorChild::GetContentWindow(
|
||||
ErrorResult& aRv) {
|
||||
if (BrowsingContext* bc = GetBrowsingContext(aRv)) {
|
||||
return WindowProxyHolder(bc);
|
||||
if (!mManager) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (nsGlobalWindowInner* window = mManager->GetWindowGlobal()) {
|
||||
if (window->IsCurrentInnerWindow()) {
|
||||
return WindowProxyHolder(window->GetBrowsingContext());
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_contentWindow.js]
|
||||
[browser_crash_report.js]
|
||||
[browser_destroy_callbacks.js]
|
||||
skip-if = !debug && (os == 'mac') #Bug 1604538
|
||||
|
|
|
@ -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.stack,
|
||||
"receiveMessage@resource://testing-common/TestWindowChild.jsm:33:31\n" +
|
||||
"receiveMessage@resource://testing-common/TestWindowChild.jsm:35:31\n" +
|
||||
asyncStack,
|
||||
"Error should have the correct stack"
|
||||
);
|
||||
|
@ -63,7 +63,7 @@ declTest("sendQuery Exception", {
|
|||
);
|
||||
is(
|
||||
error.stack,
|
||||
"receiveMessage@resource://testing-common/TestWindowChild.jsm:36:22\n" +
|
||||
"receiveMessage@resource://testing-common/TestWindowChild.jsm:38:22\n" +
|
||||
asyncStack,
|
||||
"Error should have the correct stack"
|
||||
);
|
||||
|
|
|
@ -50,9 +50,10 @@ async function openPage(enableDialogs) {
|
|||
const { Services } = ChromeUtils.import(
|
||||
"resource://gre/modules/Services.jsm"
|
||||
);
|
||||
let win = content;
|
||||
Services.obs.addObserver(doc => {
|
||||
if (content && doc == content.document) {
|
||||
content.windowUtils[name]();
|
||||
if (doc == win.document) {
|
||||
win.windowUtils[name]();
|
||||
}
|
||||
}, "document-element-inserted");
|
||||
});
|
||||
|
|
|
@ -8,6 +8,8 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
|
||||
var EXPORTED_SYMBOLS = ["TestWindowChild"];
|
||||
|
||||
var docShellThunks = new Map();
|
||||
|
||||
class TestWindowChild extends JSWindowActorChild {
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -41,6 +43,31 @@ class TestWindowChild extends JSWindowActorChild {
|
|||
case "noncloneReply":
|
||||
// Return a value which is non-cloneable, like a WindowProxy.
|
||||
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;
|
||||
|
|
|
@ -267,10 +267,10 @@ async function submitForm(browser) {
|
|||
await SpecialPowers.spawn(browser, [], async function() {
|
||||
content.document.querySelector("form").submit();
|
||||
|
||||
let win = content;
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return (
|
||||
content.location.pathname == "/" &&
|
||||
content.document.readyState == "complete"
|
||||
win.location.pathname == "/" && win.document.readyState == "complete"
|
||||
);
|
||||
}, "Wait for form submission load");
|
||||
});
|
||||
|
|
|
@ -457,10 +457,11 @@ async function submitForm(browser, action = "") {
|
|||
info("Submitting form to:" + form.action);
|
||||
form.submit();
|
||||
|
||||
let win = content;
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return (
|
||||
content.location.pathname == actionPathname &&
|
||||
content.document.readyState == "complete"
|
||||
win.location.pathname == actionPathname &&
|
||||
win.document.readyState == "complete"
|
||||
);
|
||||
}, "Wait for form submission load");
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче