mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1611332 - part2 : implement MediaSessionController which is used to update media session and store media metadata. r=chunmin
Create a class `MediaSessionController` which is used to track all alive media sessions within a tab and store their metadata which could be used to show on the virtual media control interface. That class would also be responsible to select an active media session with in a tab. Differential Revision: https://phabricator.services.mozilla.com/D60935 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
da4070cfe8
commit
624272960a
@ -9,6 +9,7 @@
|
||||
|
||||
#include "ContentMediaController.h"
|
||||
#include "MediaEventSource.h"
|
||||
#include "mozilla/dom/MediaSessionController.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
@ -52,9 +53,9 @@ enum class PlaybackState : uint8_t {
|
||||
* tabs playing media at the same time, we can use the ID to query the specific
|
||||
* controller from `MediaControlService`.
|
||||
*/
|
||||
class MediaController final {
|
||||
class MediaController final : public MediaSessionController {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaController);
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaController, override);
|
||||
|
||||
explicit MediaController(uint64_t aContextId);
|
||||
|
||||
|
103
dom/media/mediasession/MediaSessionController.cpp
Normal file
103
dom/media/mediasession/MediaSessionController.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaSessionController.h"
|
||||
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
|
||||
mozilla::LazyLogModule gMediaSession("MediaSession");
|
||||
|
||||
// avoid redefined macro in unified build
|
||||
#undef LOG
|
||||
#define LOG(msg, ...) \
|
||||
MOZ_LOG(gMediaSession, LogLevel::Debug, \
|
||||
("MediaSessionController=%p, " msg, this, ##__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
void MediaSessionController::NotifySessionCreated(uint64_t aSessionContextId) {
|
||||
if (mMetadataMap.Contains(aSessionContextId)) {
|
||||
return;
|
||||
}
|
||||
Maybe<MediaMetadataBase> empty;
|
||||
LOG("Session %" PRId64 " has been created", aSessionContextId);
|
||||
mMetadataMap.Put(aSessionContextId, empty);
|
||||
UpdateActiveMediaSessionContextId();
|
||||
}
|
||||
|
||||
void MediaSessionController::NotifySessionDestroyed(
|
||||
uint64_t aSessionContextId) {
|
||||
if (!mMetadataMap.Contains(aSessionContextId)) {
|
||||
return;
|
||||
}
|
||||
LOG("Session %" PRId64 " has been destroyed", aSessionContextId);
|
||||
mMetadataMap.Remove(aSessionContextId);
|
||||
UpdateActiveMediaSessionContextId();
|
||||
}
|
||||
|
||||
void MediaSessionController::UpdateMetadata(uint64_t aSessionContextId,
|
||||
MediaMetadataBase& aMetadata) {
|
||||
if (!mMetadataMap.Contains(aSessionContextId)) {
|
||||
return;
|
||||
}
|
||||
LOG("Update metadata for session %" PRId64, aSessionContextId);
|
||||
mMetadataMap.GetValue(aSessionContextId)->emplace(aMetadata);
|
||||
}
|
||||
|
||||
void MediaSessionController::UpdateActiveMediaSessionContextId() {
|
||||
// If there is a media session created from top level browsing context, it
|
||||
// would always be chosen as an active media session. Otherwise, we would
|
||||
// check if we have an active media session already. If we do have, it would
|
||||
// still remain as an active session. But if we don't, we would simply choose
|
||||
// arbitrary one as an active session.
|
||||
uint64_t candidateId = 0;
|
||||
if (mActiveMediaSessionContextId &&
|
||||
mMetadataMap.Contains(*mActiveMediaSessionContextId)) {
|
||||
candidateId = *mActiveMediaSessionContextId;
|
||||
}
|
||||
|
||||
for (auto iter = mMetadataMap.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
if (RefPtr<BrowsingContext> bc = BrowsingContext::Get(iter.Key());
|
||||
bc->IsTopContent()) {
|
||||
candidateId = iter.Key();
|
||||
break;
|
||||
}
|
||||
if (!candidateId) {
|
||||
candidateId = iter.Key();
|
||||
}
|
||||
}
|
||||
|
||||
if (mActiveMediaSessionContextId &&
|
||||
*mActiveMediaSessionContextId == candidateId) {
|
||||
LOG("Active session %" PRId64 " keeps unchanged",
|
||||
*mActiveMediaSessionContextId);
|
||||
return;
|
||||
}
|
||||
|
||||
mActiveMediaSessionContextId = Some(candidateId);
|
||||
LOG("Session %" PRId64 " becomes active session",
|
||||
*mActiveMediaSessionContextId);
|
||||
}
|
||||
|
||||
MediaMetadataBase MediaSessionController::CreateDefaultMetadata() const {
|
||||
// TODO : using website's title and favicon as title and arwork to fill out
|
||||
// returned result in bug1611328.
|
||||
return MediaMetadataBase();
|
||||
}
|
||||
|
||||
MediaMetadataBase MediaSessionController::GetCurrentMediaMetadata() const {
|
||||
// If we don't have active media session, or active media session doesn't have
|
||||
// media metadata, then we should create a default metadata which is using
|
||||
// website's title and favicon as artist name and album cover.
|
||||
if (mActiveMediaSessionContextId) {
|
||||
Maybe<MediaMetadataBase> metadata =
|
||||
mMetadataMap.Get(*mActiveMediaSessionContextId);
|
||||
return metadata ? *metadata : CreateDefaultMetadata();
|
||||
}
|
||||
return CreateDefaultMetadata();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
67
dom/media/mediasession/MediaSessionController.h
Normal file
67
dom/media/mediasession/MediaSessionController.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DOM_MEDIA_MEDIASESSION_MEDIASESSIONCONTROLLER_H_
|
||||
#define DOM_MEDIA_MEDIASESSION_MEDIASESSIONCONTROLLER_H_
|
||||
|
||||
#include "mozilla/dom/MediaMetadata.h"
|
||||
#include "mozilla/dom/MediaSessionBinding.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* MediaSessionController is used to track all alive media sessions within a tab
|
||||
* and store their metadata which could be used to show on the virtual media
|
||||
* control interface. In addition, we can use it to get the current media
|
||||
* metadata even if there is no media session existing.
|
||||
*
|
||||
* When media session is created in the content process, we would notify
|
||||
* MediaSessionController in the parent process to tell it in which browsing
|
||||
* context media session is created. If there are multiple media sessions
|
||||
* existing in the same tab, MediaSessionController would take a resbonsibility
|
||||
* to decide which media session should be an active media session. However,
|
||||
* the meaning of active media session here is not equal to the definition from
|
||||
* the spec [1]. We just choose the session which is the active one inside the
|
||||
* tab, the global active media session among different tabs would be selected
|
||||
* in other place, which is related to how we select media controller.
|
||||
*
|
||||
* [1] https://w3c.github.io/mediasession/#active-media-session
|
||||
*/
|
||||
class MediaSessionController {
|
||||
public:
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
|
||||
// Use these functions to ensure that we can track all existing media session
|
||||
// in the same tab when media session is created or destroyed in the content
|
||||
// process.
|
||||
void NotifySessionCreated(uint64_t aSessionContextId);
|
||||
void NotifySessionDestroyed(uint64_t aSessionContextId);
|
||||
|
||||
// Use this function to store the media metadata when media session updated
|
||||
// its metadata in the content process.
|
||||
void UpdateMetadata(uint64_t aSessionContextId, MediaMetadataBase& aMetadata);
|
||||
|
||||
// Return active media session's metadata if active media session exists and
|
||||
// it has already set its metadata. Otherwise, return default media metadata
|
||||
// which is based on website's title and favicon.
|
||||
MediaMetadataBase GetCurrentMediaMetadata() const;
|
||||
|
||||
protected:
|
||||
~MediaSessionController() = default;
|
||||
|
||||
MediaMetadataBase CreateDefaultMetadata() const;
|
||||
void UpdateActiveMediaSessionContextId();
|
||||
|
||||
Maybe<uint64_t> mActiveMediaSessionContextId;
|
||||
nsDataHashtable<nsUint64HashKey, Maybe<MediaMetadataBase>> mMetadataMap;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_MEDIA_MEDIASESSION_MEDIASESSIONCONTROLLER_H_
|
@ -9,11 +9,13 @@ MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
EXPORTS.mozilla.dom += [
|
||||
'MediaMetadata.h',
|
||||
'MediaSession.h',
|
||||
'MediaSessionController.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'MediaMetadata.cpp',
|
||||
'MediaSession.cpp',
|
||||
'MediaSessionController.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
Loading…
Reference in New Issue
Block a user