Bug 1361461 - Dispatch the compartment-nuking part of WindowDestroyedEvent to the idle queue; r=smaug

This commit is contained in:
Ehsan Akhgari 2017-05-24 16:08:08 -04:00
Родитель 3f003a3b32
Коммит db983a3ae9
6 изменённых файлов: 83 добавлений и 44 удалений

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

@ -52,7 +52,7 @@ function test() {
gBrowser.removeCurrentTab();
yield TestUtils.topicObserved("outer-window-destroyed", (subject, data) => {
yield TestUtils.topicObserved("outer-window-nuked", (subject, data) => {
let id = subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
return id == winID;
});

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

@ -9628,16 +9628,24 @@ struct BrowserCompartmentMatcher : public js::CompartmentFilter {
};
class WindowDestroyedEvent : public Runnable
class WindowDestroyedEvent final : public Runnable
{
public:
WindowDestroyedEvent(nsIDOMWindow* aWindow, uint64_t aID,
const char* aTopic) :
mID(aID), mTopic(aTopic)
mID(aID),
mPhase(Phase::Destroying),
mTopic(aTopic)
{
mWindow = do_GetWeakReference(aWindow);
}
enum class Phase
{
Destroying,
Nuking
};
NS_IMETHOD Run() override
{
PROFILER_LABEL("WindowDestroyedEvent", "Run",
@ -9645,15 +9653,20 @@ public:
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (observerService) {
if (!observerService) {
return NS_OK;
}
nsCOMPtr<nsISupportsPRUint64> wrapper =
do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
if (wrapper) {
wrapper->SetData(mID);
observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
}
}
switch (mPhase) {
case Phase::Destroying:
{
bool skipNukeCrossCompartment = false;
#ifndef DEBUG
nsCOMPtr<nsIAppStartup> appStartup =
@ -9664,8 +9677,30 @@ public:
}
#endif
if (!skipNukeCrossCompartment) {
// The compartment nuking phase might be too expensive, so do that
// part off of idle dispatch.
// For the compartment nuking phase, we dispatch either an
// inner-window-nuked or an outer-window-nuked notification.
// This will allow tests to wait for compartment nuking to happen.
if (mTopic.EqualsLiteral("inner-window-destroyed")) {
mTopic.AssignLiteral("inner-window-nuked");
} else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
mTopic.AssignLiteral("outer-window-nuked");
}
mPhase = Phase::Nuking;
nsCOMPtr<nsIRunnable> copy(this);
NS_IdleDispatchToCurrentThread(copy.forget());
}
}
break;
case Phase::Nuking:
{
nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
if (!skipNukeCrossCompartment && window) {
if (window) {
nsGlobalWindow* win = nsGlobalWindow::FromSupports(window);
nsGlobalWindow* currentInner = win->IsInnerWindow() ? win : win->GetCurrentInnerWindowInternal();
NS_ENSURE_TRUE(currentInner, NS_OK);
@ -9691,12 +9726,16 @@ public:
}
}
}
}
break;
}
return NS_OK;
}
private:
uint64_t mID;
Phase mPhase;
nsCString mTopic;
nsWeakPtr mWindow;
};

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

@ -13,7 +13,7 @@ add_task(function* test() {
let contentDocDead = yield ContentTask.spawn(browser,{innerWindowId}, function*(args){
let doc = content.document;
let {TestUtils} = Components.utils.import("resource://testing-common/TestUtils.jsm", {});
let promise = TestUtils.topicObserved("inner-window-destroyed", (subject, data) => {
let promise = TestUtils.topicObserved("inner-window-nuked", (subject, data) => {
let id = subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
return id == args.innerWindowId;
});

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

@ -49,7 +49,7 @@ function go() {
// once the window is destroyed.
frame.remove();
TestUtils.topicObserved("outer-window-destroyed", (subject, data) => {
TestUtils.topicObserved("outer-window-nuked", (subject, data) => {
let id = subject.QueryInterface(SpecialPowers.Ci.nsISupportsPRUint64).data;
return id == winID;
}).then(() => {

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

@ -25,11 +25,11 @@ function waitForWindowDestroyed(winID, callback) {
if (id != winID) {
return;
}
SpecialPowers.removeObserver(observer, "outer-window-destroyed");
SpecialPowers.removeObserver(observer, "outer-window-nuked");
SpecialPowers.executeSoon(callback);
}
};
SpecialPowers.addObserver(observer, "outer-window-destroyed");
SpecialPowers.addObserver(observer, "outer-window-nuked");
}
add_task(function* () {

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

@ -61,8 +61,8 @@ add_task(function*() {
webnavB.close();
// Wrappers are destroyed asynchronously, so wait for that to happen.
yield TestUtils.topicObserved("inner-window-destroyed");
// Wrappers are nuked asynchronously, so wait for that to happen.
yield TestUtils.topicObserved("inner-window-nuked");
// Check that it can't be accessed after he window has been closed.
let result = getThing();