summaryrefslogtreecommitdiffstats
path: root/dom/media/mediasession
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/mediasession')
-rw-r--r--dom/media/mediasession/MediaSession.cpp30
-rw-r--r--dom/media/mediasession/MediaSession.h22
-rw-r--r--dom/media/mediasession/MediaSessionIPCUtils.h17
-rw-r--r--dom/media/mediasession/moz.build4
-rw-r--r--dom/media/mediasession/test/gtest/TestPositionState.cpp127
-rw-r--r--dom/media/mediasession/test/gtest/moz.build15
6 files changed, 196 insertions, 19 deletions
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<BrowsingContext> currentBC = GetParentObject()->GetBrowsingContext();
MOZ_ASSERT(currentBC, "Update action after context destroyed!");
if (RefPtr<IMediaInfoUpdater> 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<MediaMetadata> mMediaMetadata;
- EnumeratedArray<MediaSessionAction, MediaSessionAction::EndGuard_,
- RefPtr<MediaSessionActionHandler>>
+ EnumeratedArray<MediaSessionAction, RefPtr<MediaSessionActionHandler>>
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<mozilla::dom::PositionState> {
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<mozilla::dom::PositionState> {
template <>
struct ParamTraits<mozilla::dom::MediaSessionPlaybackState>
- : public ContiguousEnumSerializer<
- mozilla::dom::MediaSessionPlaybackState,
- mozilla::dom::MediaSessionPlaybackState::None,
- mozilla::dom::MediaSessionPlaybackState::EndGuard_> {};
+ : public mozilla::dom::WebIDLEnumSerializer<
+ mozilla::dom::MediaSessionPlaybackState> {};
template <>
struct ParamTraits<mozilla::dom::MediaSessionAction>
- : 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<CurrentPlaybackPositionFixture> {};
+
+static const std::initializer_list<CurrentPlaybackPositionFixture> 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"