Bug 1627999 - part9 : handle the owner browsing context change for the media element. r=chunmin

This patch will do :
- update the media status when media changes its owner browsing context

The advantage of doing so :
- make the media status in `ContextMediaInfo` correcly

More details :
`ContextMediaInfo` stores the media status of each browsing context, but actually the media doesn't always need to stay in one browsing context. We can move it to other browsing contexts (iframe) by appending it to other browsing context's document body.
For example, in [1], we move the video from the main frame to another iframe.

Therefore, when we move the media to a new browsing context, we should also update its media status (controlledMedia/playing/audio number) for its previous owner browsing context.

[1] https://searchfox.org/mozilla-central/source/testing/web-platform/tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html

Differential Revision: https://phabricator.services.mozilla.com/D75477
This commit is contained in:
alwu 2020-05-16 00:26:20 +00:00
Родитель 3c416fbc0a
Коммит 386dc9b342
1 изменённых файлов: 50 добавлений и 4 удалений

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

@ -425,6 +425,7 @@ class HTMLMediaElement::MediaControlEventListener final
// We have already been stopped, do not notify stop twice.
return;
}
NotifyMediaStoppedPlaying();
NotifyPlaybackStateChanged(MediaPlaybackState::eStopped);
// Remove ourselves from media agent, which would stop receiving event.
@ -507,20 +508,62 @@ class HTMLMediaElement::MediaControlEventListener final
}
}
void UpdateOwnerBrowsingContextIfNeeded() {
// Has not notified any information about the owner context yet.
if (!IsStarted()) {
return;
}
BrowsingContext* currentBC = GetCurrentBrowsingContext();
MOZ_ASSERT(currentBC && mOwnerBrowsingContext);
// Still in the same browsing context, no need to update.
if (currentBC == mOwnerBrowsingContext) {
return;
}
MEDIACONTROL_LOG("Change browsing context from %" PRIu64 " to %" PRIu64,
mOwnerBrowsingContext->Id(), currentBC->Id());
// This situation would happen when we start a media in an original browsing
// context, then we move it to another browsing context, such as an iframe,
// so its owner browsing context would be changed. Therefore, we should
// reset the media status for the previous browsing context by calling
// `Stop()`, in which the listener would notify `ePaused` (if it's playing)
// and `eStop`. Then calls `Start()`, in which the listener would notify
// `eStart` to the new browsing context. If the media was playing before,
// we would also notify `ePlayed`.
bool wasInPlayingState = mState == MediaPlaybackState::ePlayed;
Stop();
Unused << Start();
if (wasInPlayingState) {
NotifyMediaStartedPlaying();
}
}
BrowsingContext* GetBrowsingContext() const override {
nsPIDOMWindowInner* window = Owner()->OwnerDoc()->GetInnerWindow();
return window ? window->GetBrowsingContext() : nullptr;
return mOwnerBrowsingContext;
}
private:
~MediaControlEventListener() = default;
// The media can be moved around different browsing context, so this context
// might be different from `mOwnerBrowsingContext` that we use to initialize
// the `ContentMediaAgent`.
BrowsingContext* GetCurrentBrowsingContext() const {
nsPIDOMWindowInner* window = Owner()->OwnerDoc()->GetInnerWindow();
return window ? window->GetBrowsingContext() : nullptr;
}
bool InitMediaAgent() {
MOZ_ASSERT(NS_IsMainThread());
mControlAgent = ContentMediaAgent::Get(GetBrowsingContext());
BrowsingContext* currentBC = GetCurrentBrowsingContext();
mControlAgent = ContentMediaAgent::Get(currentBC);
if (!mControlAgent) {
return false;
}
mOwnerBrowsingContext = currentBC;
MOZ_ASSERT(mOwnerBrowsingContext);
MEDIACONTROL_LOG("Init agent in browsing context %" PRIu64,
mOwnerBrowsingContext->Id());
mControlAgent->AddReceiver(this);
return true;
}
@ -552,6 +595,7 @@ class HTMLMediaElement::MediaControlEventListener final
RefPtr<ContentMediaAgent> mControlAgent;
bool mIsPictureInPictureEnabled = false;
bool mIsOwnerAudible = false;
BrowsingContext* MOZ_NON_OWNING_REF mOwnerBrowsingContext = nullptr;
};
class HTMLMediaElement::MediaStreamTrackListener
@ -4643,6 +4687,9 @@ nsresult HTMLMediaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
}
NotifyDecoderActivityChanges();
if (mMediaControlEventListener) {
mMediaControlEventListener->UpdateOwnerBrowsingContextIfNeeded();
}
return rv;
}
@ -7797,7 +7844,6 @@ void HTMLMediaElement::StartListeningMediaControlEventIfNeeded() {
void HTMLMediaElement::StopListeningMediaControlEventIfNeeded() {
if (mMediaControlEventListener && mMediaControlEventListener->IsStarted()) {
mMediaControlEventListener->NotifyMediaStoppedPlaying();
mMediaControlEventListener->Stop();
}
}