diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /dom/media/mediacontrol/tests/gtest | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/mediacontrol/tests/gtest')
8 files changed, 844 insertions, 0 deletions
diff --git a/dom/media/mediacontrol/tests/gtest/MediaKeyListenerTest.h b/dom/media/mediacontrol/tests/gtest/MediaKeyListenerTest.h new file mode 100644 index 0000000000..5145eb7dbb --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/MediaKeyListenerTest.h @@ -0,0 +1,39 @@ +/* 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/. */ + +#ifndef DOM_MEDIA_MEDIAKEYLISTENERTEST_H_ +#define DOM_MEDIA_MEDIAKEYLISTENERTEST_H_ + +#include "MediaControlKeySource.h" +#include "mozilla/Maybe.h" + +namespace mozilla { +namespace dom { + +class MediaKeyListenerTest : public MediaControlKeyListener { + public: + NS_INLINE_DECL_REFCOUNTING(MediaKeyListenerTest, override) + + void Clear() { mReceivedKey = mozilla::Nothing(); } + + void OnActionPerformed(const MediaControlAction& aAction) override { + mReceivedKey = mozilla::Some(aAction.mKey); + } + bool IsResultEqualTo(MediaControlKey aResult) const { + if (mReceivedKey) { + return *mReceivedKey == aResult; + } + return false; + } + bool IsReceivedResult() const { return mReceivedKey.isSome(); } + + private: + ~MediaKeyListenerTest() = default; + mozilla::Maybe<MediaControlKey> mReceivedKey; +}; + +} // namespace dom +} // namespace mozilla + +#endif // DOM_MEDIA_MEDIAKEYLISTENERTEST_H_ diff --git a/dom/media/mediacontrol/tests/gtest/TestAudioFocusManager.cpp b/dom/media/mediacontrol/tests/gtest/TestAudioFocusManager.cpp new file mode 100644 index 0000000000..df1bb288a4 --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/TestAudioFocusManager.cpp @@ -0,0 +1,163 @@ +/* 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 "AudioFocusManager.h" +#include "MediaControlService.h" +#include "mozilla/Preferences.h" + +using namespace mozilla::dom; + +#define FIRST_CONTROLLER_ID 0 +#define SECOND_CONTROLLER_ID 1 + +// This RAII class is used to set the audio focus management pref within a test +// and automatically revert the change when a test ends, in order not to +// interfere other tests unexpectedly. +class AudioFocusManagmentPrefSetterRAII { + public: + explicit AudioFocusManagmentPrefSetterRAII(bool aPrefValue) { + mOriginalValue = mozilla::Preferences::GetBool(mPrefName, false); + mozilla::Preferences::SetBool(mPrefName, aPrefValue); + } + ~AudioFocusManagmentPrefSetterRAII() { + mozilla::Preferences::SetBool(mPrefName, mOriginalValue); + } + + private: + const char* mPrefName = "media.audioFocus.management"; + bool mOriginalValue; +}; + +TEST(AudioFocusManager, TestRequestAudioFocus) +{ + AudioFocusManager manager; + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + RefPtr<MediaController> controller = new MediaController(FIRST_CONTROLLER_ID); + + manager.RequestAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + manager.RevokeAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); +} + +TEST(AudioFocusManager, TestAudioFocusNumsWhenEnableAudioFocusManagement) +{ + // When enabling audio focus management, we only allow one controller owing + // audio focus at a time when the audio competing occurs. As the mechanism of + // handling the audio competing involves multiple components, we can't test it + // simply by using the APIs from AudioFocusManager. + AudioFocusManagmentPrefSetterRAII prefSetter(true); + + AudioFocusManager manager; + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + RefPtr<MediaController> controller1 = + new MediaController(FIRST_CONTROLLER_ID); + + RefPtr<MediaController> controller2 = + new MediaController(SECOND_CONTROLLER_ID); + + manager.RequestAudioFocus(controller1); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + // When controller2 starts, it would win the audio focus from controller1. So + // only one audio focus would exist. + manager.RequestAudioFocus(controller2); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + manager.RevokeAudioFocus(controller2); + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); +} + +TEST(AudioFocusManager, TestAudioFocusNumsWhenDisableAudioFocusManagement) +{ + // When disabling audio focus management, we won't handle the audio competing, + // so we allow multiple audio focus existing at the same time. + AudioFocusManagmentPrefSetterRAII prefSetter(false); + + AudioFocusManager manager; + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + RefPtr<MediaController> controller1 = + new MediaController(FIRST_CONTROLLER_ID); + + RefPtr<MediaController> controller2 = + new MediaController(SECOND_CONTROLLER_ID); + + manager.RequestAudioFocus(controller1); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + manager.RequestAudioFocus(controller2); + ASSERT_TRUE(manager.GetAudioFocusNums() == 2); + + manager.RevokeAudioFocus(controller1); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + manager.RevokeAudioFocus(controller2); + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); +} + +TEST(AudioFocusManager, TestRequestAudioFocusRepeatedly) +{ + AudioFocusManager manager; + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + RefPtr<MediaController> controller = new MediaController(FIRST_CONTROLLER_ID); + + manager.RequestAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + manager.RequestAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); +} + +TEST(AudioFocusManager, TestRevokeAudioFocusRepeatedly) +{ + AudioFocusManager manager; + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + RefPtr<MediaController> controller = new MediaController(FIRST_CONTROLLER_ID); + + manager.RequestAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + manager.RevokeAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + manager.RevokeAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); +} + +TEST(AudioFocusManager, TestRevokeAudioFocusWithoutRequestAudioFocus) +{ + AudioFocusManager manager; + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + RefPtr<MediaController> controller = new MediaController(FIRST_CONTROLLER_ID); + + manager.RevokeAudioFocus(controller); + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); +} + +TEST(AudioFocusManager, + TestRevokeAudioFocusForControllerWithoutOwningAudioFocus) +{ + AudioFocusManager manager; + ASSERT_TRUE(manager.GetAudioFocusNums() == 0); + + RefPtr<MediaController> controller1 = + new MediaController(FIRST_CONTROLLER_ID); + + RefPtr<MediaController> controller2 = + new MediaController(SECOND_CONTROLLER_ID); + + manager.RequestAudioFocus(controller1); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); + + manager.RevokeAudioFocus(controller2); + ASSERT_TRUE(manager.GetAudioFocusNums() == 1); +} diff --git a/dom/media/mediacontrol/tests/gtest/TestMediaControlService.cpp b/dom/media/mediacontrol/tests/gtest/TestMediaControlService.cpp new file mode 100644 index 0000000000..ab5b0cb8c7 --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/TestMediaControlService.cpp @@ -0,0 +1,64 @@ +/* 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 "MediaControlService.h" +#include "MediaController.h" + +using namespace mozilla::dom; + +#define FIRST_CONTROLLER_ID 0 +#define SECOND_CONTROLLER_ID 1 + +TEST(MediaControlService, TestAddOrRemoveControllers) +{ + RefPtr<MediaControlService> service = MediaControlService::GetService(); + ASSERT_TRUE(service->GetActiveControllersNum() == 0); + + RefPtr<MediaController> controller1 = + new MediaController(FIRST_CONTROLLER_ID); + RefPtr<MediaController> controller2 = + new MediaController(SECOND_CONTROLLER_ID); + + service->RegisterActiveMediaController(controller1); + ASSERT_TRUE(service->GetActiveControllersNum() == 1); + + service->RegisterActiveMediaController(controller2); + ASSERT_TRUE(service->GetActiveControllersNum() == 2); + + service->UnregisterActiveMediaController(controller1); + ASSERT_TRUE(service->GetActiveControllersNum() == 1); + + service->UnregisterActiveMediaController(controller2); + ASSERT_TRUE(service->GetActiveControllersNum() == 0); +} + +TEST(MediaControlService, TestMainController) +{ + RefPtr<MediaControlService> service = MediaControlService::GetService(); + ASSERT_TRUE(service->GetActiveControllersNum() == 0); + + RefPtr<MediaController> controller1 = + new MediaController(FIRST_CONTROLLER_ID); + service->RegisterActiveMediaController(controller1); + + RefPtr<MediaController> mainController = service->GetMainController(); + ASSERT_TRUE(mainController->Id() == FIRST_CONTROLLER_ID); + + RefPtr<MediaController> controller2 = + new MediaController(SECOND_CONTROLLER_ID); + service->RegisterActiveMediaController(controller2); + + mainController = service->GetMainController(); + ASSERT_TRUE(mainController->Id() == SECOND_CONTROLLER_ID); + + service->UnregisterActiveMediaController(controller2); + mainController = service->GetMainController(); + ASSERT_TRUE(mainController->Id() == FIRST_CONTROLLER_ID); + + service->UnregisterActiveMediaController(controller1); + mainController = service->GetMainController(); + ASSERT_TRUE(service->GetActiveControllersNum() == 0); + ASSERT_TRUE(!mainController); +} diff --git a/dom/media/mediacontrol/tests/gtest/TestMediaController.cpp b/dom/media/mediacontrol/tests/gtest/TestMediaController.cpp new file mode 100644 index 0000000000..5ba8d2a7d5 --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/TestMediaController.cpp @@ -0,0 +1,204 @@ +/* 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 "MediaControlService.h" +#include "MediaController.h" +#include "mozilla/dom/MediaSessionBinding.h" + +using namespace mozilla::dom; + +#define CONTROLLER_ID 0 +#define FAKE_CONTEXT_ID 0 + +#define FIRST_CONTROLLER_ID 0 + +TEST(MediaController, DefaultValueCheck) +{ + RefPtr<MediaController> controller = new MediaController(CONTROLLER_ID); + ASSERT_TRUE(!controller->IsAnyMediaBeingControlled()); + ASSERT_TRUE(controller->Id() == CONTROLLER_ID); + ASSERT_TRUE(controller->PlaybackState() == MediaSessionPlaybackState::None); + ASSERT_TRUE(!controller->IsAudible()); +} + +TEST(MediaController, IsAnyMediaBeingControlled) +{ + RefPtr<MediaController> controller = new MediaController(CONTROLLER_ID); + ASSERT_TRUE(!controller->IsAnyMediaBeingControlled()); + + controller->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, + MediaPlaybackState::eStarted); + ASSERT_TRUE(controller->IsAnyMediaBeingControlled()); + + controller->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, + MediaPlaybackState::eStarted); + ASSERT_TRUE(controller->IsAnyMediaBeingControlled()); + + controller->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, + MediaPlaybackState::eStopped); + ASSERT_TRUE(controller->IsAnyMediaBeingControlled()); + + controller->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, + MediaPlaybackState::eStopped); + ASSERT_TRUE(!controller->IsAnyMediaBeingControlled()); +} + +class FakeControlledMedia final { + public: + explicit FakeControlledMedia(MediaController* aController) + : mController(aController) { + mController->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, + MediaPlaybackState::eStarted); + } + + void SetPlaying(MediaPlaybackState aState) { + if (mPlaybackState == aState) { + return; + } + mController->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, aState); + mPlaybackState = aState; + } + + void SetAudible(MediaAudibleState aState) { + if (mAudibleState == aState) { + return; + } + mController->NotifyMediaAudibleChanged(FAKE_CONTEXT_ID, aState); + mAudibleState = aState; + } + + ~FakeControlledMedia() { + if (mPlaybackState == MediaPlaybackState::ePlayed) { + mController->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, + MediaPlaybackState::ePaused); + } + mController->NotifyMediaPlaybackChanged(FAKE_CONTEXT_ID, + MediaPlaybackState::eStopped); + } + + private: + MediaPlaybackState mPlaybackState = MediaPlaybackState::eStopped; + MediaAudibleState mAudibleState = MediaAudibleState::eInaudible; + RefPtr<MediaController> mController; +}; + +TEST(MediaController, ActiveAndDeactiveController) +{ + RefPtr<MediaControlService> service = MediaControlService::GetService(); + ASSERT_TRUE(service->GetActiveControllersNum() == 0); + + RefPtr<MediaController> controller = new MediaController(FIRST_CONTROLLER_ID); + + // In order to check active control number after FakeControlledMedia + // destroyed. + { + FakeControlledMedia fakeMedia(controller); + fakeMedia.SetPlaying(MediaPlaybackState::ePlayed); + ASSERT_TRUE(service->GetActiveControllersNum() == 1); + + fakeMedia.SetAudible(MediaAudibleState::eAudible); + ASSERT_TRUE(service->GetActiveControllersNum() == 1); + + fakeMedia.SetAudible(MediaAudibleState::eInaudible); + ASSERT_TRUE(service->GetActiveControllersNum() == 1); + } + + ASSERT_TRUE(service->GetActiveControllersNum() == 0); +} + +TEST(MediaController, AudibleChanged) +{ + RefPtr<MediaController> controller = new MediaController(CONTROLLER_ID); + + FakeControlledMedia fakeMedia(controller); + fakeMedia.SetPlaying(MediaPlaybackState::ePlayed); + ASSERT_TRUE(!controller->IsAudible()); + + fakeMedia.SetAudible(MediaAudibleState::eAudible); + ASSERT_TRUE(controller->IsAudible()); + + fakeMedia.SetAudible(MediaAudibleState::eInaudible); + ASSERT_TRUE(!controller->IsAudible()); +} + +TEST(MediaController, PlayingStateChangeViaControlledMedia) +{ + RefPtr<MediaController> controller = new MediaController(CONTROLLER_ID); + + // In order to check playing state after FakeControlledMedia destroyed. + { + FakeControlledMedia foo(controller); + ASSERT_TRUE(controller->PlaybackState() == MediaSessionPlaybackState::None); + + foo.SetPlaying(MediaPlaybackState::ePlayed); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Playing); + + foo.SetPlaying(MediaPlaybackState::ePaused); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Paused); + + foo.SetPlaying(MediaPlaybackState::ePlayed); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Playing); + } + + // FakeControlledMedia has been destroyed, no playing media exists. + ASSERT_TRUE(controller->PlaybackState() == MediaSessionPlaybackState::Paused); +} + +TEST(MediaController, ControllerShouldRemainPlayingIfAnyPlayingMediaExists) +{ + RefPtr<MediaController> controller = new MediaController(CONTROLLER_ID); + + { + FakeControlledMedia foo(controller); + ASSERT_TRUE(controller->PlaybackState() == MediaSessionPlaybackState::None); + + foo.SetPlaying(MediaPlaybackState::ePlayed); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Playing); + + // foo is playing, so controller is in `playing` state. + FakeControlledMedia bar(controller); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Playing); + + bar.SetPlaying(MediaPlaybackState::ePlayed); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Playing); + + // Although we paused bar, but foo is still playing, so the controller would + // still be in `playing`. + bar.SetPlaying(MediaPlaybackState::ePaused); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Playing); + + foo.SetPlaying(MediaPlaybackState::ePaused); + ASSERT_TRUE(controller->PlaybackState() == + MediaSessionPlaybackState::Paused); + } + + // both foo and bar have been destroyed, no playing media exists. + ASSERT_TRUE(controller->PlaybackState() == MediaSessionPlaybackState::Paused); +} + +TEST(MediaController, PictureInPictureModeOrFullscreen) +{ + RefPtr<MediaController> controller = new MediaController(CONTROLLER_ID); + ASSERT_TRUE(!controller->IsBeingUsedInPIPModeOrFullscreen()); + + controller->SetIsInPictureInPictureMode(FAKE_CONTEXT_ID, true); + ASSERT_TRUE(controller->IsBeingUsedInPIPModeOrFullscreen()); + + controller->SetIsInPictureInPictureMode(FAKE_CONTEXT_ID, false); + ASSERT_TRUE(!controller->IsBeingUsedInPIPModeOrFullscreen()); + + controller->NotifyMediaFullScreenState(FAKE_CONTEXT_ID, true); + ASSERT_TRUE(controller->IsBeingUsedInPIPModeOrFullscreen()); + + controller->NotifyMediaFullScreenState(FAKE_CONTEXT_ID, false); + ASSERT_TRUE(!controller->IsBeingUsedInPIPModeOrFullscreen()); +} diff --git a/dom/media/mediacontrol/tests/gtest/TestMediaKeysEvent.cpp b/dom/media/mediacontrol/tests/gtest/TestMediaKeysEvent.cpp new file mode 100644 index 0000000000..a73ceb8592 --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/TestMediaKeysEvent.cpp @@ -0,0 +1,49 @@ +/* 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 "MediaController.h" +#include "MediaControlKeySource.h" + +using namespace mozilla::dom; + +class MediaControlKeySourceTestImpl : public MediaControlKeySource { + public: + NS_INLINE_DECL_REFCOUNTING(MediaControlKeySourceTestImpl, override) + bool Open() override { return true; } + bool IsOpened() const override { return true; } + void SetSupportedMediaKeys(const MediaKeysArray& aSupportedKeys) override {} + + private: + ~MediaControlKeySourceTestImpl() = default; +}; + +TEST(MediaControlKey, TestAddOrRemoveListener) +{ + RefPtr<MediaControlKeySource> source = new MediaControlKeySourceTestImpl(); + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaControlKeyListener> listener = new MediaControlKeyHandler(); + + source->AddListener(listener); + ASSERT_TRUE(source->GetListenersNum() == 1); + + source->RemoveListener(listener); + ASSERT_TRUE(source->GetListenersNum() == 0); +} + +TEST(MediaControlKey, SetSourcePlaybackState) +{ + RefPtr<MediaControlKeySource> source = new MediaControlKeySourceTestImpl(); + ASSERT_TRUE(source->GetPlaybackState() == MediaSessionPlaybackState::None); + + source->SetPlaybackState(MediaSessionPlaybackState::Playing); + ASSERT_TRUE(source->GetPlaybackState() == MediaSessionPlaybackState::Playing); + + source->SetPlaybackState(MediaSessionPlaybackState::Paused); + ASSERT_TRUE(source->GetPlaybackState() == MediaSessionPlaybackState::Paused); + + source->SetPlaybackState(MediaSessionPlaybackState::None); + ASSERT_TRUE(source->GetPlaybackState() == MediaSessionPlaybackState::None); +} diff --git a/dom/media/mediacontrol/tests/gtest/TestMediaKeysEventMac.mm b/dom/media/mediacontrol/tests/gtest/TestMediaKeysEventMac.mm new file mode 100644 index 0000000000..3c8ce8cd9e --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/TestMediaKeysEventMac.mm @@ -0,0 +1,136 @@ +/* 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/. */ + +#import <AppKit/AppKit.h> +#import <AppKit/NSEvent.h> +#import <ApplicationServices/ApplicationServices.h> +#import <CoreFoundation/CoreFoundation.h> +#import <IOKit/hidsystem/ev_keymap.h> + +#include "gtest/gtest.h" +#include "MediaHardwareKeysEventSourceMac.h" +#include "MediaKeyListenerTest.h" +#include "mozilla/Maybe.h" + +using namespace mozilla::dom; +using namespace mozilla::widget; + +static const int kSystemDefinedEventMediaKeysSubtype = 8; + +static void SendFakeEvent(RefPtr<MediaHardwareKeysEventSourceMac>& aSource, int aKeyData) { + NSEvent* event = [NSEvent otherEventWithType:NSEventTypeSystemDefined + location:NSZeroPoint + modifierFlags:0 + timestamp:0 + windowNumber:0 + context:nil + subtype:kSystemDefinedEventMediaKeysSubtype + data1:aKeyData + data2:0]; + aSource->EventTapCallback(nullptr, static_cast<CGEventType>(0), [event CGEvent], aSource.get()); +} + +static void NotifyFakeNonMediaKey(RefPtr<MediaHardwareKeysEventSourceMac>& aSource, + bool aIsKeyPressed) { + int keyData = 0 | ((aIsKeyPressed ? 0xA : 0xB) << 8); + SendFakeEvent(aSource, keyData); +} + +static void NotifyFakeMediaControlKey(RefPtr<MediaHardwareKeysEventSourceMac>& aSource, + MediaControlKey aEvent, bool aIsKeyPressed) { + int keyData = 0; + if (aEvent == MediaControlKey::Playpause) { + keyData = NX_KEYTYPE_PLAY << 16; + } else if (aEvent == MediaControlKey::Nexttrack) { + keyData = NX_KEYTYPE_NEXT << 16; + } else if (aEvent == MediaControlKey::Previoustrack) { + keyData = NX_KEYTYPE_PREVIOUS << 16; + } + keyData |= ((aIsKeyPressed ? 0xA : 0xB) << 8); + SendFakeEvent(aSource, keyData); +} + +static void NotifyKeyPressedMediaKey(RefPtr<MediaHardwareKeysEventSourceMac>& aSource, + MediaControlKey aEvent) { + NotifyFakeMediaControlKey(aSource, aEvent, true /* key pressed */); +} + +static void NotifyKeyReleasedMediaKeysEvent(RefPtr<MediaHardwareKeysEventSourceMac>& aSource, + MediaControlKey aEvent) { + NotifyFakeMediaControlKey(aSource, aEvent, false /* key released */); +} + +static void NotifyKeyPressedNonMediaKeysEvents(RefPtr<MediaHardwareKeysEventSourceMac>& aSource) { + NotifyFakeNonMediaKey(aSource, true /* key pressed */); +} + +static void NotifyKeyReleasedNonMediaKeysEvents(RefPtr<MediaHardwareKeysEventSourceMac>& aSource) { + NotifyFakeNonMediaKey(aSource, false /* key released */); +} + +TEST(MediaHardwareKeysEventSourceMac, TestKeyPressedMediaKeysEvent) +{ + RefPtr<MediaHardwareKeysEventSourceMac> source = new MediaHardwareKeysEventSourceMac(); + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + source->AddListener(listener.get()); + ASSERT_TRUE(source->GetListenersNum() == 1); + ASSERT_TRUE(!listener->IsReceivedResult()); + + NotifyKeyPressedMediaKey(source, MediaControlKey::Playpause); + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Playpause)); + + NotifyKeyPressedMediaKey(source, MediaControlKey::Nexttrack); + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Nexttrack)); + + NotifyKeyPressedMediaKey(source, MediaControlKey::Previoustrack); + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Previoustrack)); + + source->RemoveListener(listener); + ASSERT_TRUE(source->GetListenersNum() == 0); +} + +TEST(MediaHardwareKeysEventSourceMac, TestKeyReleasedMediaKeysEvent) +{ + RefPtr<MediaHardwareKeysEventSourceMac> source = new MediaHardwareKeysEventSourceMac(); + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + source->AddListener(listener.get()); + ASSERT_TRUE(source->GetListenersNum() == 1); + ASSERT_TRUE(!listener->IsReceivedResult()); + + NotifyKeyReleasedMediaKeysEvent(source, MediaControlKey::Playpause); + ASSERT_TRUE(!listener->IsReceivedResult()); + + NotifyKeyReleasedMediaKeysEvent(source, MediaControlKey::Nexttrack); + ASSERT_TRUE(!listener->IsReceivedResult()); + + NotifyKeyReleasedMediaKeysEvent(source, MediaControlKey::Previoustrack); + ASSERT_TRUE(!listener->IsReceivedResult()); + + source->RemoveListener(listener); + ASSERT_TRUE(source->GetListenersNum() == 0); +} + +TEST(MediaHardwareKeysEventSourceMac, TestNonMediaKeysEvent) +{ + RefPtr<MediaHardwareKeysEventSourceMac> source = new MediaHardwareKeysEventSourceMac(); + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + source->AddListener(listener.get()); + ASSERT_TRUE(source->GetListenersNum() == 1); + ASSERT_TRUE(!listener->IsReceivedResult()); + + NotifyKeyPressedNonMediaKeysEvents(source); + ASSERT_TRUE(!listener->IsReceivedResult()); + + NotifyKeyReleasedNonMediaKeysEvents(source); + ASSERT_TRUE(!listener->IsReceivedResult()); + + source->RemoveListener(listener); + ASSERT_TRUE(source->GetListenersNum() == 0); +} diff --git a/dom/media/mediacontrol/tests/gtest/TestMediaKeysEventMediaCenter.mm b/dom/media/mediacontrol/tests/gtest/TestMediaKeysEventMediaCenter.mm new file mode 100644 index 0000000000..1d32960d2f --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/TestMediaKeysEventMediaCenter.mm @@ -0,0 +1,166 @@ +/* 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/. */ +#import <MediaPlayer/MediaPlayer.h> + +#include "gtest/gtest.h" +#include "MediaHardwareKeysEventSourceMacMediaCenter.h" +#include "MediaKeyListenerTest.h" +#include "nsCocoaFeatures.h" +#include "nsCocoaUtils.h" +#include "prinrval.h" +#include "prthread.h" + +using namespace mozilla::dom; +using namespace mozilla::widget; + +NS_ASSUME_NONNULL_BEGIN + +TEST(MediaHardwareKeysEventSourceMacMediaCenter, TestMediaCenterPlayPauseEvent) +{ + RefPtr<MediaHardwareKeysEventSourceMacMediaCenter> source = + new MediaHardwareKeysEventSourceMacMediaCenter(); + + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + + source->AddListener(listener.get()); + + ASSERT_TRUE(source->Open()); + + ASSERT_TRUE(source->GetListenersNum() == 1); + ASSERT_TRUE(!listener->IsReceivedResult()); + ASSERT_TRUE(center.playbackState == MPNowPlayingPlaybackStatePlaying); + + MediaCenterEventHandler playPauseHandler = source->CreatePlayPauseHandler(); + playPauseHandler(nil); + + ASSERT_TRUE(center.playbackState == MPNowPlayingPlaybackStatePaused); + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Playpause)); + + listener->Clear(); // Reset stored media key + + playPauseHandler(nil); + + ASSERT_TRUE(center.playbackState == MPNowPlayingPlaybackStatePlaying); + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Playpause)); +} + +TEST(MediaHardwareKeysEventSourceMacMediaCenter, TestMediaCenterPlayEvent) +{ + RefPtr<MediaHardwareKeysEventSourceMacMediaCenter> source = + new MediaHardwareKeysEventSourceMacMediaCenter(); + + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + + source->AddListener(listener.get()); + + ASSERT_TRUE(source->Open()); + + ASSERT_TRUE(source->GetListenersNum() == 1); + ASSERT_TRUE(!listener->IsReceivedResult()); + ASSERT_TRUE(center.playbackState == MPNowPlayingPlaybackStatePlaying); + + MediaCenterEventHandler playHandler = source->CreatePlayHandler(); + + center.playbackState = MPNowPlayingPlaybackStatePaused; + + playHandler(nil); + + ASSERT_TRUE(center.playbackState == MPNowPlayingPlaybackStatePlaying); + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Play)); +} + +TEST(MediaHardwareKeysEventSourceMacMediaCenter, TestMediaCenterPauseEvent) +{ + RefPtr<MediaHardwareKeysEventSourceMacMediaCenter> source = + new MediaHardwareKeysEventSourceMacMediaCenter(); + + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + + source->AddListener(listener.get()); + + ASSERT_TRUE(source->Open()); + + ASSERT_TRUE(source->GetListenersNum() == 1); + ASSERT_TRUE(!listener->IsReceivedResult()); + ASSERT_TRUE(center.playbackState == MPNowPlayingPlaybackStatePlaying); + + MediaCenterEventHandler pauseHandler = source->CreatePauseHandler(); + + pauseHandler(nil); + + ASSERT_TRUE(center.playbackState == MPNowPlayingPlaybackStatePaused); + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Pause)); +} + +TEST(MediaHardwareKeysEventSourceMacMediaCenter, TestMediaCenterPrevNextEvent) +{ + RefPtr<MediaHardwareKeysEventSourceMacMediaCenter> source = + new MediaHardwareKeysEventSourceMacMediaCenter(); + + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + + source->AddListener(listener.get()); + + ASSERT_TRUE(source->Open()); + + MediaCenterEventHandler nextHandler = source->CreateNextTrackHandler(); + + nextHandler(nil); + + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Nexttrack)); + + MediaCenterEventHandler previousHandler = source->CreatePreviousTrackHandler(); + + previousHandler(nil); + + ASSERT_TRUE(listener->IsResultEqualTo(MediaControlKey::Previoustrack)); +} + +TEST(MediaHardwareKeysEventSourceMacMediaCenter, TestSetMetadata) +{ + RefPtr<MediaHardwareKeysEventSourceMacMediaCenter> source = + new MediaHardwareKeysEventSourceMacMediaCenter(); + + ASSERT_TRUE(source->GetListenersNum() == 0); + + RefPtr<MediaKeyListenerTest> listener = new MediaKeyListenerTest(); + + source->AddListener(listener.get()); + + ASSERT_TRUE(source->Open()); + + MediaMetadataBase metadata; + metadata.mTitle = u"MediaPlayback"; + metadata.mArtist = u"Firefox"; + metadata.mAlbum = u"Mozilla"; + source->SetMediaMetadata(metadata); + + // The update procedure of nowPlayingInfo is async, so wait for a second + // before checking the result. + PR_Sleep(PR_SecondsToInterval(1)); + MPNowPlayingInfoCenter* center = [MPNowPlayingInfoCenter defaultCenter]; + ASSERT_TRUE([center.nowPlayingInfo[MPMediaItemPropertyTitle] isEqualToString:@"MediaPlayback"]); + ASSERT_TRUE([center.nowPlayingInfo[MPMediaItemPropertyArtist] isEqualToString:@"Firefox"]); + ASSERT_TRUE([center.nowPlayingInfo[MPMediaItemPropertyAlbumTitle] isEqualToString:@"Mozilla"]); + + source->Close(); + PR_Sleep(PR_SecondsToInterval(1)); + ASSERT_TRUE(center.nowPlayingInfo == nil); +} + +NS_ASSUME_NONNULL_END diff --git a/dom/media/mediacontrol/tests/gtest/moz.build b/dom/media/mediacontrol/tests/gtest/moz.build new file mode 100644 index 0000000000..7043bfcd5e --- /dev/null +++ b/dom/media/mediacontrol/tests/gtest/moz.build @@ -0,0 +1,23 @@ +# -*- 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 += [ + "TestAudioFocusManager.cpp", + "TestMediaController.cpp", + "TestMediaControlService.cpp", + "TestMediaKeysEvent.cpp", +] + +if CONFIG["MOZ_APPLEMEDIA"]: + UNIFIED_SOURCES += ["TestMediaKeysEventMac.mm", "TestMediaKeysEventMediaCenter.mm"] + +include("/ipc/chromium/chromium-config.mozbuild") + +LOCAL_INCLUDES += [ + "/dom/media/mediacontrol", +] + +FINAL_LIBRARY = "xul-gtest" |