From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- dom/media/mediasession/MediaSession.cpp | 30 ++++- dom/media/mediasession/MediaSession.h | 22 ++-- dom/media/mediasession/MediaSessionIPCUtils.h | 17 ++- dom/media/mediasession/moz.build | 4 + .../mediasession/test/gtest/TestPositionState.cpp | 127 +++++++++++++++++++++ dom/media/mediasession/test/gtest/moz.build | 15 +++ 6 files changed, 196 insertions(+), 19 deletions(-) create mode 100644 dom/media/mediasession/test/gtest/TestPositionState.cpp create mode 100644 dom/media/mediasession/test/gtest/moz.build (limited to 'dom/media/mediasession') diff --git a/dom/media/mediasession/MediaSession.cpp b/dom/media/mediasession/MediaSession.cpp index e55fa28d96..9120aa5379 100644 --- a/dom/media/mediasession/MediaSession.cpp +++ b/dom/media/mediasession/MediaSession.cpp @@ -20,6 +20,29 @@ namespace mozilla::dom { +double PositionState::CurrentPlaybackPosition(TimeStamp aNow) const { + // https://w3c.github.io/mediasession/#current-playback-position + + // Set time elapsed to the system time in seconds minus the last position + // updated time. + auto timeElapsed = aNow - mPositionUpdatedTime; + // Mutliply time elapsed with actual playback rate. + timeElapsed = timeElapsed.MultDouble(mPlaybackRate); + // Set position to time elapsed added to last reported playback position. + auto position = timeElapsed.ToSeconds() + mLastReportedPlaybackPosition; + + // If position is less than zero, return zero. + if (position < 0.0) { + return 0.0; + } + // If position is greater than duration, return duration. + if (position > mDuration) { + return mDuration; + } + // Return position. + return position; +} + // We don't use NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE because we need to // unregister MediaSession from document's activity listeners. NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(MediaSession) @@ -138,6 +161,7 @@ void MediaSession::SetPositionState(const MediaPositionState& aState, // If the state is an empty dictionary then clear the position state. if (!aState.IsAnyMemberPresent()) { mPositionState.reset(); + NotifyPositionStateChanged(); return; } @@ -175,8 +199,8 @@ void MediaSession::SetPositionState(const MediaPositionState& aState, // Update the position state and last position updated time. MOZ_ASSERT(aState.mDuration.WasPassed()); - mPositionState = - Some(PositionState(aState.mDuration.Value(), playbackRate, position)); + mPositionState = Some(PositionState(aState.mDuration.Value(), playbackRate, + position, TimeStamp::Now())); NotifyPositionStateChanged(); } @@ -328,7 +352,7 @@ void MediaSession::NotifyPositionStateChanged() { RefPtr currentBC = GetParentObject()->GetBrowsingContext(); MOZ_ASSERT(currentBC, "Update action after context destroyed!"); if (RefPtr updater = ContentMediaAgent::Get(currentBC)) { - updater->UpdatePositionState(currentBC->Id(), *mPositionState); + updater->UpdatePositionState(currentBC->Id(), mPositionState); } } diff --git a/dom/media/mediasession/MediaSession.h b/dom/media/mediasession/MediaSession.h index db6864c842..6784fb531f 100644 --- a/dom/media/mediasession/MediaSession.h +++ b/dom/media/mediasession/MediaSession.h @@ -11,6 +11,7 @@ #include "mozilla/Attributes.h" #include "mozilla/dom/MediaSessionBinding.h" #include "mozilla/EnumeratedArray.h" +#include "mozilla/TimeStamp.h" #include "nsCycleCollectionParticipant.h" #include "nsIDocumentActivity.h" #include "nsWrapperCache.h" @@ -29,13 +30,21 @@ class MediaMetadata; struct PositionState { PositionState() = default; PositionState(double aDuration, double aPlaybackRate, - double aLastReportedTime) + double aLastReportedTime, TimeStamp aPositionUpdatedTime) : mDuration(aDuration), mPlaybackRate(aPlaybackRate), - mLastReportedPlaybackPosition(aLastReportedTime) {} - double mDuration; - double mPlaybackRate; - double mLastReportedPlaybackPosition; + mLastReportedPlaybackPosition(aLastReportedTime), + mPositionUpdatedTime(aPositionUpdatedTime) {} + + double mDuration = 0.0; + double mPlaybackRate = 0.0; + double mLastReportedPlaybackPosition = 0.0; + TimeStamp mPositionUpdatedTime; + + // Returns the playback position in seconds (from 0 to mDuration) + // at the current time (aNow). + // https://w3c.github.io/mediasession/#current-playback-position + double CurrentPlaybackPosition(TimeStamp aNow = TimeStamp::Now()) const; }; class MediaSession final : public nsIDocumentActivity, public nsWrapperCache { @@ -111,8 +120,7 @@ class MediaSession final : public nsIDocumentActivity, public nsWrapperCache { RefPtr mMediaMetadata; - EnumeratedArray> + EnumeratedArray> mActionHandlers; // This is used as is a hint for the user agent to determine whether the diff --git a/dom/media/mediasession/MediaSessionIPCUtils.h b/dom/media/mediasession/MediaSessionIPCUtils.h index c44f4b4553..610b123b6c 100644 --- a/dom/media/mediasession/MediaSessionIPCUtils.h +++ b/dom/media/mediasession/MediaSessionIPCUtils.h @@ -6,6 +6,7 @@ #define DOM_MEDIA_MEDIASESSION_MEDIASESSIONIPCUTILS_H_ #include "ipc/EnumSerializer.h" +#include "mozilla/dom/BindingIPCUtils.h" #include "MediaMetadata.h" #include "mozilla/dom/MediaSession.h" #include "mozilla/dom/MediaSessionBinding.h" @@ -71,12 +72,14 @@ struct ParamTraits { WriteParam(aWriter, aParam.mDuration); WriteParam(aWriter, aParam.mPlaybackRate); WriteParam(aWriter, aParam.mLastReportedPlaybackPosition); + WriteParam(aWriter, aParam.mPositionUpdatedTime); } static bool Read(MessageReader* aReader, paramType* aResult) { if (!ReadParam(aReader, &(aResult->mDuration)) || !ReadParam(aReader, &(aResult->mPlaybackRate)) || - !ReadParam(aReader, &(aResult->mLastReportedPlaybackPosition))) { + !ReadParam(aReader, &(aResult->mLastReportedPlaybackPosition)) || + !ReadParam(aReader, &(aResult->mPositionUpdatedTime))) { return false; } return true; @@ -85,17 +88,13 @@ struct ParamTraits { template <> struct ParamTraits - : public ContiguousEnumSerializer< - mozilla::dom::MediaSessionPlaybackState, - mozilla::dom::MediaSessionPlaybackState::None, - mozilla::dom::MediaSessionPlaybackState::EndGuard_> {}; + : public mozilla::dom::WebIDLEnumSerializer< + mozilla::dom::MediaSessionPlaybackState> {}; template <> struct ParamTraits - : public ContiguousEnumSerializer< - mozilla::dom::MediaSessionAction, - mozilla::dom::MediaSessionAction::Play, - mozilla::dom::MediaSessionAction::EndGuard_> {}; + : public mozilla::dom::WebIDLEnumSerializer< + mozilla::dom::MediaSessionAction> {}; } // namespace IPC diff --git a/dom/media/mediasession/moz.build b/dom/media/mediasession/moz.build index 805bf67971..70f69fc14f 100644 --- a/dom/media/mediasession/moz.build +++ b/dom/media/mediasession/moz.build @@ -6,6 +6,10 @@ MOCHITEST_MANIFESTS += ["test/mochitest.toml"] +TEST_DIRS += [ + "test/gtest", +] + EXPORTS.mozilla.dom += [ "MediaMetadata.h", "MediaSession.h", diff --git a/dom/media/mediasession/test/gtest/TestPositionState.cpp b/dom/media/mediasession/test/gtest/TestPositionState.cpp new file mode 100644 index 0000000000..5fa38d0294 --- /dev/null +++ b/dom/media/mediasession/test/gtest/TestPositionState.cpp @@ -0,0 +1,127 @@ +/* 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 "gtest/gtest.h" +#include "MediaSession.h" + +using namespace mozilla; +using namespace mozilla::dom; + +struct CurrentPlaybackPositionFixture { + double mDuration = 0.0; + double mPlaybackRate = 0.0; + double mLastReportedTime = 0.0; + + TimeDuration mDelta; + double mExpectedPosition = -1; +}; + +class CurrentPlaybackPositionTest + : public testing::TestWithParam {}; + +static const std::initializer_list kFixtures = { + // position must be positive + { + 10.0, + 1.0, + 0.0, + TimeDuration::FromSeconds(-1.0), + 0.0, + }, + // no time elapsed + { + 10.0, + 1.0, + 0.0, + TimeDuration::FromSeconds(0.0), + 0.0, + }, + { + 10.0, + 1.0, + 0.0, + TimeDuration::FromSeconds(3.0), + 3.0, + }, + { + 10.0, + 1.0, + 0.0, + TimeDuration::FromSeconds(10.0), + 10.0, + }, + // position is clamped to the duration + { + 10.0, + 1.0, + 0.0, + TimeDuration::FromSeconds(20.0), + 10.0, + }, + { + 10.0, + 1.0, + 5.0, + TimeDuration::FromSeconds(-1.0), + 4.0, + }, + { + 10.0, + 1.0, + 5.0, + TimeDuration::FromSeconds(-6.0), + 0.0, + }, + { + 10.0, + 1.0, + 5.0, + TimeDuration::FromSeconds(6.0), + 10.0, + }, + // expected: 5s + 2 * 2s + { + 10.0, + 2.0, + 5.0, + TimeDuration::FromSeconds(2.0), + 9.0, + }, + // expected: 5s + 0.5 * 2s + { + 10.0, + 0.5, + 5.0, + TimeDuration::FromSeconds(2.0), + 6.0, + }, + { + 5.0, + 4.0, + 10.0, + TimeDuration::FromSeconds(20.0), + 5.0, + }, + // empty media (0s) + { + 0.0, + 4.0, + 5.0, + TimeDuration::FromSeconds(20.0), + 0.0, + }, +}; + +TEST_P(CurrentPlaybackPositionTest, Run) { + const auto& fixture = GetParam(); + PositionState state(fixture.mDuration, fixture.mPlaybackRate, + fixture.mLastReportedTime, TimeStamp::Now()); + + ASSERT_DOUBLE_EQ(state.CurrentPlaybackPosition(state.mPositionUpdatedTime + + fixture.mDelta), + fixture.mExpectedPosition); +} + +INSTANTIATE_TEST_SUITE_P(PositionState, CurrentPlaybackPositionTest, + testing::ValuesIn(kFixtures)); diff --git a/dom/media/mediasession/test/gtest/moz.build b/dom/media/mediasession/test/gtest/moz.build new file mode 100644 index 0000000000..fd2a9a6e30 --- /dev/null +++ b/dom/media/mediasession/test/gtest/moz.build @@ -0,0 +1,15 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +UNIFIED_SOURCES += [ + "TestPositionState.cpp", +] + +LOCAL_INCLUDES += [ + "/dom/media/mediasession", +] + +FINAL_LIBRARY = "xul-gtest" -- cgit v1.2.3