Commit 3194c190 authored by zqzhang's avatar zqzhang Committed by Commit bot

[Blink>MediaSession] Use setActionCallback() instead of event listeners for media control actions

As the MediaSession spec changed from using event-listener-based
to callback-based fashion for media controls, we need to keep the
implementation up to date.

Spec PR:
https://github.com/WICG/mediasession/pull/159

BUG=675963

Review-Url: https://codereview.chromium.org/2589893002
Cr-Commit-Position: refs/heads/master@{#441787}
parent ddded05f
......@@ -48,12 +48,6 @@ PASS window.cached_navigator_connection.onchange is null
PASS window.cached_navigator_connection.ontypechange is null
PASS window.cached_navigator_mediaDevices.ondevicechange is null
PASS window.cached_navigator_mediaSession.metadata is null
PASS window.cached_navigator_mediaSession.onnexttrack is null
PASS window.cached_navigator_mediaSession.onpause is null
PASS window.cached_navigator_mediaSession.onplay is null
PASS window.cached_navigator_mediaSession.onprevioustrack is null
PASS window.cached_navigator_mediaSession.onseekbackward is null
PASS window.cached_navigator_mediaSession.onseekforward is null
PASS window.cached_navigator_mediaSession.playbackState is 'none'
PASS window.cached_navigator_presentation.defaultRequest is null
PASS window.cached_navigator_presentation.receiver is null
......
......@@ -48,12 +48,6 @@ PASS window.cached_navigator_connection.onchange is null
PASS window.cached_navigator_connection.ontypechange is null
PASS window.cached_navigator_mediaDevices.ondevicechange is null
PASS window.cached_navigator_mediaSession.metadata is null
PASS window.cached_navigator_mediaSession.onnexttrack is null
PASS window.cached_navigator_mediaSession.onpause is null
PASS window.cached_navigator_mediaSession.onplay is null
PASS window.cached_navigator_mediaSession.onprevioustrack is null
PASS window.cached_navigator_mediaSession.onseekbackward is null
PASS window.cached_navigator_mediaSession.onseekforward is null
PASS window.cached_navigator_mediaSession.playbackState is 'none'
PASS window.cached_navigator_presentation.defaultRequest is null
PASS window.cached_navigator_presentation.receiver is null
......
......@@ -48,12 +48,6 @@ PASS window.cached_navigator_connection.onchange is null
PASS window.cached_navigator_connection.ontypechange is null
PASS window.cached_navigator_mediaDevices.ondevicechange is null
PASS window.cached_navigator_mediaSession.metadata is null
PASS window.cached_navigator_mediaSession.onnexttrack is null
PASS window.cached_navigator_mediaSession.onpause is null
PASS window.cached_navigator_mediaSession.onplay is null
PASS window.cached_navigator_mediaSession.onprevioustrack is null
PASS window.cached_navigator_mediaSession.onseekbackward is null
PASS window.cached_navigator_mediaSession.onseekforward is null
PASS window.cached_navigator_mediaSession.playbackState is 'none'
PASS window.cached_navigator_presentation.defaultRequest is null
PASS window.cached_navigator_presentation.receiver is null
......
......@@ -50,12 +50,6 @@ PASS oldChildWindow.navigator.language is newChildWindow.navigator.language
PASS oldChildWindow.navigator.maxTouchPoints is newChildWindow.navigator.maxTouchPoints
PASS oldChildWindow.navigator.mediaDevices.ondevicechange is newChildWindow.navigator.mediaDevices.ondevicechange
PASS oldChildWindow.navigator.mediaSession.metadata is newChildWindow.navigator.mediaSession.metadata
PASS oldChildWindow.navigator.mediaSession.onnexttrack is newChildWindow.navigator.mediaSession.onnexttrack
PASS oldChildWindow.navigator.mediaSession.onpause is newChildWindow.navigator.mediaSession.onpause
PASS oldChildWindow.navigator.mediaSession.onplay is newChildWindow.navigator.mediaSession.onplay
PASS oldChildWindow.navigator.mediaSession.onprevioustrack is newChildWindow.navigator.mediaSession.onprevioustrack
PASS oldChildWindow.navigator.mediaSession.onseekbackward is newChildWindow.navigator.mediaSession.onseekbackward
PASS oldChildWindow.navigator.mediaSession.onseekforward is newChildWindow.navigator.mediaSession.onseekforward
PASS oldChildWindow.navigator.mediaSession.playbackState is newChildWindow.navigator.mediaSession.playbackState
PASS oldChildWindow.navigator.onLine is newChildWindow.navigator.onLine
PASS oldChildWindow.navigator.platform is newChildWindow.navigator.platform
......
......@@ -29,12 +29,6 @@ PASS childWindow.navigator.language is window.navigator.language
PASS childWindow.navigator.maxTouchPoints is 0
PASS childWindow.navigator.mediaDevices.ondevicechange is null
PASS childWindow.navigator.mediaSession.metadata is null
PASS childWindow.navigator.mediaSession.onnexttrack is null
PASS childWindow.navigator.mediaSession.onpause is null
PASS childWindow.navigator.mediaSession.onplay is null
PASS childWindow.navigator.mediaSession.onprevioustrack is null
PASS childWindow.navigator.mediaSession.onseekbackward is null
PASS childWindow.navigator.mediaSession.onseekforward is null
PASS childWindow.navigator.mediaSession.playbackState is 'none'
PASS childWindow.navigator.onLine is window.navigator.onLine
PASS childWindow.navigator.platform is window.navigator.platform
......
......@@ -29,12 +29,6 @@ PASS childWindow.navigator.language is window.navigator.language
PASS childWindow.navigator.maxTouchPoints is 0
PASS childWindow.navigator.mediaDevices.ondevicechange is null
PASS childWindow.navigator.mediaSession.metadata is null
PASS childWindow.navigator.mediaSession.onnexttrack is null
PASS childWindow.navigator.mediaSession.onpause is null
PASS childWindow.navigator.mediaSession.onplay is null
PASS childWindow.navigator.mediaSession.onprevioustrack is null
PASS childWindow.navigator.mediaSession.onseekbackward is null
PASS childWindow.navigator.mediaSession.onseekforward is null
PASS childWindow.navigator.mediaSession.playbackState is 'none'
PASS childWindow.navigator.onLine is window.navigator.onLine
PASS childWindow.navigator.platform is window.navigator.platform
......
<!DOCTYPE html>
<title>Test that setting MediaSession event handler should notify the service</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
test(function(t) {
window.navigator.mediaSession.setActionHandler("play", null);
window.navigator.mediaSession.setActionHandler("pause", null);
window.navigator.mediaSession.setActionHandler("previoustrack", null);
window.navigator.mediaSession.setActionHandler("nexttrack", null);
window.navigator.mediaSession.setActionHandler("seekbackward", null);
window.navigator.mediaSession.setActionHandler("seekforward", null);
}, "Test that setActionHandler() can be executed for supported actions");
test(function(t) {
assert_throws(
new TypeError("Failed to execute 'setActionHandler' on 'MediaSession':" +
"The provided value 'invalid' is not a valid enum value" +
"of type MediaSessionAction."),
_ => { window.navigator.mediaSession.setActionHandler("invalid", null); });
}, "Test that setActionHandler() throws exception for unsupported actions");
</script>
<!DOCTYPE html>
<title>Test that setting MediaSession callbacks are alive after garbage-collection</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../../../resources/mojo-helpers.js"></script>
<script src="resources/mediasessionservice-mock.js"></script>
<script src="resources/utils.js"></script>
<script>
var mock;
function gc() {
if (window.GCController) {
GCController.collect();
} else {
for (var i = 0; i < 10000; ++i) {
({ });
}
}
}
async_test(function(t) {
mediaSessionServiceMock.then(m => {
mock = m;
mock.setClientCallback(_ => {
gc();
setTimeout(_ => {
mock.getClient().didReceiveAction(MediaSessionAction.PLAY);
});
});
window.navigator.mediaSession.setActionHandler("play", _ => { t.done(); });
});
});
</script>
......@@ -20,20 +20,26 @@ var expectations = [
var nextExpectation = 0;
function checkExpectation(t, event) {
function checkExpectation(t, action) {
var expectedEvent = expectations[nextExpectation];
assert_equals(expectedEvent, event.type);
assert_equals(expectedEvent, action);
if (++nextExpectation >= expectations.length)
t.done();
}
function runTests(t) {
window.navigator.mediaSession.onplay = t.step_func(checkExpectation.bind(null, t));
window.navigator.mediaSession.onpause = t.step_func(checkExpectation.bind(null, t));
window.navigator.mediaSession.onprevioustrack = t.step_func(checkExpectation.bind(null, t));
window.navigator.mediaSession.onnexttrack = t.step_func(checkExpectation.bind(null, t));
window.navigator.mediaSession.onseekforward = t.step_func(checkExpectation.bind(null, t));
window.navigator.mediaSession.onseekbackward = t.step_func(checkExpectation.bind(null, t));
window.navigator.mediaSession.setActionHandler(
"play", t.step_func(checkExpectation.bind(null, t, "play")));
window.navigator.mediaSession.setActionHandler(
"pause", t.step_func(checkExpectation.bind(null, t, "pause")));
window.navigator.mediaSession.setActionHandler(
"previoustrack", t.step_func(checkExpectation.bind(null, t, "previoustrack")));
window.navigator.mediaSession.setActionHandler(
"nexttrack", t.step_func(checkExpectation.bind(null, t, "nexttrack")));
window.navigator.mediaSession.setActionHandler(
"seekbackward", t.step_func(checkExpectation.bind(null, t, "seekbackward")));
window.navigator.mediaSession.setActionHandler(
"seekforward", t.step_func(checkExpectation.bind(null, t, "seekforward")));
mock.getClient().didReceiveAction(MediaSessionAction.PLAY);
mock.getClient().didReceiveAction(MediaSessionAction.PAUSE);
......
......@@ -22,23 +22,17 @@ function getExpectations() {
[ MediaSessionAction.SEEK_BACKWARD, true ],
[ MediaSessionAction.SEEK_FORWARD, true ],
[ MediaSessionAction.PLAY, false ],
[ MediaSessionAction.PLAY, true ],
[ MediaSessionAction.PAUSE, false ],
[ MediaSessionAction.PAUSE, true ],
[ MediaSessionAction.PREVIOUS_TRACK, false ],
[ MediaSessionAction.PREVIOUS_TRACK, true ],
[ MediaSessionAction.NEXT_TRACK, false ],
[ MediaSessionAction.NEXT_TRACK, true ],
[ MediaSessionAction.SEEK_BACKWARD, false ],
[ MediaSessionAction.SEEK_BACKWARD, true ],
[ MediaSessionAction.SEEK_FORWARD, false ],
[ MediaSessionAction.PLAY, true ],
[ MediaSessionAction.PAUSE, true ],
[ MediaSessionAction.PREVIOUS_TRACK, true ],
[ MediaSessionAction.NEXT_TRACK, true ],
[ MediaSessionAction.SEEK_BACKWARD, true ],
[ MediaSessionAction.SEEK_FORWARD, true ],
[ MediaSessionAction.PLAY, false ],
[ MediaSessionAction.PAUSE, false ],
[ MediaSessionAction.PREVIOUS_TRACK, false ],
[ MediaSessionAction.NEXT_TRACK, false ],
[ MediaSessionAction.SEEK_BACKWARD, false ],
[ MediaSessionAction.SEEK_FORWARD, false ],
];
}
return expectations;
......@@ -55,32 +49,45 @@ async_test(function(t) {
t.done();
}));
// Setting handlers
window.navigator.mediaSession.onresize = _ => {}; // Unknown event.
window.navigator.mediaSession.onplay = _ => {};
window.navigator.mediaSession.onpause = _ => {};
window.navigator.mediaSession.onprevioustrack = _ => {};
window.navigator.mediaSession.onnexttrack = _ => {};
window.navigator.mediaSession.onseekbackward = _ => {};
window.navigator.mediaSession.onseekforward = _ => {};
// Setting handlers should notify the service.
window.navigator.mediaSession.setActionHandler("play", _ => {});
window.navigator.mediaSession.setActionHandler("pause", _ => {});
window.navigator.mediaSession.setActionHandler("previoustrack", _ => {});
window.navigator.mediaSession.setActionHandler("nexttrack", _ => {});
window.navigator.mediaSession.setActionHandler("seekbackward", _ => {});
window.navigator.mediaSession.setActionHandler("seekforward", _ => {});
// Setting handlers again should not notify the service.
window.navigator.mediaSession.setActionHandler("play", _ => {});
window.navigator.mediaSession.setActionHandler("pause", _ => {});
window.navigator.mediaSession.setActionHandler("previoustrack", _ => {});
window.navigator.mediaSession.setActionHandler("nexttrack", _ => {});
window.navigator.mediaSession.setActionHandler("seekbackward", _ => {});
window.navigator.mediaSession.setActionHandler("seekforward", _ => {});
// Unsetting handlers should notify the service.
window.navigator.mediaSession.setActionHandler("play", null);
window.navigator.mediaSession.setActionHandler("pause", null);
window.navigator.mediaSession.setActionHandler("previoustrack", null);
window.navigator.mediaSession.setActionHandler("nexttrack", null);
window.navigator.mediaSession.setActionHandler("seekbackward", null);
window.navigator.mediaSession.setActionHandler("seekforward", null);
// Resetting handlers
window.navigator.mediaSession.onresize = _ => {}; // Unknown event.
window.navigator.mediaSession.onplay = _ => {};
window.navigator.mediaSession.onpause = _ => {};
window.navigator.mediaSession.onprevioustrack = _ => {};
window.navigator.mediaSession.onnexttrack = _ => {};
window.navigator.mediaSession.onseekbackward = _ => {};
window.navigator.mediaSession.onseekforward = _ => {};
// Unsetting handlers should not notify the service.
window.navigator.mediaSession.setActionHandler("play", null);
window.navigator.mediaSession.setActionHandler("pause", null);
window.navigator.mediaSession.setActionHandler("previoustrack", null);
window.navigator.mediaSession.setActionHandler("nexttrack", null);
window.navigator.mediaSession.setActionHandler("seekbackward", null);
window.navigator.mediaSession.setActionHandler("seekforward", null);
// Unsetting handlers
window.navigator.mediaSession.onresize = null; // Unknown event.
window.navigator.mediaSession.onplay = null;
window.navigator.mediaSession.onpause = null;
window.navigator.mediaSession.onprevioustrack = null;
window.navigator.mediaSession.onnexttrack = null;
window.navigator.mediaSession.onseekbackward = null;
window.navigator.mediaSession.onseekforward = null;
// Setting handlers again should notify the service.
window.navigator.mediaSession.setActionHandler("play", _ => {});
window.navigator.mediaSession.setActionHandler("pause", _ => {});
window.navigator.mediaSession.setActionHandler("previoustrack", _ => {});
window.navigator.mediaSession.setActionHandler("nexttrack", _ => {});
window.navigator.mediaSession.setActionHandler("seekbackward", _ => {});
window.navigator.mediaSession.setActionHandler("seekforward", _ => {});
});
}, "test that setting event handler notifies the mojo service");
......
......@@ -3933,21 +3933,10 @@ interface MediaRecorder : EventTarget
interface MediaSession : EventTarget
attribute @@toStringTag
getter metadata
getter onnexttrack
getter onpause
getter onplay
getter onprevioustrack
getter onseekbackward
getter onseekforward
getter playbackState
method constructor
method setActionHandler
setter metadata
setter onnexttrack
setter onpause
setter onplay
setter onprevioustrack
setter onseekbackward
setter onseekforward
setter playbackState
interface MediaSettingsRange
attribute @@toStringTag
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "bindings/modules/v8/V8MediaSession.h"
#include "bindings/core/v8/V8DOMWrapper.h"
#include "modules/mediasession/MediaSession.h"
namespace blink {
void V8MediaSession::visitDOMWrapperCustom(
v8::Isolate* isolate,
ScriptWrappable* scriptWrappable,
const v8::Persistent<v8::Object>& wrapper) {
scriptWrappable->toImpl<MediaSession>()->setV8ReferencesForHandlers(isolate,
wrapper);
}
} // namespace blink
......@@ -9,6 +9,7 @@ bindings_modules_v8_custom_files =
"V8DeviceMotionEventCustom.cpp",
"V8ExtendableMessageEventCustom.cpp",
"V8IDBObserverCustom.cpp",
"V8MediaSessionCustom.cpp",
"V8RemotePlaybackCustom.cpp",
"V8WebGLRenderingContextCustom.cpp",
"V8WebGL2RenderingContextCustom.cpp",
......
......@@ -65,6 +65,8 @@ bindings_modules_generated_union_type_files = [
generated_modules_callback_function_files = [
"$bindings_modules_v8_output_dir/IDBObserverCallback.cpp",
"$bindings_modules_v8_output_dir/IDBObserverCallback.h",
"$bindings_modules_v8_output_dir/MediaSessionActionHandler.cpp",
"$bindings_modules_v8_output_dir/MediaSessionActionHandler.h",
"$bindings_modules_v8_output_dir/RemotePlaybackAvailabilityCallback.cpp",
"$bindings_modules_v8_output_dir/RemotePlaybackAvailabilityCallback.h",
]
......
......@@ -151,7 +151,6 @@ mouseup
mousewheel
mute
negotiationneeded
nexttrack
nomatch
notificationclick
notificationclose
......@@ -170,7 +169,6 @@ paymentrequest
periodicsync
play
playing
playpause
pointercancel
pointerdown
pointerenter
......@@ -182,7 +180,6 @@ pointerout
pointerover
pointerup
popstate
previoustrack
progress
push
ratechange
......@@ -200,9 +197,7 @@ resume
scroll
search
securitypolicyviolation
seekbackward
seeked
seekforward
seeking
select
selectionchange
......
......@@ -14,7 +14,6 @@ modules/indexeddb/IDBOpenDBRequest
modules/indexeddb/IDBRequest
modules/indexeddb/IDBTransaction
modules/mediarecorder/MediaRecorder
modules/mediasession/MediaSession
modules/mediasource/MediaSource
modules/mediasource/SourceBuffer
modules/mediasource/SourceBufferList
......
......@@ -4,12 +4,11 @@
#include "modules/mediasession/MediaSession.h"
#include "bindings/modules/v8/MediaSessionActionHandler.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentUserGestureToken.h"
#include "core/dom/ExecutionContext.h"
#include "core/events/Event.h"
#include "core/frame/LocalFrame.h"
#include "modules/EventTargetModules.h"
#include "modules/mediasession/MediaMetadata.h"
#include "modules/mediasession/MediaMetadataSanitizer.h"
#include "platform/UserGestureIndicator.h"
......@@ -23,39 +22,49 @@ namespace {
using ::blink::mojom::blink::MediaSessionAction;
const AtomicString& mojomActionToEventName(MediaSessionAction action) {
const AtomicString& mojomActionToActionName(MediaSessionAction action) {
DEFINE_STATIC_LOCAL(const AtomicString, playActionName, ("play"));
DEFINE_STATIC_LOCAL(const AtomicString, pauseActionName, ("pause"));
DEFINE_STATIC_LOCAL(const AtomicString, previousTrackActionName,
("previoustrack"));
DEFINE_STATIC_LOCAL(const AtomicString, nextTrackActionName, ("nexttrack"));
DEFINE_STATIC_LOCAL(const AtomicString, seekBackwardActionName,
("seekbackward"));
DEFINE_STATIC_LOCAL(const AtomicString, seekForwardActionName,
("seekforward"));
switch (action) {
case MediaSessionAction::PLAY:
return EventTypeNames::play;
return playActionName;
case MediaSessionAction::PAUSE:
return EventTypeNames::pause;
return pauseActionName;
case MediaSessionAction::PREVIOUS_TRACK:
return EventTypeNames::previoustrack;
return previousTrackActionName;
case MediaSessionAction::NEXT_TRACK:
return EventTypeNames::nexttrack;
return nextTrackActionName;
case MediaSessionAction::SEEK_BACKWARD:
return EventTypeNames::seekbackward;
return seekBackwardActionName;
case MediaSessionAction::SEEK_FORWARD:
return EventTypeNames::seekforward;
return seekForwardActionName;
default:
NOTREACHED();
}
return WTF::emptyAtom;
}
WTF::Optional<MediaSessionAction> eventNameToMojomAction(
const AtomicString& eventName) {
if (EventTypeNames::play == eventName)
WTF::Optional<MediaSessionAction> actionNameToMojomAction(
const String& actionName) {
if ("play" == actionName)
return MediaSessionAction::PLAY;
if (EventTypeNames::pause == eventName)
if ("pause" == actionName)
return MediaSessionAction::PAUSE;
if (EventTypeNames::previoustrack == eventName)
if ("previoustrack" == actionName)
return MediaSessionAction::PREVIOUS_TRACK;
if (EventTypeNames::nexttrack == eventName)
if ("nexttrack" == actionName)
return MediaSessionAction::NEXT_TRACK;
if (EventTypeNames::seekbackward == eventName)
if ("seekbackward" == actionName)
return MediaSessionAction::SEEK_BACKWARD;
if (EventTypeNames::seekforward == eventName)
if ("seekforward" == actionName)
return MediaSessionAction::SEEK_FORWARD;
NOTREACHED();
......@@ -140,12 +149,43 @@ void MediaSession::onMetadataChanged() {
m_metadata, getExecutionContext()));
}
const WTF::AtomicString& MediaSession::interfaceName() const {
return EventTargetNames::MediaSession;
void MediaSession::setActionHandler(const String& action,
MediaSessionActionHandler* handler) {
if (handler) {
auto addResult = m_actionHandlers.set(
action, TraceWrapperMember<MediaSessionActionHandler>(this, handler));
if (!addResult.isNewEntry)
return;
notifyActionChange(action, ActionChangeType::ActionEnabled);
} else {
if (m_actionHandlers.find(action) == m_actionHandlers.end())
return;
m_actionHandlers.remove(action);
notifyActionChange(action, ActionChangeType::ActionDisabled);
}
}
ExecutionContext* MediaSession::getExecutionContext() const {
return ContextClient::getExecutionContext();
void MediaSession::notifyActionChange(const String& action,
ActionChangeType type) {
mojom::blink::MediaSessionService* service = getService();
if (!service)
return;
auto mojomAction = actionNameToMojomAction(action);
DCHECK(mojomAction.has_value());
switch (type) {
case ActionChangeType::ActionEnabled:
service->EnableAction(mojomAction.value());
break;
case ActionChangeType::ActionDisabled:
service->DisableAction(mojomAction.value());
break;
}
}
mojom::blink::MediaSessionService* MediaSession::getService() {
......@@ -171,43 +211,36 @@ mojom::blink::MediaSessionService* MediaSession::getService() {
return m_service.get();
}
bool MediaSession::addEventListenerInternal(
const AtomicString& eventType,
EventListener* listener,
const AddEventListenerOptionsResolved& options) {
if (mojom::blink::MediaSessionService* service = getService()) {
auto mojomAction = eventNameToMojomAction(eventType);
DCHECK(mojomAction.has_value());
service->EnableAction(mojomAction.value());
}
return EventTarget::addEventListenerInternal(eventType, listener, options);
}
bool MediaSession::removeEventListenerInternal(
const AtomicString& eventType,
const EventListener* listener,
const EventListenerOptions& options) {
if (mojom::blink::MediaSessionService* service = getService()) {
auto mojomAction = eventNameToMojomAction(eventType);
DCHECK(mojomAction.has_value());
service->DisableAction(mojomAction.value());
}
return EventTarget::removeEventListenerInternal(eventType, listener, options);
}
void MediaSession::DidReceiveAction(
blink::mojom::blink::MediaSessionAction action) {
DCHECK(getExecutionContext()->isDocument());
Document* document = toDocument(getExecutionContext());
UserGestureIndicator gestureIndicator(
DocumentUserGestureToken::create(document));
dispatchEvent(Event::create(mojomActionToEventName(action)));
auto iter = m_actionHandlers.find(mojomActionToActionName(action));
if (iter == m_actionHandlers.end())
return;
iter->value->call(this);
}
void MediaSession::setV8ReferencesForHandlers(
v8::Isolate* isolate,
const v8::Persistent<v8::Object>& wrapper) {
for (auto handler : m_actionHandlers.values())
handler->setWrapperReference(isolate, wrapper);
}
DEFINE_TRACE(MediaSession) {
visitor->trace(m_metadata);
EventTargetWithInlineData::trace(visitor);
visitor->trace(m_actionHandlers);
ContextClient::trace(visitor);
}
DEFINE_TRACE_WRAPPERS(MediaSession) {
for (auto handler : m_actionHandlers.values())
visitor->traceWrappers(handler);
}
} // namespace blink
......@@ -6,22 +6,25 @@
#define MediaSession_h
#include "bindings/core/v8/ScriptWrappable.h"
#include "bindings/core/v8/TraceWrapperMember.h"
#include "core/dom/ContextLifecycleObserver.h"
#include "core/events/EventTarget.h"
#include "modules/ModulesExport.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "platform/heap/Handle.h"
#include "public/platform/modules/mediasession/media_session.mojom-blink.h"
#include "wtf/text/WTFString.h"
#include <memory>
namespace blink {
class ExecutionContext;
class MediaMetadata;
class MediaSessionActionHandler;
class MODULES_EXPORT MediaSession final
: public EventTargetWithInlineData,
: public GarbageCollectedFinalized<MediaSession>,
public ContextClient,
public ScriptWrappable,
blink::mojom::blink::MediaSessionClient {
USING_GARBAGE_COLLECTED_MIXIN(MediaSession);
DEFINE_WRAPPERTYPEINFO();
......@@ -38,45 +41,41 @@ class MODULES_EXPORT MediaSession final
void setMetadata(MediaMetadata*);
MediaMetadata* metadata() const;
// EventTarget implementation.
const WTF::AtomicString& interfaceName() const override;
ExecutionContext* getExecutionContext() const override;
void setActionHandler(const String& action, MediaSessionActionHandler*);
// Called by the MediaMetadata owned by |this| when it has updates. Also used
// internally when a new MediaMetadata object is set.
void onMetadataChanged();
DEFINE_ATTRIBUTE_EVENT_LISTENER(play);
DEFINE_ATTRIBUTE_EVENT_LISTENER(pause);
DEFINE_ATTRIBUTE_EVENT_LISTENER(previoustrack);
DEFINE_ATTRIBUTE_EVENT_LISTENER(nexttrack);
DEFINE_ATTRIBUTE_EVENT_LISTENER(seekforward);
DEFINE_ATTRIBUTE_EVENT_LISTENER(seekbackward);
DECLARE_VIRTUAL_TRACE();
DECLARE_VIRTUAL_TRACE_WRAPPERS();
private:
friend class V8MediaSession;
friend class MediaSessionTest;
enum class ActionChangeType {
ActionEnabled,
ActionDisabled,
};
explicit MediaSession(ExecutionContext*);
// EventTarget overrides
bool addEventListenerInternal(
const AtomicString& eventType,
EventListener*,
const AddEventListenerOptionsResolved&) override;
bool removeEventListenerInternal(const AtomicString& eventType,
const EventListener*,
const EventListenerOptions&) override;
void notifyActionChange(const String& action, ActionChangeType);
// blink::mojom::blink::MediaSessionClient implementation.
void DidReceiveAction(blink::mojom::blink::MediaSessionAction) override;
void setV8ReferencesForHandlers(v8::Isolate*,
const v8::Persistent<v8::Object>& wrapper);
// Returns null when the ExecutionContext is not document.
mojom::blink::MediaSessionService* getService();
mojom::blink::MediaSessionPlaybackState m_playbackState;
Member<MediaMetadata> m_metadata;
HeapHashMap<String, TraceWrapperMember<MediaSessionActionHandler>>
m_actionHandlers;
mojom::blink::MediaSessionServicePtr m_service;
mojo::Binding<blink::mojom::blink::MediaSessionClient> m_clientBinding;
};
......
......@@ -12,17 +12,24 @@ enum MediaSessionPlaybackState {
// https://wicg.github.io/mediasession/#the-mediasession-interface
enum MediaSessionAction {
"play",
"pause",
"previoustrack",
"nexttrack",
"seekbackward",
"seekforward"
};
callback MediaSessionActionHandler = void ();
[
Custom=VisitDOMWrapper,
RuntimeEnabled=MediaSession,
] interface MediaSession : EventTarget {
attribute MediaMetadata? metadata;
attribute MediaSessionPlaybackState playbackState;
attribute EventHandler onplay;
attribute EventHandler onpause;
attribute EventHandler onprevioustrack;
attribute EventHandler onnexttrack;
attribute EventHandler onseekforward;
attribute EventHandler onseekbackward;
void setActionHandler(MediaSessionAction action,
MediaSessionActionHandler? handler);
};
......@@ -4,7 +4,7 @@
#include "modules/mediasession/NavigatorMediaSession.h"
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "bindings/core/v8/ScriptState.h"
#include "modules/mediasession/MediaSession.h"
#include "platform/Supplementable.h"
......
......@@ -12,6 +12,7 @@
namespace blink {
class Navigator;
class ScriptState;
// Provides MediaSession as a supplement of Navigator as an attribute.
class NavigatorMediaSession final
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment