зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1665527
- part2 : notify media session status based on its document's activity state. r=chunmin
Because of D90771, we need media session to notifty its status correctly in order to deactivate the controller. Therefore, when its document becomes inactive (in bfcahce), we should treat media session as inactive and notify it to `MediaStatusManager` in order to clear the active media session if needed. In addition, add some assertions to ensure we won't modify or set any attributes on media session when its document is inactive. Differential Revision: https://phabricator.services.mozilla.com/D90926
This commit is contained in:
Родитель
2e937ee7bb
Коммит
ad52a54195
|
@ -27,12 +27,40 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaSession)
|
|||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaSession)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaSession)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentActivity)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
MediaSession::MediaSession(nsPIDOMWindowInner* aParent) : mParent(aParent) {
|
||||
MediaSession::MediaSession(nsPIDOMWindowInner* aParent)
|
||||
: mParent(aParent), mDoc(mParent->GetExtantDoc()) {
|
||||
MOZ_ASSERT(mParent);
|
||||
NotifyMediaSessionStatus(SessionStatus::eCreated);
|
||||
MOZ_ASSERT(mDoc);
|
||||
mDoc->RegisterActivityObserver(this);
|
||||
if (mDoc->IsCurrentActiveDocument()) {
|
||||
SetMediaSessionDocStatus(SessionDocStatus::eActive);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaSession::Shutdown() {
|
||||
mDoc->UnregisterActivityObserver(this);
|
||||
SetMediaSessionDocStatus(SessionDocStatus::eInactive);
|
||||
}
|
||||
|
||||
void MediaSession::NotifyOwnerDocumentActivityChanged() {
|
||||
const bool isDocActive = mDoc->IsCurrentActiveDocument();
|
||||
LOG("Document activity changed, isActive=%d", isDocActive);
|
||||
if (isDocActive) {
|
||||
SetMediaSessionDocStatus(SessionDocStatus::eActive);
|
||||
} else {
|
||||
SetMediaSessionDocStatus(SessionDocStatus::eInactive);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaSession::SetMediaSessionDocStatus(SessionDocStatus aState) {
|
||||
if (mSessionDocState == aState) {
|
||||
return;
|
||||
}
|
||||
mSessionDocState = aState;
|
||||
NotifyMediaSessionDocStatus(mSessionDocState);
|
||||
}
|
||||
|
||||
nsPIDOMWindowInner* MediaSession::GetParentObject() const { return mParent; }
|
||||
|
@ -45,12 +73,14 @@ JSObject* MediaSession::WrapObject(JSContext* aCx,
|
|||
MediaMetadata* MediaSession::GetMetadata() const { return mMediaMetadata; }
|
||||
|
||||
void MediaSession::SetMetadata(MediaMetadata* aMetadata) {
|
||||
MOZ_ASSERT(mSessionDocState == SessionDocStatus::eActive);
|
||||
mMediaMetadata = aMetadata;
|
||||
NotifyMetadataUpdated();
|
||||
}
|
||||
|
||||
void MediaSession::SetPlaybackState(
|
||||
const MediaSessionPlaybackState& aPlaybackState) {
|
||||
MOZ_ASSERT(mSessionDocState == SessionDocStatus::eActive);
|
||||
if (mDeclaredPlaybackState == aPlaybackState) {
|
||||
return;
|
||||
}
|
||||
|
@ -70,6 +100,7 @@ MediaSessionPlaybackState MediaSession::PlaybackState() const {
|
|||
|
||||
void MediaSession::SetActionHandler(MediaSessionAction aAction,
|
||||
MediaSessionActionHandler* aHandler) {
|
||||
MOZ_ASSERT(mSessionDocState == SessionDocStatus::eActive);
|
||||
MOZ_ASSERT(size_t(aAction) < ArrayLength(mActionHandlers));
|
||||
// If the media session changes its supported action, then we would propagate
|
||||
// this information to the chrome process in order to run the media session
|
||||
|
@ -92,6 +123,7 @@ MediaSessionActionHandler* MediaSession::GetActionHandler(
|
|||
|
||||
void MediaSession::SetPositionState(const MediaPositionState& aState,
|
||||
ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mSessionDocState == SessionDocStatus::eActive);
|
||||
// https://w3c.github.io/mediasession/#dom-mediasession-setpositionstate
|
||||
// If the state is an empty dictionary then clear the position state.
|
||||
if (!aState.IsAnyMemberPresent()) {
|
||||
|
@ -190,11 +222,7 @@ bool MediaSession::IsActive() const {
|
|||
return *activeSessionContextId == currentBC->Id();
|
||||
}
|
||||
|
||||
void MediaSession::Shutdown() {
|
||||
NotifyMediaSessionStatus(SessionStatus::eDestroyed);
|
||||
}
|
||||
|
||||
void MediaSession::NotifyMediaSessionStatus(SessionStatus aState) {
|
||||
void MediaSession::NotifyMediaSessionDocStatus(SessionDocStatus aState) {
|
||||
RefPtr<BrowsingContext> currentBC = GetParentObject()->GetBrowsingContext();
|
||||
MOZ_ASSERT(currentBC, "Update session status after context destroyed!");
|
||||
|
||||
|
@ -202,7 +230,7 @@ void MediaSession::NotifyMediaSessionStatus(SessionStatus aState) {
|
|||
if (!updater) {
|
||||
return;
|
||||
}
|
||||
if (aState == SessionStatus::eCreated) {
|
||||
if (aState == SessionDocStatus::eActive) {
|
||||
updater->NotifySessionCreated(currentBC->Id());
|
||||
} else {
|
||||
updater->NotifySessionDestroyed(currentBC->Id());
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDocumentActivity.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
class nsPIDOMWindowInner;
|
||||
|
@ -35,11 +36,12 @@ struct PositionState {
|
|||
double mLastReportedPlaybackPosition;
|
||||
};
|
||||
|
||||
class MediaSession final : public nsISupports, public nsWrapperCache {
|
||||
class MediaSession final : public nsIDocumentActivity, public nsWrapperCache {
|
||||
public:
|
||||
// Ref counting and cycle collection
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaSession)
|
||||
NS_DECL_NSIDOCUMENTACTIVITY
|
||||
|
||||
explicit MediaSession(nsPIDOMWindowInner* aParent);
|
||||
|
||||
|
@ -78,16 +80,18 @@ class MediaSession final : public nsISupports, public nsWrapperCache {
|
|||
bool IsActive() const;
|
||||
|
||||
private:
|
||||
// Propagate media context status to the media session controller in the
|
||||
// chrome process when we create or destroy the media session.
|
||||
enum class SessionStatus : bool {
|
||||
eDestroyed = false,
|
||||
eCreated = true,
|
||||
// When the document which media session belongs to is going to be destroyed,
|
||||
// or is in the bfcache, then the session would be inactive. Otherwise, it's
|
||||
// active all the time.
|
||||
enum class SessionDocStatus : bool {
|
||||
eInactive = false,
|
||||
eActive = true,
|
||||
};
|
||||
void SetMediaSessionDocStatus(SessionDocStatus aState);
|
||||
|
||||
// These methods are used to propagate media session's status to the chrome
|
||||
// process.
|
||||
void NotifyMediaSessionStatus(SessionStatus aState);
|
||||
void NotifyMediaSessionDocStatus(SessionDocStatus aState);
|
||||
void NotifyMetadataUpdated();
|
||||
void NotifyEnableSupportedAction(MediaSessionAction aAction);
|
||||
void NotifyDisableSupportedAction(MediaSessionAction aAction);
|
||||
|
@ -114,6 +118,8 @@ class MediaSession final : public nsISupports, public nsWrapperCache {
|
|||
MediaSessionPlaybackState::None;
|
||||
|
||||
Maybe<PositionState> mPositionState;
|
||||
RefPtr<Document> mDoc;
|
||||
SessionDocStatus mSessionDocState = SessionDocStatus::eInactive;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
Загрузка…
Ссылка в новой задаче