blob: d8d7c62f575ac9b777e08ce27954764e5655ea81 [file] [log] [blame]
// Copyright 2019 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 "content/browser/media/system_media_controls_notifier.h"
#include <memory>
#include <utility>
#include "base/test/task_environment.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/idle/scoped_set_idle_state.h"
#include "ui/base/win/system_media_controls/mock_system_media_controls_service.h"
namespace content {
using ABI::Windows::Media::MediaPlaybackStatus;
using media_session::mojom::MediaPlaybackState;
using media_session::mojom::MediaSessionInfo;
using media_session::mojom::MediaSessionInfoPtr;
using testing::_;
using testing::Expectation;
class SystemMediaControlsNotifierTest : public testing::Test {
public:
SystemMediaControlsNotifierTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
~SystemMediaControlsNotifierTest() override = default;
void SetUp() override {
notifier_ =
std::make_unique<SystemMediaControlsNotifier>(/*connector=*/nullptr);
notifier_->SetSystemMediaControlsServiceForTesting(
&mock_system_media_controls_service_);
notifier_->Initialize();
}
protected:
void SimulatePlaying() {
MediaSessionInfoPtr session_info(MediaSessionInfo::New());
session_info->playback_state = MediaPlaybackState::kPlaying;
notifier_->MediaSessionInfoChanged(std::move(session_info));
}
void SimulatePaused() {
MediaSessionInfoPtr session_info(MediaSessionInfo::New());
session_info->playback_state = MediaPlaybackState::kPaused;
notifier_->MediaSessionInfoChanged(std::move(session_info));
}
void SimulateStopped() { notifier_->MediaSessionInfoChanged(nullptr); }
void SimulateMetadataChanged(bool empty,
base::string16 title,
base::string16 artist) {
if (!empty) {
media_session::MediaMetadata metadata;
metadata.title = title;
metadata.artist = artist;
notifier_->MediaSessionMetadataChanged(
base::Optional<media_session::MediaMetadata>(metadata));
} else {
notifier_->MediaSessionMetadataChanged(base::nullopt);
}
}
void SimulateImageChanged() {
// Need a non-empty SkBitmap so MediaControllerImageChanged doesn't try to
// get the icon from ChromeContentBrowserClient.
SkBitmap bitmap;
bitmap.allocN32Pixels(1, 1);
notifier_->MediaControllerImageChanged(
media_session::mojom::MediaSessionImageType::kArtwork, bitmap);
}
SystemMediaControlsNotifier& notifier() { return *notifier_; }
system_media_controls::testing::MockSystemMediaControlsService&
mock_system_media_controls_service() {
return mock_system_media_controls_service_;
}
base::RepeatingTimer& lock_polling_timer() {
return notifier_->lock_polling_timer_;
}
base::OneShotTimer& hide_smtc_timer() { return notifier_->hide_smtc_timer_; }
private:
base::test::TaskEnvironment task_environment_;
std::unique_ptr<SystemMediaControlsNotifier> notifier_;
system_media_controls::testing::MockSystemMediaControlsService
mock_system_media_controls_service_;
DISALLOW_COPY_AND_ASSIGN(SystemMediaControlsNotifierTest);
};
TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesPlaybackState) {
Expectation playing = EXPECT_CALL(
mock_system_media_controls_service(),
SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Playing));
Expectation paused =
EXPECT_CALL(
mock_system_media_controls_service(),
SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Paused))
.After(playing);
Expectation stopped =
EXPECT_CALL(
mock_system_media_controls_service(),
SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Stopped))
.After(paused);
EXPECT_CALL(mock_system_media_controls_service(), ClearMetadata())
.After(stopped);
SimulatePlaying();
SimulatePaused();
SimulateStopped();
}
TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesMetadata) {
base::string16 title = L"title";
base::string16 artist = L"artist";
EXPECT_CALL(mock_system_media_controls_service(), SetTitle(title));
EXPECT_CALL(mock_system_media_controls_service(), SetArtist(artist));
EXPECT_CALL(mock_system_media_controls_service(), ClearMetadata()).Times(0);
EXPECT_CALL(mock_system_media_controls_service(), UpdateDisplay());
SimulateMetadataChanged(false, title, artist);
}
TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesNullMetadata) {
EXPECT_CALL(mock_system_media_controls_service(), SetTitle(_)).Times(0);
EXPECT_CALL(mock_system_media_controls_service(), SetArtist(_)).Times(0);
EXPECT_CALL(mock_system_media_controls_service(), ClearMetadata());
SimulateMetadataChanged(true, L"", L"");
}
TEST_F(SystemMediaControlsNotifierTest, ProperlyUpdatesImage) {
EXPECT_CALL(mock_system_media_controls_service(), SetThumbnail(_));
SimulateImageChanged();
}
TEST_F(SystemMediaControlsNotifierTest, DisablesOnLockAndEnablesOnUnlock) {
EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(false));
{
// Lock the screen.
ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED);
// Make sure that the lock polling timer is running and then force it to
// fire so that we don't need to wait. This should disable the service.
EXPECT_TRUE(lock_polling_timer().IsRunning());
lock_polling_timer().user_task().Run();
}
// Ensure that the service was disabled.
testing::Mock::VerifyAndClearExpectations(
&mock_system_media_controls_service());
// The service should be reenabled on unlock.
EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(true));
{
// Unlock the screen.
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_ACTIVE);
// Make sure that the lock polling timer is running and then force it to
// fire so that we don't need to wait. This should enable the service.
EXPECT_TRUE(lock_polling_timer().IsRunning());
lock_polling_timer().user_task().Run();
}
}
TEST_F(SystemMediaControlsNotifierTest, DoesNotDisableOnLockWhenPlaying) {
EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(_)).Times(0);
SimulatePlaying();
// Lock the screen.
ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED);
// Make sure that the lock polling timer is running and then force it to
// fire so that we don't need to wait. This should not disable the service.
EXPECT_TRUE(lock_polling_timer().IsRunning());
lock_polling_timer().user_task().Run();
}
TEST_F(SystemMediaControlsNotifierTest, DisablesAfterPausingOnLockScreen) {
Expectation playing = EXPECT_CALL(
mock_system_media_controls_service(),
SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Playing));
Expectation paused =
EXPECT_CALL(
mock_system_media_controls_service(),
SetPlaybackStatus(MediaPlaybackStatus::MediaPlaybackStatus_Paused))
.After(playing);
EXPECT_CALL(mock_system_media_controls_service(), SetEnabled(false))
.After(paused);
SimulatePlaying();
// Lock the screen.
ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED);
// Make sure that the lock polling timer is running and then force it to
// fire so that we don't need to wait. This should not disable the service.
EXPECT_TRUE(lock_polling_timer().IsRunning());
lock_polling_timer().user_task().Run();
// Since we're playing, the timer to hide the SMTC should not be running.
EXPECT_FALSE(hide_smtc_timer().IsRunning());
SimulatePaused();
// Now that we're paused, the timer to hide the SMTC should be running.
EXPECT_TRUE(hide_smtc_timer().IsRunning());
// Force the timer to fire now. This should disable the service.
hide_smtc_timer().FireNow();
}
} // namespace content