Bug 1192252 - Add a helper RAII class for managing the cleanup in nsFrameLoader::SwapWithOtherLoader; r=smaug

This commit is contained in:
Ehsan Akhgari 2015-08-07 10:17:50 -04:00
parent 380cdc7d57
commit b5fe53ab03
2 changed files with 58 additions and 32 deletions

View File

@ -951,6 +951,60 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
return NS_OK;
}
class MOZ_STACK_CLASS AutoResetInFrameSwap final
{
public:
AutoResetInFrameSwap(nsFrameLoader* aThisFrameLoader,
nsFrameLoader* aOtherFrameLoader,
nsDocShell* aThisDocShell,
nsDocShell* aOtherDocShell,
EventTarget* aThisEventTarget,
EventTarget* aOtherEventTarget
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mThisFrameLoader(aThisFrameLoader)
, mOtherFrameLoader(aOtherFrameLoader)
, mThisDocShell(aThisDocShell)
, mOtherDocShell(aOtherDocShell)
, mThisEventTarget(aThisEventTarget)
, mOtherEventTarget(aOtherEventTarget)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
mThisFrameLoader->mInSwap = true;
mOtherFrameLoader->mInSwap = true;
mThisDocShell->SetInFrameSwap(true);
mOtherDocShell->SetInFrameSwap(true);
// Fire pageshow events on still-loading pages, and then fire pagehide
// events. Note that we do NOT fire these in the normal way, but just fire
// them on the chrome event handlers.
nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, false);
nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, false);
nsContentUtils::FirePageHideEvent(mThisDocShell, mThisEventTarget);
nsContentUtils::FirePageHideEvent(mOtherDocShell, mOtherEventTarget);
}
~AutoResetInFrameSwap()
{
nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, true);
nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, true);
mThisFrameLoader->mInSwap = false;
mOtherFrameLoader->mInSwap = false;
mThisDocShell->SetInFrameSwap(false);
mOtherDocShell->SetInFrameSwap(false);
}
private:
nsRefPtr<nsFrameLoader> mThisFrameLoader;
nsRefPtr<nsFrameLoader> mOtherFrameLoader;
nsRefPtr<nsDocShell> mThisDocShell;
nsRefPtr<nsDocShell> mOtherDocShell;
nsCOMPtr<EventTarget> mThisEventTarget;
nsCOMPtr<EventTarget> mOtherEventTarget;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
nsresult
nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
nsRefPtr<nsFrameLoader>& aFirstToSwap,
@ -1119,47 +1173,23 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
if (mInSwap || aOther->mInSwap) {
return NS_ERROR_NOT_IMPLEMENTED;
}
mInSwap = aOther->mInSwap = true;
ourDocshell->SetInFrameSwap(true);
otherDocshell->SetInFrameSwap(true);
AutoResetInFrameSwap autoFrameSwap(this, aOther, ourDocshell, otherDocshell,
ourEventTarget, otherEventTarget);
// Fire pageshow events on still-loading pages, and then fire pagehide
// events. Note that we do NOT fire these in the normal way, but just fire
// them on the chrome event handlers.
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, false);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, false);
nsContentUtils::FirePageHideEvent(ourDocshell, ourEventTarget);
nsContentUtils::FirePageHideEvent(otherDocshell, otherEventTarget);
nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
if (!ourFrame || !otherFrame) {
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
mInSwap = aOther->mInSwap = false;
ourDocshell->SetInFrameSwap(false);
otherDocshell->SetInFrameSwap(false);
return NS_ERROR_NOT_IMPLEMENTED;
}
nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
if (!ourFrameFrame) {
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
mInSwap = aOther->mInSwap = false;
ourDocshell->SetInFrameSwap(false);
otherDocshell->SetInFrameSwap(false);
return NS_ERROR_NOT_IMPLEMENTED;
}
// OK. First begin to swap the docshells in the two nsIFrames
rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
if (NS_FAILED(rv)) {
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
mInSwap = aOther->mInSwap = false;
ourDocshell->SetInFrameSwap(false);
otherDocshell->SetInFrameSwap(false);
return rv;
}
@ -1262,12 +1292,6 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
ourParentDocument->FlushPendingNotifications(Flush_Layout);
otherParentDocument->FlushPendingNotifications(Flush_Layout);
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
mInSwap = aOther->mInSwap = false;
ourDocshell->SetInFrameSwap(false);
otherDocshell->SetInFrameSwap(false);
return NS_OK;
}

View File

@ -31,6 +31,7 @@ class nsSubDocumentFrame;
class nsView;
class nsIInProcessContentFrameMessageManager;
class AutoResetInShow;
class AutoResetInFrameSwap;
class nsITabParent;
class nsIDocShellTreeItem;
class nsIDocShellTreeOwner;
@ -59,6 +60,7 @@ class nsFrameLoader final : public nsIFrameLoader,
public mozilla::dom::ipc::MessageManagerCallback
{
friend class AutoResetInShow;
friend class AutoResetInFrameSwap;
typedef mozilla::dom::PBrowserParent PBrowserParent;
typedef mozilla::dom::TabParent TabParent;
typedef mozilla::layout::RenderFrameParent RenderFrameParent;