blob: 6f85142d37e52b0fa82f3e784cedbe75b47d03ab [file] [log] [blame]
// Copyright 2015 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 "modules/mediasession/MediaSession.h"
#include "bindings/core/v8/ScriptState.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"
#include "public/platform/InterfaceProvider.h"
#include "wtf/Optional.h"
#include <memory>
namespace blink {
namespace {
using ::blink::mojom::blink::MediaSessionAction;
const AtomicString& mojomActionToEventName(MediaSessionAction action) {
switch (action) {
case MediaSessionAction::PLAY:
return EventTypeNames::play;
case MediaSessionAction::PAUSE:
return EventTypeNames::pause;
case MediaSessionAction::PLAY_PAUSE:
return EventTypeNames::playpause;
case MediaSessionAction::PREVIOUS_TRACK:
return EventTypeNames::previoustrack;
case MediaSessionAction::NEXT_TRACK:
return EventTypeNames::nexttrack;
case MediaSessionAction::SEEK_BACKWARD:
return EventTypeNames::seekbackward;
case MediaSessionAction::SEEK_FORWARD:
return EventTypeNames::seekforward;
default:
NOTREACHED();
}
return WTF::emptyAtom;
}
WTF::Optional<MediaSessionAction> eventNameToMojomAction(
const AtomicString& eventName) {
if (EventTypeNames::play == eventName)
return MediaSessionAction::PLAY;
if (EventTypeNames::pause == eventName)
return MediaSessionAction::PAUSE;
if (EventTypeNames::playpause == eventName)
return MediaSessionAction::PLAY_PAUSE;
if (EventTypeNames::previoustrack == eventName)
return MediaSessionAction::PREVIOUS_TRACK;
if (EventTypeNames::nexttrack == eventName)
return MediaSessionAction::NEXT_TRACK;
if (EventTypeNames::seekbackward == eventName)
return MediaSessionAction::SEEK_BACKWARD;
if (EventTypeNames::seekforward == eventName)
return MediaSessionAction::SEEK_FORWARD;
NOTREACHED();
return WTF::nullopt;
}
} // anonymous namespace
MediaSession::MediaSession(ScriptState* scriptState)
: m_scriptState(scriptState), m_clientBinding(this) {}
MediaSession* MediaSession::create(ScriptState* scriptState) {
return new MediaSession(scriptState);
}
void MediaSession::dispose() {
m_clientBinding.Close();
}
void MediaSession::setMetadata(MediaMetadata* metadata) {
if (mojom::blink::MediaSessionService* service =
getService(m_scriptState.get())) {
service->SetMetadata(MediaMetadataSanitizer::sanitizeAndConvertToMojo(
metadata, getExecutionContext()));
}
}
MediaMetadata* MediaSession::metadata() const {
return m_metadata;
}
const WTF::AtomicString& MediaSession::interfaceName() const {
return EventTargetNames::MediaSession;
}
ExecutionContext* MediaSession::getExecutionContext() const {
return m_scriptState->getExecutionContext();
}
mojom::blink::MediaSessionService* MediaSession::getService(
ScriptState* scriptState) {
if (m_service)
return m_service.get();
DCHECK(scriptState->getExecutionContext()->isDocument())
<< "MediaSession::getService() is only available from a frame";
Document* document = toDocument(scriptState->getExecutionContext());
if (!document->frame())
return nullptr;
InterfaceProvider* interfaceProvider = document->frame()->interfaceProvider();
if (!interfaceProvider)
return nullptr;
interfaceProvider->getInterface(mojo::GetProxy(&m_service));
if (m_service.get())
m_service->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
return m_service.get();
}
bool MediaSession::addEventListenerInternal(
const AtomicString& eventType,
EventListener* listener,
const AddEventListenerOptionsResolved& options) {
if (mojom::blink::MediaSessionService* service =
getService(m_scriptState.get())) {
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(m_scriptState.get())) {
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)));
}
DEFINE_TRACE(MediaSession) {
visitor->trace(m_metadata);
EventTargetWithInlineData::trace(visitor);
}
} // namespace blink