blob: bd202afc53d87b84f18e591638b3f7d5e20fffb3 [file] [log] [blame]
/*
* Copyright (C) 2020-2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if ENABLE(MEDIA_SESSION)
#include "ActiveDOMObject.h"
#include "ExceptionOr.h"
#include "MediaPositionState.h"
#include "MediaSessionAction.h"
#include "MediaSessionActionHandler.h"
#include "MediaSessionPlaybackState.h"
#include "MediaSessionReadyState.h"
#include <wtf/Logger.h>
#include <wtf/MonotonicTime.h>
#include <wtf/UniqueRef.h>
#include <wtf/WeakHashSet.h>
#include <wtf/WeakPtr.h>
namespace WebCore {
class Document;
class HTMLMediaElement;
class MediaMetadata;
class MediaSessionCoordinator;
class MediaSessionCoordinatorPrivate;
class Navigator;
template<typename> class DOMPromiseDeferred;
class MediaSession : public RefCounted<MediaSession>, public ActiveDOMObject, public CanMakeWeakPtr<MediaSession> {
WTF_MAKE_FAST_ALLOCATED;
public:
static Ref<MediaSession> create(Navigator&);
~MediaSession();
MediaMetadata* metadata() const { return m_metadata.get(); };
void setMetadata(RefPtr<MediaMetadata>&&);
void metadataUpdated();
MediaSessionPlaybackState playbackState() const { return m_playbackState; };
void setPlaybackState(MediaSessionPlaybackState);
void setActionHandler(MediaSessionAction, RefPtr<MediaSessionActionHandler>&&);
void callActionHandler(const MediaSessionActionDetails&, DOMPromiseDeferred<void>&&);
ExceptionOr<void> setPositionState(std::optional<MediaPositionState>&&);
std::optional<MediaPositionState> positionState() const { return m_positionState; }
WEBCORE_EXPORT std::optional<double> currentPosition() const;
void willBeginPlayback();
void willPausePlayback();
Document* document() const;
#if ENABLE(MEDIA_SESSION_COORDINATOR)
MediaSessionReadyState readyState() const { return m_readyState; };
void setReadyState(MediaSessionReadyState);
MediaSessionCoordinator& coordinator() const { return m_coordinator.get(); }
#endif
#if ENABLE(MEDIA_SESSION_PLAYLIST)
const Vector<Ref<MediaMetadata>>& playlist() const { return m_playlist; }
ExceptionOr<void> setPlaylist(ScriptExecutionContext&, Vector<RefPtr<MediaMetadata>>&&);
#endif
bool hasActiveActionHandlers() const { return !m_actionHandlers.isEmpty(); }
enum class TriggerGestureIndicator {
No,
Yes,
};
WEBCORE_EXPORT bool callActionHandler(const MediaSessionActionDetails&, TriggerGestureIndicator = TriggerGestureIndicator::Yes);
#if !RELEASE_LOG_DISABLED
const Logger& logger() const { return *m_logger.get(); }
#endif
class Observer : public CanMakeWeakPtr<Observer> {
public:
virtual ~Observer() = default;
virtual void metadataChanged(const RefPtr<MediaMetadata>&) { }
virtual void positionStateChanged(const std::optional<MediaPositionState>&) { }
virtual void playbackStateChanged(MediaSessionPlaybackState) { }
virtual void actionHandlersChanged() { }
#if ENABLE(MEDIA_SESSION_COORDINATOR)
virtual void readyStateChanged(MediaSessionReadyState) { }
#endif
};
void addObserver(Observer&);
void removeObserver(Observer&);
RefPtr<HTMLMediaElement> activeMediaElement() const;
private:
explicit MediaSession(Navigator&);
const void* logIdentifier() const { return m_logIdentifier; }
void updateReportedPosition();
void forEachObserver(const Function<void(Observer&)>&);
void notifyMetadataObservers();
void notifyPositionStateObservers();
void notifyPlaybackStateObservers();
void notifyActionHandlerObservers();
void notifyReadyStateObservers();
// ActiveDOMObject
const char* activeDOMObjectName() const final { return "MediaSession"; }
void suspend(ReasonForSuspension) final;
void stop() final;
WeakPtr<Navigator> m_navigator;
RefPtr<MediaMetadata> m_metadata;
MediaSessionPlaybackState m_playbackState { MediaSessionPlaybackState::None };
std::optional<MediaPositionState> m_positionState;
std::optional<double> m_lastReportedPosition;
MonotonicTime m_timeAtLastPositionUpdate;
HashMap<MediaSessionAction, RefPtr<MediaSessionActionHandler>, IntHash<MediaSessionAction>, WTF::StrongEnumHashTraits<MediaSessionAction>> m_actionHandlers;
RefPtr<const Logger> m_logger;
const void* m_logIdentifier;
WeakHashSet<Observer> m_observers;
#if ENABLE(MEDIA_SESSION_COORDINATOR)
MediaSessionReadyState m_readyState { MediaSessionReadyState::Havenothing };
const Ref<MediaSessionCoordinator> m_coordinator;
#endif
#if ENABLE(MEDIA_SESSION_PLAYLIST)
Vector<Ref<MediaMetadata>> m_playlist;
#endif
};
String convertEnumerationToString(MediaSessionPlaybackState);
String convertEnumerationToString(MediaSessionAction);
}
namespace WTF {
template<> struct LogArgument<WebCore::MediaSessionPlaybackState> {
static String toString(WebCore::MediaSessionPlaybackState state) { return convertEnumerationToString(state); }
};
template<> struct LogArgument<WebCore::MediaSessionAction> {
static String toString(WebCore::MediaSessionAction action) { return convertEnumerationToString(action); }
};
}
#endif // ENABLE(MEDIA_SESSION)