mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changesets f63a2cf3fa11 and 7d9a91ee3d48 (bug 1126089) for mochitest-bc failures.
This commit is contained in:
parent
c23816a32e
commit
fa73ab5dc5
@ -25,7 +25,7 @@ const Observer = {
|
||||
start: function () {
|
||||
Services.obs.addObserver(this, 'remote-browser-shown', false);
|
||||
Services.obs.addObserver(this, 'inprocess-browser-shown', false);
|
||||
Services.obs.addObserver(this, 'message-manager-close', false);
|
||||
Services.obs.addObserver(this, 'message-manager-disconnect', false);
|
||||
|
||||
SystemAppProxy.getFrames().forEach(frame => {
|
||||
let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
|
||||
@ -40,7 +40,7 @@ const Observer = {
|
||||
stop: function () {
|
||||
Services.obs.removeObserver(this, 'remote-browser-shown');
|
||||
Services.obs.removeObserver(this, 'inprocess-browser-shown');
|
||||
Services.obs.removeObserver(this, 'message-manager-close');
|
||||
Services.obs.removeObserver(this, 'message-manager-disconnect');
|
||||
this._frames.clear();
|
||||
this._apps.clear();
|
||||
},
|
||||
@ -61,7 +61,7 @@ const Observer = {
|
||||
break;
|
||||
|
||||
// Every time an iframe is destroyed, its message manager also is
|
||||
case 'message-manager-close':
|
||||
case 'message-manager-disconnect':
|
||||
this.onMessageManagerDestroyed(subject);
|
||||
break;
|
||||
}
|
||||
|
@ -684,7 +684,7 @@ this.UITour = {
|
||||
}
|
||||
this.tourBrowsersByWindow.get(window).add(browser);
|
||||
|
||||
Services.obs.addObserver(this, "message-manager-close", false);
|
||||
Services.obs.addObserver(this, "message-manager-disconnect", false);
|
||||
|
||||
window.addEventListener("SSWindowClosing", this);
|
||||
|
||||
@ -736,7 +736,7 @@ this.UITour = {
|
||||
switch (aTopic) {
|
||||
// The browser message manager is disconnected when the <browser> is
|
||||
// destroyed and we want to teardown at that point.
|
||||
case "message-manager-close": {
|
||||
case "message-manager-disconnect": {
|
||||
let winEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (winEnum.hasMoreElements()) {
|
||||
let window = winEnum.getNext();
|
||||
|
@ -7334,14 +7334,14 @@ nsDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer)
|
||||
nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader)
|
||||
{
|
||||
mInitializableFrameLoaders.RemoveElement(aLoader);
|
||||
if (mInDestructor) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mFrameLoaderFinalizers.AppendElement(aFinalizer);
|
||||
mFinalizableFrameLoaders.AppendElement(aLoader);
|
||||
if (!mFrameLoaderRunner) {
|
||||
mFrameLoaderRunner =
|
||||
NS_NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
|
||||
@ -7366,7 +7366,7 @@ nsDocument::MaybeInitializeFinalizeFrameLoaders()
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
if (!mInDestructor && !mFrameLoaderRunner &&
|
||||
(mInitializableFrameLoaders.Length() ||
|
||||
mFrameLoaderFinalizers.Length())) {
|
||||
mFinalizableFrameLoaders.Length())) {
|
||||
mFrameLoaderRunner =
|
||||
NS_NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
|
||||
nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
|
||||
@ -7385,12 +7385,12 @@ nsDocument::MaybeInitializeFinalizeFrameLoaders()
|
||||
loader->ReallyStartLoading();
|
||||
}
|
||||
|
||||
uint32_t length = mFrameLoaderFinalizers.Length();
|
||||
uint32_t length = mFinalizableFrameLoaders.Length();
|
||||
if (length > 0) {
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > finalizers;
|
||||
mFrameLoaderFinalizers.SwapElements(finalizers);
|
||||
nsTArray<nsRefPtr<nsFrameLoader> > loaders;
|
||||
mFinalizableFrameLoaders.SwapElements(loaders);
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
finalizers[i]->Run();
|
||||
loaders[i]->Finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7407,6 +7407,20 @@ nsDocument::TryCancelFrameLoaderInitialization(nsIDocShell* aShell)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell)
|
||||
{
|
||||
if (aShell) {
|
||||
uint32_t length = mFinalizableFrameLoaders.Length();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
if (mFinalizableFrameLoaders[i]->GetExistingDocShell() == aShell) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsDocument::RequestExternalResource(nsIURI* aURI,
|
||||
nsINode* aRequestingNode,
|
||||
|
@ -1033,8 +1033,9 @@ public:
|
||||
virtual void FlushSkinBindings() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) MOZ_OVERRIDE;
|
||||
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer) MOZ_OVERRIDE;
|
||||
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) MOZ_OVERRIDE;
|
||||
virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) MOZ_OVERRIDE;
|
||||
virtual bool FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell) MOZ_OVERRIDE;
|
||||
virtual nsIDocument*
|
||||
RequestExternalResource(nsIURI* aURI,
|
||||
nsINode* aRequestingNode,
|
||||
@ -1767,7 +1768,7 @@ private:
|
||||
nsString mLastStyleSheetSet;
|
||||
|
||||
nsTArray<nsRefPtr<nsFrameLoader> > mInitializableFrameLoaders;
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > mFrameLoaderFinalizers;
|
||||
nsTArray<nsRefPtr<nsFrameLoader> > mFinalizableFrameLoaders;
|
||||
nsRefPtr<nsRunnableMethod<nsDocument> > mFrameLoaderRunner;
|
||||
|
||||
nsRevocableEventPtr<nsRunnableMethod<nsDocument, void, false> >
|
||||
|
@ -107,6 +107,25 @@ using namespace mozilla::layers;
|
||||
using namespace mozilla::layout;
|
||||
typedef FrameMetrics::ViewID ViewID;
|
||||
|
||||
class nsAsyncDocShellDestroyer : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit nsAsyncDocShellDestroyer(nsIDocShell* aDocShell)
|
||||
: mDocShell(aDocShell)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
|
||||
if (base_win) {
|
||||
base_win->Destroy();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<nsIDocShell> mDocShell;
|
||||
};
|
||||
|
||||
// Bug 136580: Limit to the number of nested content frames that can have the
|
||||
// same URL. This is to stop content that is recursively loading
|
||||
// itself. Note that "#foo" on the end of URL doesn't affect
|
||||
@ -162,6 +181,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
|
||||
|
||||
nsFrameLoader::~nsFrameLoader()
|
||||
{
|
||||
mNeedsAsyncDestroy = true;
|
||||
if (mMessageManager) {
|
||||
mMessageManager->Disconnect();
|
||||
}
|
||||
@ -503,6 +523,16 @@ nsFrameLoader::GetDocShell(nsIDocShell **aDocShell)
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::Finalize()
|
||||
{
|
||||
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
|
||||
if (base_win) {
|
||||
base_win->Destroy();
|
||||
}
|
||||
mDocShell = nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
FirePageHideEvent(nsIDocShellTreeItem* aItem,
|
||||
EventTarget* aChromeEventHandler)
|
||||
@ -1328,59 +1358,29 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::DestroyChild()
|
||||
{
|
||||
if (mRemoteBrowser) {
|
||||
mRemoteBrowser->SetOwnerElement(nullptr);
|
||||
mRemoteBrowser->Destroy();
|
||||
mRemoteBrowser = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::Destroy()
|
||||
{
|
||||
StartDestroy();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsFrameLoaderDestroyRunnable : public nsRunnable
|
||||
{
|
||||
enum DestroyPhase
|
||||
{
|
||||
// See the implementation of Run for an explanation of these phases.
|
||||
eDestroyDocShell,
|
||||
eWaitForUnloadMessage,
|
||||
eDestroyComplete
|
||||
};
|
||||
|
||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||
DestroyPhase mPhase;
|
||||
|
||||
public:
|
||||
explicit nsFrameLoaderDestroyRunnable(nsFrameLoader* aFrameLoader)
|
||||
: mFrameLoader(aFrameLoader), mPhase(eDestroyDocShell) {}
|
||||
|
||||
NS_IMETHODIMP Run() MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
void
|
||||
nsFrameLoader::StartDestroy()
|
||||
{
|
||||
// nsFrameLoader::StartDestroy is called just before the frameloader is
|
||||
// detached from the <browser> element. Destruction continues in phases via
|
||||
// the nsFrameLoaderDestroyRunnable.
|
||||
|
||||
if (mDestroyCalled) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
mDestroyCalled = true;
|
||||
|
||||
// After this point, we return an error when trying to send a message using
|
||||
// the message manager on the frame.
|
||||
if (mMessageManager) {
|
||||
mMessageManager->Close();
|
||||
mMessageManager->Disconnect();
|
||||
}
|
||||
|
||||
// Retain references to the <browser> element and the frameloader in case we
|
||||
// receive any messages from the message manager on the frame. These
|
||||
// references are dropped in DestroyComplete.
|
||||
if (mChildMessageManager || mRemoteBrowser) {
|
||||
mOwnerContentStrong = mOwnerContent;
|
||||
if (mRemoteBrowser) {
|
||||
mRemoteBrowser->CacheFrameLoader(this);
|
||||
}
|
||||
if (mChildMessageManager) {
|
||||
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
@ -1392,6 +1392,7 @@ nsFrameLoader::StartDestroy()
|
||||
|
||||
SetOwnerContent(nullptr);
|
||||
}
|
||||
DestroyChild();
|
||||
|
||||
// Seems like this is a dynamic frame removal.
|
||||
if (dynamicSubframeRemoval) {
|
||||
@ -1411,7 +1412,7 @@ nsFrameLoader::StartDestroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Let our window know that we are gone
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsPIDOMWindow> win_private(mDocShell->GetWindow());
|
||||
@ -1420,122 +1421,23 @@ nsFrameLoader::StartDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> destroyRunnable = new nsFrameLoaderDestroyRunnable(this);
|
||||
if (mNeedsAsyncDestroy || !doc ||
|
||||
NS_FAILED(doc->FinalizeFrameLoader(this, destroyRunnable))) {
|
||||
NS_DispatchToCurrentThread(destroyRunnable);
|
||||
if ((mNeedsAsyncDestroy || !doc ||
|
||||
NS_FAILED(doc->FinalizeFrameLoader(this))) && mDocShell) {
|
||||
nsCOMPtr<nsIRunnable> event = new nsAsyncDocShellDestroyer(mDocShell);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_DispatchToCurrentThread(event);
|
||||
|
||||
// Let go of our docshell now that the async destroyer holds on to
|
||||
// the docshell.
|
||||
|
||||
mDocShell = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoaderDestroyRunnable::Run()
|
||||
{
|
||||
switch (mPhase) {
|
||||
case eDestroyDocShell:
|
||||
mFrameLoader->DestroyDocShell();
|
||||
|
||||
// In the out-of-process case, TabParent will eventually call
|
||||
// DestroyComplete once it receives a __delete__ message from the child. In
|
||||
// the in-process case, we dispatch a series of runnables to ensure that
|
||||
// DestroyComplete gets called at the right time. The frame loader is kept
|
||||
// alive by mFrameLoader during this time.
|
||||
if (mFrameLoader->mChildMessageManager) {
|
||||
// When the docshell is destroyed, NotifyWindowIDDestroyed is called to
|
||||
// asynchronously notify {outer,inner}-window-destroyed via a runnable. We
|
||||
// don't want DestroyComplete to run until after those runnables have
|
||||
// run. Since we're enqueueing ourselves after the window-destroyed
|
||||
// runnables are enqueued, we're guaranteed to run after.
|
||||
mPhase = eWaitForUnloadMessage;
|
||||
NS_DispatchToCurrentThread(this);
|
||||
}
|
||||
break;
|
||||
|
||||
case eWaitForUnloadMessage:
|
||||
// The *-window-destroyed observers have finished running at this
|
||||
// point. However, it's possible that a *-window-destroyed observer might
|
||||
// have sent a message using the message manager. These messages might not
|
||||
// have been processed yet. So we enqueue ourselves again to ensure that
|
||||
// DestroyComplete runs after all messages sent by *-window-destroyed
|
||||
// observers have been processed.
|
||||
mPhase = eDestroyComplete;
|
||||
NS_DispatchToCurrentThread(this);
|
||||
break;
|
||||
|
||||
case eDestroyComplete:
|
||||
// Now that all messages sent by unload listeners and window destroyed
|
||||
// observers have been processed, we disconnect the message manager and
|
||||
// finish destruction.
|
||||
mFrameLoader->DestroyComplete();
|
||||
break;
|
||||
}
|
||||
// NOTE: 'this' may very well be gone by now.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::DestroyDocShell()
|
||||
{
|
||||
// This code runs after the frameloader has been detached from the <browser>
|
||||
// element. We postpone this work because we may not be allowed to run
|
||||
// script at that time.
|
||||
|
||||
// Ask the TabChild to fire the frame script "unload" event, destroy its
|
||||
// docshell, and finally destroy the PBrowser actor. This eventually leads to
|
||||
// nsFrameLoader::DestroyComplete being called.
|
||||
if (mRemoteBrowser) {
|
||||
mRemoteBrowser->Destroy();
|
||||
}
|
||||
|
||||
// Fire the "unload" event if we're in-process.
|
||||
if (mChildMessageManager) {
|
||||
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->FireUnloadEvent();
|
||||
}
|
||||
|
||||
// Destroy the docshell.
|
||||
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
|
||||
if (base_win) {
|
||||
base_win->Destroy();
|
||||
}
|
||||
mDocShell = nullptr;
|
||||
|
||||
if (mChildMessageManager) {
|
||||
// Stop handling events in the in-process frame script.
|
||||
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->DisconnectEventListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::DestroyComplete()
|
||||
{
|
||||
// We get here, as part of StartDestroy, after the docshell has been destroyed
|
||||
// and all message manager messages sent during docshell destruction have been
|
||||
// dispatched. We also get here if the child process crashes. In the latter
|
||||
// case, StartDestroy might not have been called.
|
||||
|
||||
// Drop the strong references created in StartDestroy.
|
||||
if (mChildMessageManager || mRemoteBrowser) {
|
||||
mOwnerContentStrong = nullptr;
|
||||
if (mRemoteBrowser) {
|
||||
mRemoteBrowser->CacheFrameLoader(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Call TabParent::Destroy if we haven't already (in case of a crash).
|
||||
if (mRemoteBrowser) {
|
||||
mRemoteBrowser->SetOwnerElement(nullptr);
|
||||
mRemoteBrowser->Destroy();
|
||||
mRemoteBrowser = nullptr;
|
||||
}
|
||||
|
||||
if (mMessageManager) {
|
||||
mMessageManager->Disconnect();
|
||||
}
|
||||
|
||||
if (mChildMessageManager) {
|
||||
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameLoader::GetDepthTooGreat(bool* aDepthTooGreat)
|
||||
{
|
||||
|
@ -78,9 +78,7 @@ public:
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
nsresult CheckForRecursiveLoad(nsIURI* aURI);
|
||||
nsresult ReallyStartLoading();
|
||||
void StartDestroy();
|
||||
void DestroyDocShell();
|
||||
void DestroyComplete();
|
||||
void Finalize();
|
||||
nsIDocShell* GetExistingDocShell() { return mDocShell; }
|
||||
mozilla::dom::EventTarget* GetTabChildGlobalAsEventTarget();
|
||||
nsresult CreateStaticClone(nsIFrameLoader* aDest);
|
||||
@ -321,11 +319,6 @@ private:
|
||||
nsCOMPtr<nsIURI> mURIToLoad;
|
||||
mozilla::dom::Element* mOwnerContent; // WEAK
|
||||
|
||||
// After the frameloader has been removed from the DOM but before all of the
|
||||
// messages from the frame have been received, we keep a strong reference to
|
||||
// our <browser> element.
|
||||
nsRefPtr<mozilla::dom::Element> mOwnerContentStrong;
|
||||
|
||||
// Note: this variable must be modified only by ResetPermissionManagerStatus()
|
||||
uint32_t mAppIdSentToPermissionManager;
|
||||
|
||||
|
@ -301,8 +301,7 @@ SameProcessCpowHolder::ToObject(JSContext* aCx,
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
|
||||
nsIMessageListener* aListener,
|
||||
bool aListenWhenClosed)
|
||||
nsIMessageListener* aListener)
|
||||
{
|
||||
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
|
||||
mListeners.Get(aMessage);
|
||||
@ -321,7 +320,6 @@ nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
|
||||
nsMessageListenerInfo* entry = listeners->AppendElement();
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
entry->mStrongListener = aListener;
|
||||
entry->mListenWhenClosed = aListenWhenClosed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -409,7 +407,6 @@ nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
|
||||
|
||||
nsMessageListenerInfo* entry = listeners->AppendElement();
|
||||
entry->mWeakListener = weak;
|
||||
entry->mListenWhenClosed = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -986,20 +983,6 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
mozilla::jsipc::CpowHolder* aCpows,
|
||||
nsIPrincipal* aPrincipal,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
return ReceiveMessage(aTarget, mClosed, aMessage, aIsSync,
|
||||
aCloneData, aCpows, aPrincipal, aJSONRetVal);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
bool aTargetClosed,
|
||||
const nsAString& aMessage,
|
||||
bool aIsSync,
|
||||
const StructuredCloneData* aCloneData,
|
||||
mozilla::jsipc::CpowHolder* aCpows,
|
||||
nsIPrincipal* aPrincipal,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
|
||||
mListeners.Get(aMessage);
|
||||
@ -1021,10 +1004,6 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
}
|
||||
}
|
||||
|
||||
if (!listener.mListenWhenClosed && aTargetClosed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS;
|
||||
if (weakListener) {
|
||||
wrappedJS = do_QueryInterface(weakListener);
|
||||
@ -1175,7 +1154,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
||||
}
|
||||
}
|
||||
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = mParentManager;
|
||||
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aTargetClosed, aMessage,
|
||||
return mParentManager ? mParentManager->ReceiveMessage(aTarget, aMessage,
|
||||
aIsSync, aCloneData,
|
||||
aCpows, aPrincipal,
|
||||
aJSONRetVal) : NS_OK;
|
||||
@ -1255,27 +1234,9 @@ nsFrameMessageManager::RemoveFromParent()
|
||||
mOwnedCallback = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameMessageManager::Close()
|
||||
{
|
||||
if (!mClosed) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->NotifyObservers(NS_ISUPPORTS_CAST(nsIContentFrameMessageManager*, this),
|
||||
"message-manager-close", nullptr);
|
||||
}
|
||||
}
|
||||
mClosed = true;
|
||||
mCallback = nullptr;
|
||||
mOwnedCallback = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
|
||||
{
|
||||
// Notify message-manager-close if we haven't already.
|
||||
Close();
|
||||
|
||||
if (!mDisconnected) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
@ -1288,6 +1249,8 @@ nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
|
||||
}
|
||||
mDisconnected = true;
|
||||
mParentManager = nullptr;
|
||||
mCallback = nullptr;
|
||||
mOwnedCallback = nullptr;
|
||||
if (!mHandlingMessage) {
|
||||
mListeners.Clear();
|
||||
}
|
||||
|
@ -133,7 +133,6 @@ struct nsMessageListenerInfo
|
||||
// Exactly one of mStrongListener and mWeakListener must be non-null.
|
||||
nsCOMPtr<nsIMessageListener> mStrongListener;
|
||||
nsWeakPtr mWeakListener;
|
||||
bool mListenWhenClosed;
|
||||
};
|
||||
|
||||
|
||||
@ -170,7 +169,6 @@ public:
|
||||
mIsBroadcaster(!!(aFlags & mozilla::dom::ipc::MM_BROADCASTER)),
|
||||
mOwnsCallback(!!(aFlags & mozilla::dom::ipc::MM_OWNSCALLBACK)),
|
||||
mHandlingMessage(false),
|
||||
mClosed(false),
|
||||
mDisconnected(false),
|
||||
mCallback(aCallback),
|
||||
mParentManager(aParentManager)
|
||||
@ -240,7 +238,6 @@ public:
|
||||
mChildManagers.RemoveObject(aManager);
|
||||
}
|
||||
void Disconnect(bool aRemoveFromParent = true);
|
||||
void Close();
|
||||
|
||||
void InitWithCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
|
||||
void SetCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
|
||||
@ -293,11 +290,6 @@ private:
|
||||
JS::MutableHandle<JS::Value> aRetval,
|
||||
bool aIsSync);
|
||||
|
||||
nsresult ReceiveMessage(nsISupports* aTarget, bool aTargetClosed, const nsAString& aMessage,
|
||||
bool aIsSync, const StructuredCloneData* aCloneData,
|
||||
mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
|
||||
InfallibleTArray<nsString>* aJSONRetVal);
|
||||
|
||||
NS_IMETHOD LoadScript(const nsAString& aURL,
|
||||
bool aAllowDelayedLoad,
|
||||
bool aRunInGlobalScope);
|
||||
@ -317,7 +309,6 @@ protected:
|
||||
bool mIsBroadcaster; // true if the message manager is a broadcaster
|
||||
bool mOwnsCallback;
|
||||
bool mHandlingMessage;
|
||||
bool mClosed; // true if we can no longer send messages
|
||||
bool mDisconnected;
|
||||
mozilla::dom::ipc::MessageManagerCallback* mCallback;
|
||||
nsAutoPtr<mozilla::dom::ipc::MessageManagerCallback> mOwnedCallback;
|
||||
|
@ -61,7 +61,6 @@ class nsIObserver;
|
||||
class nsIPresShell;
|
||||
class nsIPrincipal;
|
||||
class nsIRequest;
|
||||
class nsIRunnable;
|
||||
class nsIStreamListener;
|
||||
class nsIStructuredCloneContainer;
|
||||
class nsIStyleRule;
|
||||
@ -1653,9 +1652,11 @@ public:
|
||||
virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) = 0;
|
||||
// In case of failure, the caller must handle the error, for example by
|
||||
// finalizing frame loader asynchronously.
|
||||
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer) = 0;
|
||||
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0;
|
||||
// Removes the frame loader of aShell from the initialization list.
|
||||
virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) = 0;
|
||||
// Returns true if the frame loader of aShell is in the finalization list.
|
||||
virtual bool FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell) = 0;
|
||||
|
||||
/**
|
||||
* Check whether this document is a root document that is not an
|
||||
|
@ -201,7 +201,7 @@ interface nsIMessageListener : nsISupports
|
||||
void receiveMessage();
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(b949bfec-bb7d-47bc-b387-ac6a9b655072)]
|
||||
[scriptable, builtinclass, uuid(aae827bd-acf1-45fe-a556-ea545d4c0804)]
|
||||
interface nsIMessageListenerManager : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -213,16 +213,9 @@ interface nsIMessageListenerManager : nsISupports
|
||||
*
|
||||
* If the same listener registers twice for the same message, the
|
||||
* second registration is ignored.
|
||||
*
|
||||
* Pass true for listenWhenClosed if you want to receive messages
|
||||
* during the short period after a frame has been removed from the
|
||||
* DOM and before its frame script has finished unloading. This
|
||||
* parameter only has an effect for frame message managers in
|
||||
* the main process. Default is false.
|
||||
*/
|
||||
void addMessageListener(in AString messageName,
|
||||
in nsIMessageListener listener,
|
||||
[optional] in boolean listenWhenClosed);
|
||||
in nsIMessageListener listener);
|
||||
|
||||
/**
|
||||
* Undo an |addMessageListener| call -- that is, calling this causes us to no
|
||||
@ -259,7 +252,7 @@ interface nsIMessageListenerManager : nsISupports
|
||||
* messages that are only delivered to its one parent-process message
|
||||
* manager.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(bb5d79e4-e73c-45e7-9651-4d718f4b994c)]
|
||||
[scriptable, builtinclass, uuid(d6b0d851-43e6-426d-9f13-054bc0198175)]
|
||||
interface nsIMessageSender : nsIMessageListenerManager
|
||||
{
|
||||
/**
|
||||
@ -291,7 +284,7 @@ interface nsIMessageSender : nsIMessageListenerManager
|
||||
* manager will broadcast the message to all frame message managers
|
||||
* within its window.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(4d7d62ad-4725-4f39-86cf-8fb22bf9c1d8)]
|
||||
[scriptable, builtinclass, uuid(d36346b9-5d3b-497d-9c28-ffbc3e4f6d0d)]
|
||||
interface nsIMessageBroadcaster : nsIMessageListenerManager
|
||||
{
|
||||
/**
|
||||
@ -318,7 +311,7 @@ interface nsIMessageBroadcaster : nsIMessageListenerManager
|
||||
nsIMessageListenerManager getChildAt(in unsigned long aIndex);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(0e602c9e-1977-422a-a8e4-fe0d4a4f78d0)]
|
||||
[scriptable, builtinclass, uuid(7fda0941-9dcc-448b-bd39-16373c5b4003)]
|
||||
interface nsISyncMessageSender : nsIMessageSender
|
||||
{
|
||||
/**
|
||||
@ -348,7 +341,7 @@ interface nsISyncMessageSender : nsIMessageSender
|
||||
[optional] in nsIPrincipal principal);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(13f3555f-769e-44ea-b607-5239230c3162)]
|
||||
[scriptable, builtinclass, uuid(e04a7ade-c61a-46ec-9f13-efeabedd9d3d)]
|
||||
interface nsIMessageManagerGlobal : nsISyncMessageSender
|
||||
{
|
||||
/**
|
||||
@ -383,13 +376,13 @@ interface nsIContentFrameMessageManager : nsIMessageManagerGlobal
|
||||
readonly attribute nsIDocShell docShell;
|
||||
};
|
||||
|
||||
[uuid(a9e07e89-7125-48e3-bf73-2cbae7fc5b1c)]
|
||||
[uuid(a2325927-9c0c-437d-9215-749c79235031)]
|
||||
interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
|
||||
{
|
||||
[notxpcom] nsIContent getOwnerContent();
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(d0c799a2-d5ff-4a75-acbb-b8c8347944a6)]
|
||||
[scriptable, builtinclass, uuid(9ca95410-b253-11e4-ab27-0800200c9a66)]
|
||||
interface nsIContentProcessMessageManager : nsIMessageManagerGlobal
|
||||
{
|
||||
};
|
||||
|
@ -101,7 +101,6 @@ nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||
nsIContent* aOwner,
|
||||
nsFrameMessageManager* aChrome)
|
||||
: mDocShell(aShell), mInitialized(false), mLoadingScript(false),
|
||||
mPreventEventsEscaping(false),
|
||||
mOwner(aOwner), mChromeMessageManager(aChrome)
|
||||
{
|
||||
SetIsNotDOMBinding();
|
||||
@ -208,24 +207,25 @@ nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
|
||||
}
|
||||
|
||||
void
|
||||
nsInProcessTabChildGlobal::FireUnloadEvent()
|
||||
nsInProcessTabChildGlobal::Disconnect()
|
||||
{
|
||||
// We're called from nsDocument::MaybeInitializeFinalizeFrameLoaders, so it
|
||||
// should be safe to run script.
|
||||
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
||||
|
||||
// Don't let the unload event propagate to chrome event handlers.
|
||||
mPreventEventsEscaping = true;
|
||||
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
|
||||
|
||||
// Allow events fired during docshell destruction (pagehide, unload) to
|
||||
// propagate to the <browser> element since chrome code depends on this.
|
||||
mPreventEventsEscaping = false;
|
||||
// Let the frame scripts know the child is being closed. We do any other
|
||||
// cleanup after the event has been fired. See DelayedDisconnect
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsInProcessTabChildGlobal::DelayedDisconnect)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
nsInProcessTabChildGlobal::DisconnectEventListeners()
|
||||
nsInProcessTabChildGlobal::DelayedDisconnect()
|
||||
{
|
||||
// Don't let the event escape
|
||||
mOwner = nullptr;
|
||||
|
||||
// Fire the "unload" event
|
||||
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
|
||||
|
||||
// Continue with the Disconnect cleanup
|
||||
if (mDocShell) {
|
||||
nsCOMPtr<nsPIDOMWindow> win = mDocShell->GetWindow();
|
||||
if (win) {
|
||||
@ -233,22 +233,15 @@ nsInProcessTabChildGlobal::DisconnectEventListeners()
|
||||
win->SetChromeEventHandler(win->GetChromeEventHandler());
|
||||
}
|
||||
}
|
||||
if (mListenerManager) {
|
||||
mListenerManager->Disconnect();
|
||||
}
|
||||
|
||||
mDocShell = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsInProcessTabChildGlobal::Disconnect()
|
||||
{
|
||||
mChromeMessageManager = nullptr;
|
||||
mOwner = nullptr;
|
||||
if (mMessageManager) {
|
||||
static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
|
||||
mMessageManager = nullptr;
|
||||
}
|
||||
if (mListenerManager) {
|
||||
mListenerManager->Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsIContent *)
|
||||
@ -262,6 +255,18 @@ nsInProcessTabChildGlobal::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = true;
|
||||
|
||||
if (mIsBrowserOrAppFrame &&
|
||||
(!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
|
||||
if (mOwner) {
|
||||
nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow();
|
||||
if (innerWindow) {
|
||||
aVisitor.mParentTarget = innerWindow->GetParentTarget();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
aVisitor.mParentTarget = mOwner;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mOwner) {
|
||||
nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
|
||||
@ -275,23 +280,6 @@ nsInProcessTabChildGlobal::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mPreventEventsEscaping) {
|
||||
aVisitor.mParentTarget = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mIsBrowserOrAppFrame &&
|
||||
(!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
|
||||
if (mOwner) {
|
||||
nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow();
|
||||
if (innerWindow) {
|
||||
aVisitor.mParentTarget = innerWindow->GetParentTarget();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
aVisitor.mParentTarget = mOwner;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
|
||||
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
|
||||
/* vim: set sw=4 ts=8 et 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
|
||||
@ -118,8 +118,6 @@ public:
|
||||
virtual JSContext* GetJSContextForEventHandlers() MOZ_OVERRIDE { return nsContentUtils::GetSafeJSContext(); }
|
||||
virtual nsIPrincipal* GetPrincipal() MOZ_OVERRIDE { return mPrincipal; }
|
||||
void LoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope);
|
||||
void FireUnloadEvent();
|
||||
void DisconnectEventListeners();
|
||||
void Disconnect();
|
||||
void SendMessageToParent(const nsString& aMessage, bool aSync,
|
||||
const nsString& aJSON,
|
||||
@ -139,6 +137,8 @@ public:
|
||||
mChromeMessageManager = aParent;
|
||||
}
|
||||
|
||||
void DelayedDisconnect();
|
||||
|
||||
virtual JSObject* GetGlobalJSObject() MOZ_OVERRIDE {
|
||||
if (!mGlobal) {
|
||||
return nullptr;
|
||||
@ -164,7 +164,6 @@ protected:
|
||||
// <iframe mozapp>? This affects where events get sent, so it affects
|
||||
// PreHandleEvent.
|
||||
bool mIsBrowserOrAppFrame;
|
||||
bool mPreventEventsEscaping;
|
||||
public:
|
||||
nsIContent* mOwner;
|
||||
nsFrameMessageManager* mChromeMessageManager;
|
||||
|
@ -1,15 +1,10 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
file_messagemanager_unload.html
|
||||
|
||||
[browser_bug593387.js]
|
||||
skip-if = e10s # Bug ?????? - test directly touches content (contentWindow.iframe.addEventListener)
|
||||
[browser_bug902350.js]
|
||||
skip-if = e10s # Bug ?????? - test e10s utils don't support load events from iframe etc, which this test relies on.
|
||||
[browser_messagemanager_loadprocessscript.js]
|
||||
[browser_pagehide_on_tab_close.js]
|
||||
skip-if = e10s # this tests non-e10s behavior. it's not expected to work in e10s.
|
||||
[browser_messagemanager_unload.js]
|
||||
[browser_state_notifications.js]
|
||||
# skip-if = e10s # Bug ?????? - content-document-* notifications come while document's URI is still about:blank, but test expects real URL.
|
||||
skip-if = true # Intermittent failures - bug 987493. Restore the skip-if above once fixed
|
||||
|
@ -1,98 +0,0 @@
|
||||
function frameScript()
|
||||
{
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function eventHandler(e) {
|
||||
if (!docShell) {
|
||||
sendAsyncMessage("Test:Fail", "docShell is null");
|
||||
}
|
||||
|
||||
sendAsyncMessage("Test:Event", [e.type, e.target === content.document, e.eventPhase]);
|
||||
}
|
||||
|
||||
let outerID = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils).outerWindowID;
|
||||
function onOuterWindowDestroyed(subject, topic, data) {
|
||||
if (docShell) {
|
||||
sendAsyncMessage("Test:Fail", "docShell is non-null");
|
||||
}
|
||||
|
||||
let id = subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
|
||||
sendAsyncMessage("Test:Event", ["outer-window-destroyed", id == outerID]);
|
||||
if (id == outerID) {
|
||||
Services.obs.removeObserver(onOuterWindowDestroyed, "outer-window-destroyed");
|
||||
}
|
||||
}
|
||||
|
||||
let url = "https://example.com/browser/dom/base/test/file_messagemanager_unload.html";
|
||||
|
||||
content.location = url;
|
||||
addEventListener("load", (e) => {
|
||||
if (e.target.location != url) {
|
||||
return;
|
||||
}
|
||||
|
||||
addEventListener("unload", eventHandler, false);
|
||||
addEventListener("unload", eventHandler, true);
|
||||
addEventListener("pagehide", eventHandler, false);
|
||||
addEventListener("pagehide", eventHandler, true);
|
||||
Services.obs.addObserver(onOuterWindowDestroyed, "outer-window-destroyed", false);
|
||||
|
||||
sendAsyncMessage("Test:Ready");
|
||||
}, true);
|
||||
}
|
||||
|
||||
const EXPECTED = [
|
||||
// Unload events on the TabChildGlobal. These come first so that the
|
||||
// docshell is available.
|
||||
["unload", false, 2],
|
||||
["unload", false, 2],
|
||||
|
||||
// pagehide and unload events for the top-level page.
|
||||
["pagehide", true, 1],
|
||||
["pagehide", true, 3],
|
||||
["unload", true, 1],
|
||||
|
||||
// pagehide and unload events for the iframe.
|
||||
["pagehide", false, 1],
|
||||
["pagehide", false, 3],
|
||||
["unload", false, 1],
|
||||
|
||||
// outer-window-destroyed for both pages.
|
||||
["outer-window-destroyed", false],
|
||||
["outer-window-destroyed", true],
|
||||
];
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var newTab = gBrowser.addTab("about:blank");
|
||||
gBrowser.selectedTab = newTab;
|
||||
|
||||
let browser = newTab.linkedBrowser;
|
||||
|
||||
browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")()", false);
|
||||
|
||||
browser.messageManager.addMessageListener("Test:Fail", (msg) => {
|
||||
ok(false, msg.data);
|
||||
}, true);
|
||||
|
||||
let index = 0;
|
||||
browser.messageManager.addMessageListener("Test:Event", (msg) => {
|
||||
ok(msg.target === browser, "<browser> is correct");
|
||||
|
||||
info(JSON.stringify(msg.data));
|
||||
|
||||
is(JSON.stringify(msg.data), JSON.stringify(EXPECTED[index]), "results match");
|
||||
index++;
|
||||
|
||||
if (index == EXPECTED.length) {
|
||||
finish();
|
||||
}
|
||||
}, true);
|
||||
|
||||
browser.messageManager.addMessageListener("Test:Ready", () => {
|
||||
info("Got ready message");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var tab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function onload() {
|
||||
tab.linkedBrowser.removeEventListener("load", onload);
|
||||
|
||||
tab.linkedBrowser.addEventListener("pagehide", function() {
|
||||
ok(true, "got page hide event");
|
||||
finish();
|
||||
});
|
||||
|
||||
executeSoon(() => { gBrowser.removeTab(tab); });
|
||||
}, true);
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<iframe id="frame" src="about:robots"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -2650,6 +2650,32 @@ TabChild::RecvAppOfflineStatus(const uint32_t& aId, const bool& aOffline)
|
||||
return true;
|
||||
}
|
||||
|
||||
class UnloadScriptEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
UnloadScriptEvent(TabChild* aTabChild, TabChildGlobal* aTabChildGlobal)
|
||||
: mTabChild(aTabChild), mTabChildGlobal(aTabChildGlobal)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
NS_NewDOMEvent(getter_AddRefs(event), mTabChildGlobal, nullptr, nullptr);
|
||||
if (event) {
|
||||
event->InitEvent(NS_LITERAL_STRING("unload"), false, false);
|
||||
event->SetTrusted(true);
|
||||
|
||||
bool dummy;
|
||||
mTabChildGlobal->DispatchEvent(event, &dummy);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<TabChild> mTabChild;
|
||||
TabChildGlobal* mTabChildGlobal;
|
||||
};
|
||||
|
||||
bool
|
||||
TabChild::RecvDestroy()
|
||||
{
|
||||
@ -2657,10 +2683,10 @@ TabChild::RecvDestroy()
|
||||
mDestroyed = true;
|
||||
|
||||
if (mTabChildGlobal) {
|
||||
// Message handlers are called from the event loop, so it better be safe to
|
||||
// run script.
|
||||
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
||||
mTabChildGlobal->DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
|
||||
// Let the frame scripts know the child is being closed
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new UnloadScriptEvent(this, mTabChildGlobal)
|
||||
);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
|
@ -318,12 +318,6 @@ TabParent::RemoveTabParentFromTable(uint64_t aLayersId)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::CacheFrameLoader(nsFrameLoader* aFrameLoader)
|
||||
{
|
||||
mFrameLoader = aFrameLoader;
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::SetOwnerElement(Element* aElement)
|
||||
{
|
||||
@ -413,13 +407,15 @@ TabParent::ActorDestroy(ActorDestroyReason why)
|
||||
if (mIMETabParent == this) {
|
||||
mIMETabParent = nullptr;
|
||||
}
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true);
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
nsRefPtr<nsFrameMessageManager> fmm;
|
||||
if (frameLoader) {
|
||||
fmm = frameLoader->GetFrameMessageManager();
|
||||
nsCOMPtr<Element> frameElement(mFrameElement);
|
||||
ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr,
|
||||
nullptr);
|
||||
frameLoader->DestroyComplete();
|
||||
frameLoader->DestroyChild();
|
||||
|
||||
if (why == AbnormalShutdown && os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, frameLoader),
|
||||
@ -428,13 +424,14 @@ TabParent::ActorDestroy(ActorDestroyReason why)
|
||||
NS_LITERAL_STRING("oop-browser-crashed"),
|
||||
true, true);
|
||||
}
|
||||
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
|
||||
if (os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsITabParent*, this), "ipc:browser-destroyed", nullptr);
|
||||
}
|
||||
if (fmm) {
|
||||
fmm->Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2288,7 +2285,7 @@ TabParent::ReceiveMessage(const nsString& aMessage,
|
||||
nsIPrincipal* aPrincipal,
|
||||
InfallibleTArray<nsString>* aJSONRetVal)
|
||||
{
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true);
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (frameLoader && frameLoader->GetFrameMessageManager()) {
|
||||
nsRefPtr<nsFrameMessageManager> manager =
|
||||
frameLoader->GetFrameMessageManager();
|
||||
@ -2406,16 +2403,8 @@ TabParent::AllowContentIME()
|
||||
}
|
||||
|
||||
already_AddRefed<nsFrameLoader>
|
||||
TabParent::GetFrameLoader(bool aUseCachedFrameLoaderAfterDestroy) const
|
||||
TabParent::GetFrameLoader() const
|
||||
{
|
||||
if (mIsDestroyed && !aUseCachedFrameLoaderAfterDestroy) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mFrameLoader) {
|
||||
nsRefPtr<nsFrameLoader> fl = mFrameLoader;
|
||||
return fl.forget();
|
||||
}
|
||||
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(mFrameElement);
|
||||
return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nullptr;
|
||||
}
|
||||
|
@ -80,8 +80,6 @@ public:
|
||||
Element* GetOwnerElement() const { return mFrameElement; }
|
||||
void SetOwnerElement(Element* aElement);
|
||||
|
||||
void CacheFrameLoader(nsFrameLoader* aFrameLoader);
|
||||
|
||||
/**
|
||||
* Get the mozapptype attribute from this TabParent's owner DOM element.
|
||||
*/
|
||||
@ -454,7 +452,7 @@ protected:
|
||||
bool mUpdatedDimensions;
|
||||
|
||||
private:
|
||||
already_AddRefed<nsFrameLoader> GetFrameLoader(bool aUseCachedFrameLoaderAfterDestroy = false) const;
|
||||
already_AddRefed<nsFrameLoader> GetFrameLoader() const;
|
||||
layout::RenderFrameParent* GetRenderFrame();
|
||||
nsRefPtr<nsIContentParent> mManager;
|
||||
void TryCacheDPIAndScale();
|
||||
@ -496,11 +494,6 @@ private:
|
||||
|
||||
nsCOMPtr<nsILoadContext> mLoadContext;
|
||||
|
||||
// We keep a strong reference to the frameloader after we've sent the
|
||||
// Destroy message and before we've received __delete__. This allows us to
|
||||
// dispatch message manager messages during this time.
|
||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||
|
||||
TabId mTabId;
|
||||
|
||||
// Helper class for RecvCreateWindow.
|
||||
|
@ -48,42 +48,6 @@ function b2gStart() {
|
||||
webNav.loadURI(url, null, null, null, null);
|
||||
}
|
||||
|
||||
let TabDestroyObserver = {
|
||||
outstanding: new Set(),
|
||||
promiseResolver: null,
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "message-manager-close", false);
|
||||
Services.obs.addObserver(this, "message-manager-disconnect", false);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
Services.obs.removeObserver(this, "message-manager-close");
|
||||
Services.obs.removeObserver(this, "message-manager-disconnect");
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
if (topic == "message-manager-close") {
|
||||
this.outstanding.add(subject);
|
||||
} else if (topic == "message-manager-disconnect") {
|
||||
this.outstanding.delete(subject);
|
||||
if (!this.outstanding.size && this.promiseResolver) {
|
||||
this.promiseResolver();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
wait: function() {
|
||||
if (!this.outstanding.size) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.promiseResolver = resolve;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function testInit() {
|
||||
gConfig = readConfig();
|
||||
if (gConfig.testRoot == "browser" ||
|
||||
@ -221,8 +185,6 @@ Tester.prototype = {
|
||||
},
|
||||
|
||||
start: function Tester_start() {
|
||||
TabDestroyObserver.init();
|
||||
|
||||
//if testOnLoad was not called, then gConfig is not defined
|
||||
if (!gConfig)
|
||||
gConfig = readConfig();
|
||||
@ -312,8 +274,6 @@ Tester.prototype = {
|
||||
},
|
||||
|
||||
finish: function Tester_finish(aSkipSummary) {
|
||||
TabDestroyObserver.destroy();
|
||||
|
||||
this.Promise.Debugging.flushUncaughtErrors();
|
||||
|
||||
var passCount = this.tests.reduce(function(a, f) a + f.passCount, 0);
|
||||
@ -623,9 +583,6 @@ Tester.prototype = {
|
||||
Services.obs.notifyObservers({wrappedJSObject: barrier},
|
||||
"shutdown-leaks-before-check", null);
|
||||
|
||||
barrier.client.addBlocker("ShutdownLeaks: Wait for tabs to finish closing",
|
||||
TabDestroyObserver.wait());
|
||||
|
||||
barrier.wait().then(() => {
|
||||
// Simulate memory pressure so that we're forced to free more resources
|
||||
// and thus get rid of more false leaks like already terminated workers.
|
||||
|
@ -713,9 +713,9 @@ var DebuggerServer = {
|
||||
prefix: prefix
|
||||
});
|
||||
|
||||
function onClose() {
|
||||
Services.obs.removeObserver(onMessageManagerClose, "message-manager-close");
|
||||
events.off(aConnection, "closed", onClose);
|
||||
function onDisconnect() {
|
||||
Services.obs.removeObserver(onMessageManagerDisconnect, "message-manager-disconnect");
|
||||
events.off(aConnection, "closed", onDisconnect);
|
||||
if (childTransport) {
|
||||
// If we have a child transport, the actor has already
|
||||
// been created. We need to stop using this message manager.
|
||||
@ -730,16 +730,16 @@ var DebuggerServer = {
|
||||
}
|
||||
}
|
||||
|
||||
let onMessageManagerClose = DevToolsUtils.makeInfallible(function (subject, topic, data) {
|
||||
let onMessageManagerDisconnect = DevToolsUtils.makeInfallible(function (subject, topic, data) {
|
||||
if (subject == aMm) {
|
||||
onClose();
|
||||
onDisconnect();
|
||||
aConnection.send({ from: actor.actor, type: "tabDetached" });
|
||||
}
|
||||
}).bind(this);
|
||||
Services.obs.addObserver(onMessageManagerClose,
|
||||
"message-manager-close", false);
|
||||
Services.obs.addObserver(onMessageManagerDisconnect,
|
||||
"message-manager-disconnect", false);
|
||||
|
||||
events.on(aConnection, "closed", onClose);
|
||||
events.on(aConnection, "closed", onDisconnect);
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
@ -882,9 +882,9 @@ var DebuggerServer = {
|
||||
}).bind(this);
|
||||
mm.addMessageListener("debug:actor", onActorCreated);
|
||||
|
||||
let onMessageManagerClose = DevToolsUtils.makeInfallible(function (subject, topic, data) {
|
||||
let onMessageManagerDisconnect = DevToolsUtils.makeInfallible(function (subject, topic, data) {
|
||||
if (subject == mm) {
|
||||
Services.obs.removeObserver(onMessageManagerClose, topic);
|
||||
Services.obs.removeObserver(onMessageManagerDisconnect, topic);
|
||||
|
||||
// provides hook to actor modules that need to exchange messages
|
||||
// between e10s parent and child processes
|
||||
@ -925,8 +925,8 @@ var DebuggerServer = {
|
||||
}
|
||||
}
|
||||
}).bind(this);
|
||||
Services.obs.addObserver(onMessageManagerClose,
|
||||
"message-manager-close", false);
|
||||
Services.obs.addObserver(onMessageManagerDisconnect,
|
||||
"message-manager-disconnect", false);
|
||||
|
||||
events.once(aConnection, "closed", () => {
|
||||
if (childTransport) {
|
||||
|
Loading…
Reference in New Issue
Block a user