Bug 1347758 - part1 : window should know whehter there is any alive media component and decide to resume the tab or not.
We should let window decide whether resume the media component, not document.
Because we might have media component which is not in DOM tree, but we still
want to play it.
Window should be resumed when all following conditions are true,
(1) the tab is in the foreground
(2) there is any alive media component (MediaElement/WebAudio/PlugIn...)
(3) the window is blocked (nsISuspendedTypes::SUSPENDED_BLOCK)
MozReview-Commit-ID: JXw5MA4FCxF
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1322,17 +1322,16 @@ nsIDocument::nsIDocument()
mHasHadDefaultView(false),
mStyleSheetChangeEventsEnabled(false),
mIsSrcdocDocument(false),
mDidDocumentOpen(false),
mHasDisplayDocument(false),
mFontFaceSetDirty(true),
mGetUserFontSetCalled(false),
mPostedFlushUserFontSet(false),
- mEverInForeground(false),
mCompatMode(eCompatibility_FullStandards),
mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
mStyleBackendType(StyleBackendType::None),
#ifdef MOZILLA_INTERNAL_API
mVisibilityState(dom::VisibilityState::Hidden),
#else
mDummy(0),
#endif
@@ -1421,18 +1420,16 @@ nsDocument::nsDocument(const char* aCont
MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
// Start out mLastStyleSheetSet as null, per spec
SetDOMStringToNull(mLastStyleSheetSet);
// void state used to differentiate an empty source from an unselected source
mPreloadPictureFoundSource.SetIsVoid(true);
-
- mEverInForeground = false;
}
void
nsDocument::ClearAllBoxObjects()
{
if (mBoxObjectTable) {
for (auto iter = mBoxObjectTable->Iter(); !iter.Done(); iter.Next()) {
nsPIBoxObject* boxObject = iter.UserData();
@@ -12207,29 +12204,20 @@ nsDocument::PostVisibilityUpdateEvent()
nsCOMPtr<nsIRunnable> event =
NewRunnableMethod(this, &nsDocument::UpdateVisibilityState);
Dispatch("nsDocument::UpdateVisibilityState", TaskCategory::Other, event.forget());
}
void
nsDocument::MaybeActiveMediaComponents()
{
- if (mEverInForeground) {
- return;
- }
-
if (!mWindow) {
return;
}
- if (mMediaContent.IsEmpty()) {
- return;
- }
-
- mEverInForeground = true;
GetWindow()->MaybeActiveMediaComponents();
}
NS_IMETHODIMP
nsDocument::GetHidden(bool* aHidden)
{
*aHidden = Hidden();
return NS_OK;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -984,17 +984,18 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMW
mMediaSuspend(Preferences::GetBool("media.block-autoplay-until-in-foreground", true) ?
nsISuspendedTypes::SUSPENDED_BLOCK : nsISuspendedTypes::NONE_SUSPENDED),
mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
mDesktopModeViewport(false), mIsRootOuterWindow(false), mInnerWindow(nullptr),
mOuterWindow(aOuterWindow),
// Make sure no actual window ends up with mWindowID == 0
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
- mLargeAllocStatus(LargeAllocStatus::NONE)
+ mLargeAllocStatus(LargeAllocStatus::NONE),
+ mShouldResumeOnFirstActiveMediaComponent(false)
{
if (aOuterWindow) {
mTimeoutManager =
MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindow::Cast(AsInner()));
}
}
template<class T>
@@ -4343,49 +4344,53 @@ bool
nsPIDOMWindowInner::IsRunningTimeout()
{
return TimeoutManager().IsRunningTimeout();
}
void
nsPIDOMWindowOuter::NotifyCreatedNewMediaComponent()
{
- if (mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) {
- return;
- }
+ // We would only active media component when there is any alive one.
+ mShouldResumeOnFirstActiveMediaComponent = true;
// If the document is already on the foreground but the suspend state is still
// suspend-block, that means the media component was created after calling
// MaybeActiveMediaComponents, so the window's suspend state doesn't be
// changed yet. Therefore, we need to call it again, because the state is only
// changed after there exists alive media within the window.
MaybeActiveMediaComponents();
}
void
nsPIDOMWindowOuter::MaybeActiveMediaComponents()
{
if (IsInnerWindow()) {
return mOuterWindow->MaybeActiveMediaComponents();
}
+ // Resume the media when the tab was blocked and the tab already has
+ // alive media components.
+ if (!mShouldResumeOnFirstActiveMediaComponent ||
+ mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) {
+ return;
+ }
+
nsCOMPtr<nsPIDOMWindowInner> inner = GetCurrentInnerWindow();
if (!inner) {
return;
}
+ // If the document is not visible, don't need to resume it.
nsCOMPtr<nsIDocument> doc = inner->GetExtantDoc();
- if (!doc) {
- return;
- }
-
- if (!doc->Hidden() &&
- mMediaSuspend == nsISuspendedTypes::SUSPENDED_BLOCK) {
- SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED);
- }
+ if (!doc || doc->Hidden()) {
+ return;
+ }
+
+ SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED);
}
SuspendTypes
nsPIDOMWindowOuter::GetMediaSuspend() const
{
if (IsInnerWindow()) {
return mOuterWindow->GetMediaSuspend();
}
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -3181,19 +3181,16 @@ protected:
bool mFontFaceSetDirty : 1;
// Has GetUserFontSet() been called?
bool mGetUserFontSetCalled : 1;
// Do we currently have an event posted to call FlushUserFontSet?
bool mPostedFlushUserFontSet : 1;
- // True is document has ever been in a foreground window.
- bool mEverInForeground : 1;
-
// Compatibility mode
nsCompatibility mCompatMode;
// Our readyState
ReadyState mReadyState;
// Whether this document has (or will have, once we have a pres shell) a
// Gecko- or Servo-backed style system.
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -732,16 +732,20 @@ protected:
uint32_t mMarkedCCGeneration;
// Let the service workers plumbing know that some feature are enabled while
// testing.
bool mServiceWorkersTestingEnabled;
mozilla::dom::LargeAllocStatus mLargeAllocStatus; // Outer window only
+
+ // When there is any created alive media component, we can consider to resume
+ // the media content in the window.
+ bool mShouldResumeOnFirstActiveMediaComponent;
};
#define NS_PIDOMWINDOWINNER_IID \
{ 0x775dabc9, 0x8f43, 0x4277, \
{ 0x9a, 0xdb, 0xf1, 0x99, 0x0d, 0x77, 0xcf, 0xfb } }
#define NS_PIDOMWINDOWOUTER_IID \
{ 0x769693d4, 0xb009, 0x4fe2, \