import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1191491 - Do not dispatch an audio-playback notification when swapping browsers; r=smaug (dacb2ff694)
- Bug 1192252 - Add a helper RAII class for managing the cleanup in nsFrameLoader::SwapWithOtherLoader; r=smaug (362488db65)
This commit is contained in:
2022-02-10 11:06:41 +08:00
parent 156b2fd421
commit 3e6d2379f7
6 changed files with 97 additions and 25 deletions
+14
View File
@@ -782,6 +782,7 @@ nsDocShell::nsDocShell()
, mUseRemoteTabs(false)
, mDeviceSizeIsPageSize(false)
, mWindowDraggingAllowed(false)
, mInFrameSwap(false)
, mCanExecuteScripts(false)
, mFiredUnloadEvent(false)
, mEODForCurrentDocument(false)
@@ -14243,3 +14244,16 @@ nsDocShell::GetPaymentRequestId(nsAString& aPaymentRequestId)
aPaymentRequestId = GetInheritedPaymentRequestId();
return NS_OK;
}
bool
nsDocShell::InFrameSwap()
{
nsRefPtr<nsDocShell> shell = this;
do {
if (shell->mInFrameSwap) {
return true;
}
shell = shell->GetParentDocshell();
} while (shell);
return false;
}
+7
View File
@@ -262,6 +262,12 @@ public:
// is no longer applied
void NotifyAsyncPanZoomStopped();
void SetInFrameSwap(bool aInSwap)
{
mInFrameSwap = aInSwap;
}
bool InFrameSwap();
private:
// An observed docshell wrapper is created when recording markers is enabled.
mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
@@ -910,6 +916,7 @@ protected:
bool mUseRemoteTabs;
bool mDeviceSizeIsPageSize;
bool mWindowDraggingAllowed;
bool mInFrameSwap;
// Because scriptability depends on the mAllowJavascript values of our
// ancestors, we cache the effective scriptability and recompute it when
+58 -24
View File
@@ -939,6 +939,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,
@@ -975,8 +1029,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsIDocShell> ourDocshell = GetExistingDocShell();
nsCOMPtr<nsIDocShell> otherDocshell = aOther->GetExistingDocShell();
nsRefPtr<nsDocShell> ourDocshell = static_cast<nsDocShell*>(GetExistingDocShell());
nsRefPtr<nsDocShell> otherDocshell = static_cast<nsDocShell*>(aOther->GetExistingDocShell());
if (!ourDocshell || !otherDocshell) {
// How odd
return NS_ERROR_NOT_IMPLEMENTED;
@@ -1107,39 +1161,23 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
if (mInSwap || aOther->mInSwap) {
return NS_ERROR_NOT_IMPLEMENTED;
}
mInSwap = aOther->mInSwap = 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) {
mInSwap = aOther->mInSwap = false;
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
return NS_ERROR_NOT_IMPLEMENTED;
}
nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
if (!ourFrameFrame) {
mInSwap = aOther->mInSwap = false;
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
return NS_ERROR_NOT_IMPLEMENTED;
}
// OK. First begin to swap the docshells in the two nsIFrames
rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
if (NS_FAILED(rv)) {
mInSwap = aOther->mInSwap = false;
nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true);
return rv;
}
@@ -1242,10 +1280,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;
return NS_OK;
}
+2
View File
@@ -31,6 +31,7 @@ class nsSubDocumentFrame;
class nsView;
class nsIInProcessContentFrameMessageManager;
class AutoResetInShow;
class AutoResetInFrameSwap;
class nsITabParent;
class nsIDocShellTreeItem;
class nsIDocShellTreeOwner;
@@ -58,6 +59,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;
+9 -1
View File
@@ -102,6 +102,7 @@ static PRLogModuleInfo* gMediaElementEventsLog;
#include "nsIPermissionManager.h"
#include "nsContentTypeParser.h"
#include "nsDocShell.h"
#include "mozilla/EventStateManager.h"
@@ -4016,7 +4017,14 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
if (pauseElement && mAudioChannelAgent) {
// If the element is being paused since we are navigating away from the
// document, notify the audio channel agent.
NotifyAudioChannelAgent(false);
// Be careful to ignore this event during a docshell frame swap.
auto docShell = static_cast<nsDocShell*>(OwnerDoc()->GetDocShell());
if (!docShell) {
return;
}
if (!docShell->InFrameSwap()) {
NotifyAudioChannelAgent(false);
}
}
}
+7
View File
@@ -2429,11 +2429,18 @@ TabChild::RecvSwappedWithOtherRemoteLoader()
return true;
}
nsRefPtr<nsDocShell> docShell = static_cast<nsDocShell*>(ourDocShell.get());
nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
docShell->SetInFrameSwap(true);
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false);
nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget);
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true);
docShell->SetInFrameSwap(false);
return true;
}