| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <tuple> | 5 #include <tuple> |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 using testing::NiceMock; | 23 using testing::NiceMock; |
| 24 using testing::Return; | 24 using testing::Return; |
| 25 using testing::StrictMock; | 25 using testing::StrictMock; |
| 26 | 26 |
| 27 namespace media { | 27 namespace media { |
| 28 | 28 |
| 29 namespace { | 29 namespace { |
| 30 constexpr base::TimeDelta kIdleTimeout = base::TimeDelta::FromSeconds(1); | 30 constexpr base::TimeDelta kIdleTimeout = base::TimeDelta::FromSeconds(1); |
| 31 } | 31 } |
| 32 | 32 |
| 33 ACTION_P(RunClosure, closure) { | |
| 34 closure.Run(); | |
| 35 return true; | |
| 36 } | |
| 37 | |
| 38 class MockWebMediaPlayerDelegateObserver | 33 class MockWebMediaPlayerDelegateObserver |
| 39 : public WebMediaPlayerDelegate::Observer { | 34 : public WebMediaPlayerDelegate::Observer { |
| 40 public: | 35 public: |
| 41 MockWebMediaPlayerDelegateObserver() {} | 36 MockWebMediaPlayerDelegateObserver() {} |
| 42 ~MockWebMediaPlayerDelegateObserver() {} | 37 ~MockWebMediaPlayerDelegateObserver() {} |
| 43 | 38 |
| 44 // WebMediaPlayerDelegate::Observer implementation. | 39 // WebMediaPlayerDelegate::Observer implementation. |
| 45 MOCK_METHOD0(OnHidden, void()); | 40 MOCK_METHOD0(OnFrameHidden, void()); |
| 46 MOCK_METHOD0(OnShown, void()); | 41 MOCK_METHOD0(OnFrameClosed, void()); |
| 47 MOCK_METHOD1(OnSuspendRequested, bool(bool)); | 42 MOCK_METHOD0(OnFrameShown, void()); |
| 43 MOCK_METHOD0(OnIdleTimeout, void()); |
| 48 MOCK_METHOD0(OnPlay, void()); | 44 MOCK_METHOD0(OnPlay, void()); |
| 49 MOCK_METHOD0(OnPause, void()); | 45 MOCK_METHOD0(OnPause, void()); |
| 50 MOCK_METHOD1(OnVolumeMultiplierUpdate, void(double)); | 46 MOCK_METHOD1(OnVolumeMultiplierUpdate, void(double)); |
| 51 }; | 47 }; |
| 52 | 48 |
| 53 class RendererWebMediaPlayerDelegateTest : public content::RenderViewTest { | 49 class RendererWebMediaPlayerDelegateTest : public content::RenderViewTest { |
| 54 public: | 50 public: |
| 55 RendererWebMediaPlayerDelegateTest() {} | 51 RendererWebMediaPlayerDelegateTest() {} |
| 56 ~RendererWebMediaPlayerDelegateTest() override {} | 52 ~RendererWebMediaPlayerDelegateTest() override {} |
| 57 | 53 |
| 58 void SetUp() override { | 54 void SetUp() override { |
| 59 RenderViewTest::SetUp(); | 55 RenderViewTest::SetUp(); |
| 60 // Start the tick clock off at a non-null value. | 56 // Start the tick clock off at a non-null value. |
| 61 tick_clock_.Advance(base::TimeDelta::FromSeconds(1234)); | 57 tick_clock_.Advance(base::TimeDelta::FromSeconds(1234)); |
| 62 delegate_manager_.reset( | 58 delegate_manager_.reset( |
| 63 new RendererWebMediaPlayerDelegate(view_->GetMainRenderFrame())); | 59 new RendererWebMediaPlayerDelegate(view_->GetMainRenderFrame())); |
| 64 delegate_manager_->SetIdleCleanupParamsForTesting(kIdleTimeout, | 60 delegate_manager_->SetIdleCleanupParamsForTesting(kIdleTimeout, |
| 65 &tick_clock_, false); | 61 &tick_clock_, false); |
| 66 } | 62 } |
| 67 | 63 |
| 68 void TearDown() override { | 64 void TearDown() override { |
| 69 delegate_manager_.reset(); | 65 delegate_manager_.reset(); |
| 70 RenderViewTest::TearDown(); | 66 RenderViewTest::TearDown(); |
| 71 } | 67 } |
| 72 | 68 |
| 73 protected: | 69 protected: |
| 74 IPC::TestSink& test_sink() { return render_thread_->sink(); } | 70 IPC::TestSink& test_sink() { return render_thread_->sink(); } |
| 75 | 71 |
| 76 bool HasPlayingVideo(int delegate_id) { | 72 void SetBackgroundVideoPlaybackUnlocked(bool is_unlocked) { |
| 77 return delegate_manager_->playing_videos_.count(delegate_id); | 73 delegate_manager_->background_video_allowed_ = is_unlocked; |
| 78 } | |
| 79 | |
| 80 void SetPlayingBackgroundVideo(bool is_playing) { | |
| 81 delegate_manager_->is_playing_background_video_ = is_playing; | |
| 82 } | 74 } |
| 83 | 75 |
| 84 void CallOnMediaDelegatePlay(int delegate_id) { | 76 void CallOnMediaDelegatePlay(int delegate_id) { |
| 85 delegate_manager_->OnMediaDelegatePlay(delegate_id); | 77 delegate_manager_->OnMediaDelegatePlay(delegate_id); |
| 86 } | 78 } |
| 87 | 79 |
| 88 void CallOnMediaDelegatePause(int delegate_id) { | 80 void CallOnMediaDelegatePause(int delegate_id) { |
| 89 delegate_manager_->OnMediaDelegatePause(delegate_id); | 81 delegate_manager_->OnMediaDelegatePause(delegate_id); |
| 90 } | 82 } |
| 91 | 83 |
| 92 void SetIsLowEndDeviceForTesting() { | 84 void SetIsLowEndDeviceForTesting() { |
| 93 delegate_manager_->SetIdleCleanupParamsForTesting(kIdleTimeout, | 85 delegate_manager_->SetIdleCleanupParamsForTesting(kIdleTimeout, |
| 94 &tick_clock_, true); | 86 &tick_clock_, true); |
| 95 } | 87 } |
| 96 | 88 |
| 89 void RunLoopOnce() { |
| 90 base::RunLoop run_loop; |
| 91 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 92 run_loop.QuitClosure()); |
| 93 run_loop.Run(); |
| 94 } |
| 95 |
| 97 std::unique_ptr<RendererWebMediaPlayerDelegate> delegate_manager_; | 96 std::unique_ptr<RendererWebMediaPlayerDelegate> delegate_manager_; |
| 98 StrictMock<MockWebMediaPlayerDelegateObserver> observer_1_, observer_2_, | 97 StrictMock<MockWebMediaPlayerDelegateObserver> observer_1_, observer_2_, |
| 99 observer_3_; | 98 observer_3_; |
| 100 base::SimpleTestTickClock tick_clock_; | 99 base::SimpleTestTickClock tick_clock_; |
| 101 | 100 |
| 102 private: | 101 private: |
| 103 DISALLOW_COPY_AND_ASSIGN(RendererWebMediaPlayerDelegateTest); | 102 DISALLOW_COPY_AND_ASSIGN(RendererWebMediaPlayerDelegateTest); |
| 104 }; | 103 }; |
| 105 | 104 |
| 106 TEST_F(RendererWebMediaPlayerDelegateTest, SendsMessagesCorrectly) { | 105 TEST_F(RendererWebMediaPlayerDelegateTest, SendsMessagesCorrectly) { |
| 107 StrictMock<MockWebMediaPlayerDelegateObserver> observer; | 106 StrictMock<MockWebMediaPlayerDelegateObserver> observer; |
| 108 const int delegate_id = delegate_manager_->AddObserver(&observer); | 107 const int delegate_id = delegate_manager_->AddObserver(&observer); |
| 109 | 108 |
| 110 // Verify the playing message. | 109 // Verify the playing message. |
| 111 { | 110 { |
| 112 const bool kHasVideo = true, kHasAudio = false, kIsRemote = false; | 111 const bool kHasVideo = true, kHasAudio = false, kIsRemote = false; |
| 113 const media::MediaContentType kMediaContentType = | 112 const media::MediaContentType kMediaContentType = |
| 114 media::MediaContentType::Transient; | 113 media::MediaContentType::Transient; |
| 115 delegate_manager_->DidPlay(delegate_id, kHasVideo, kHasAudio, kIsRemote, | 114 delegate_manager_->DidPlay(delegate_id, kHasVideo, kHasAudio, |
| 116 kMediaContentType); | 115 kMediaContentType); |
| 117 | 116 |
| 118 const IPC::Message* msg = test_sink().GetUniqueMessageMatching( | 117 const IPC::Message* msg = test_sink().GetUniqueMessageMatching( |
| 119 MediaPlayerDelegateHostMsg_OnMediaPlaying::ID); | 118 MediaPlayerDelegateHostMsg_OnMediaPlaying::ID); |
| 120 ASSERT_TRUE(msg); | 119 ASSERT_TRUE(msg); |
| 121 | 120 |
| 122 std::tuple<int, bool, bool, bool, media::MediaContentType> result; | 121 std::tuple<int, bool, bool, bool, media::MediaContentType> result; |
| 123 ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPlaying::Read(msg, &result)); | 122 ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPlaying::Read(msg, &result)); |
| 124 EXPECT_EQ(delegate_id, std::get<0>(result)); | 123 EXPECT_EQ(delegate_id, std::get<0>(result)); |
| 125 EXPECT_EQ(kHasVideo, std::get<1>(result)); | 124 EXPECT_EQ(kHasVideo, std::get<1>(result)); |
| 126 EXPECT_EQ(kHasAudio, std::get<2>(result)); | 125 EXPECT_EQ(kHasAudio, std::get<2>(result)); |
| 127 EXPECT_EQ(kIsRemote, std::get<3>(result)); | 126 EXPECT_EQ(kIsRemote, std::get<3>(result)); |
| 128 EXPECT_EQ(kMediaContentType, std::get<4>(result)); | 127 EXPECT_EQ(kMediaContentType, std::get<4>(result)); |
| 129 } | 128 } |
| 130 | 129 |
| 131 // Verify the paused message. | 130 // Verify the paused message. |
| 132 { | 131 { |
| 133 test_sink().ClearMessages(); | 132 test_sink().ClearMessages(); |
| 134 const bool kReachedEndOfStream = true; | 133 const bool kReachedEndOfStream = false; |
| 135 delegate_manager_->DidPause(delegate_id, kReachedEndOfStream); | 134 delegate_manager_->DidPause(delegate_id); |
| 136 | 135 |
| 137 const IPC::Message* msg = test_sink().GetUniqueMessageMatching( | 136 const IPC::Message* msg = test_sink().GetUniqueMessageMatching( |
| 138 MediaPlayerDelegateHostMsg_OnMediaPaused::ID); | 137 MediaPlayerDelegateHostMsg_OnMediaPaused::ID); |
| 139 ASSERT_TRUE(msg); | 138 ASSERT_TRUE(msg); |
| 140 | 139 |
| 141 std::tuple<int, bool> result; | 140 std::tuple<int, bool> result; |
| 142 ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPaused::Read(msg, &result)); | 141 ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPaused::Read(msg, &result)); |
| 143 EXPECT_EQ(delegate_id, std::get<0>(result)); | 142 EXPECT_EQ(delegate_id, std::get<0>(result)); |
| 144 EXPECT_EQ(kReachedEndOfStream, std::get<1>(result)); | 143 EXPECT_EQ(kReachedEndOfStream, std::get<1>(result)); |
| 145 } | 144 } |
| 146 | 145 |
| 147 // Verify the destruction message. | 146 // Verify the destruction message. |
| 148 { | 147 { |
| 149 test_sink().ClearMessages(); | 148 test_sink().ClearMessages(); |
| 150 delegate_manager_->PlayerGone(delegate_id); | 149 delegate_manager_->PlayerGone(delegate_id); |
| 151 const IPC::Message* msg = test_sink().GetUniqueMessageMatching( | 150 const IPC::Message* msg = test_sink().GetUniqueMessageMatching( |
| 152 MediaPlayerDelegateHostMsg_OnMediaDestroyed::ID); | 151 MediaPlayerDelegateHostMsg_OnMediaDestroyed::ID); |
| 153 ASSERT_TRUE(msg); | 152 ASSERT_TRUE(msg); |
| 154 | 153 |
| 155 std::tuple<int> result; | 154 std::tuple<int> result; |
| 156 ASSERT_TRUE( | 155 ASSERT_TRUE( |
| 157 MediaPlayerDelegateHostMsg_OnMediaDestroyed::Read(msg, &result)); | 156 MediaPlayerDelegateHostMsg_OnMediaDestroyed::Read(msg, &result)); |
| 158 EXPECT_EQ(delegate_id, std::get<0>(result)); | 157 EXPECT_EQ(delegate_id, std::get<0>(result)); |
| 159 } | 158 } |
| 160 } | 159 } |
| 161 | 160 |
| 162 TEST_F(RendererWebMediaPlayerDelegateTest, DeliversObserverNotifications) { | 161 TEST_F(RendererWebMediaPlayerDelegateTest, DeliversObserverNotifications) { |
| 163 const int delegate_id = delegate_manager_->AddObserver(&observer_1_); | 162 const int delegate_id = delegate_manager_->AddObserver(&observer_1_); |
| 164 | 163 |
| 165 EXPECT_CALL(observer_1_, OnHidden()); | 164 EXPECT_CALL(observer_1_, OnFrameHidden()); |
| 166 delegate_manager_->WasHidden(); | 165 delegate_manager_->WasHidden(); |
| 167 | 166 |
| 168 EXPECT_CALL(observer_1_, OnShown()); | 167 EXPECT_CALL(observer_1_, OnFrameShown()); |
| 169 delegate_manager_->WasShown(); | 168 delegate_manager_->WasShown(); |
| 170 | 169 |
| 171 EXPECT_CALL(observer_1_, OnPause()); | 170 EXPECT_CALL(observer_1_, OnPause()); |
| 172 MediaPlayerDelegateMsg_Pause pause_msg(0, delegate_id); | 171 MediaPlayerDelegateMsg_Pause pause_msg(0, delegate_id); |
| 173 delegate_manager_->OnMessageReceived(pause_msg); | 172 delegate_manager_->OnMessageReceived(pause_msg); |
| 174 | 173 |
| 175 EXPECT_CALL(observer_1_, OnPlay()); | 174 EXPECT_CALL(observer_1_, OnPlay()); |
| 176 MediaPlayerDelegateMsg_Play play_msg(0, delegate_id); | 175 MediaPlayerDelegateMsg_Play play_msg(0, delegate_id); |
| 177 delegate_manager_->OnMessageReceived(play_msg); | 176 delegate_manager_->OnMessageReceived(play_msg); |
| 178 | 177 |
| 179 const double kTestMultiplier = 0.5; | 178 const double kTestMultiplier = 0.5; |
| 180 EXPECT_CALL(observer_1_, OnVolumeMultiplierUpdate(kTestMultiplier)); | 179 EXPECT_CALL(observer_1_, OnVolumeMultiplierUpdate(kTestMultiplier)); |
| 181 MediaPlayerDelegateMsg_UpdateVolumeMultiplier volume_msg(0, delegate_id, | 180 MediaPlayerDelegateMsg_UpdateVolumeMultiplier volume_msg(0, delegate_id, |
| 182 kTestMultiplier); | 181 kTestMultiplier); |
| 183 delegate_manager_->OnMessageReceived(volume_msg); | 182 delegate_manager_->OnMessageReceived(volume_msg); |
| 184 | 183 |
| 185 EXPECT_CALL(observer_1_, OnSuspendRequested(true)); | 184 EXPECT_CALL(observer_1_, OnFrameClosed()); |
| 186 MediaPlayerDelegateMsg_SuspendAllMediaPlayers suspend_msg(0); | 185 MediaPlayerDelegateMsg_SuspendAllMediaPlayers suspend_msg(0); |
| 187 delegate_manager_->OnMessageReceived(suspend_msg); | 186 delegate_manager_->OnMessageReceived(suspend_msg); |
| 188 } | 187 } |
| 189 | 188 |
| 190 TEST_F(RendererWebMediaPlayerDelegateTest, TheTimerIsInitiallyStopped) { | 189 TEST_F(RendererWebMediaPlayerDelegateTest, TheTimerIsInitiallyStopped) { |
| 191 ASSERT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting()); | 190 ASSERT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting()); |
| 192 } | 191 } |
| 193 | 192 |
| 194 TEST_F(RendererWebMediaPlayerDelegateTest, AddingAnObserverStartsTheTimer) { | 193 TEST_F(RendererWebMediaPlayerDelegateTest, AddingAnIdleObserverStartsTheTimer) { |
| 195 delegate_manager_->AddObserver(&observer_1_); | 194 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); |
| 195 delegate_manager_->SetIdle(delegate_id_1, true); |
| 196 RunLoopOnce(); |
| 196 ASSERT_TRUE(delegate_manager_->IsIdleCleanupTimerRunningForTesting()); | 197 ASSERT_TRUE(delegate_manager_->IsIdleCleanupTimerRunningForTesting()); |
| 197 } | 198 } |
| 198 | 199 |
| 199 TEST_F(RendererWebMediaPlayerDelegateTest, RemovingAllObserversStopsTheTimer) { | 200 TEST_F(RendererWebMediaPlayerDelegateTest, RemovingAllObserversStopsTheTimer) { |
| 200 delegate_manager_->RemoveObserver( | 201 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); |
| 201 delegate_manager_->AddObserver(&observer_1_)); | 202 delegate_manager_->SetIdle(delegate_id_1, true); |
| 203 RunLoopOnce(); |
| 204 delegate_manager_->RemoveObserver(delegate_id_1); |
| 205 RunLoopOnce(); |
| 202 ASSERT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting()); | 206 ASSERT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting()); |
| 203 } | 207 } |
| 204 | 208 |
| 205 TEST_F(RendererWebMediaPlayerDelegateTest, PlayingDelegatesAreNotIdle) { | |
| 206 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); | |
| 207 delegate_manager_->DidPlay(delegate_id_1, true, true, false, | |
| 208 media::MediaContentType::Persistent); | |
| 209 ASSERT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting()); | |
| 210 } | |
| 211 | |
| 212 TEST_F(RendererWebMediaPlayerDelegateTest, PlaySuspendsLowEndIdleDelegates) { | 209 TEST_F(RendererWebMediaPlayerDelegateTest, PlaySuspendsLowEndIdleDelegates) { |
| 213 SetIsLowEndDeviceForTesting(); | 210 SetIsLowEndDeviceForTesting(); |
| 214 | 211 |
| 215 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); | 212 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); |
| 216 delegate_manager_->AddObserver(&observer_2_); | 213 delegate_manager_->SetIdle(delegate_id_1, true); |
| 214 const int delegate_id_2 = delegate_manager_->AddObserver(&observer_2_); |
| 215 delegate_manager_->SetIdle(delegate_id_2, true); |
| 216 RunLoopOnce(); |
| 217 | 217 |
| 218 // Calling play on the first player should suspend the other idle player. | 218 // Calling play on the first player should suspend the other idle player. |
| 219 EXPECT_CALL(observer_2_, OnSuspendRequested(false)); | 219 EXPECT_CALL(observer_2_, OnIdleTimeout()); |
| 220 delegate_manager_->DidPlay(delegate_id_1, true, true, |
| 221 media::MediaContentType::Persistent); |
| 222 delegate_manager_->SetIdle(delegate_id_1, false); |
| 220 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(1)); | 223 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(1)); |
| 221 delegate_manager_->DidPlay(delegate_id_1, true, true, false, | 224 RunLoopOnce(); |
| 222 media::MediaContentType::Persistent); | |
| 223 } | 225 } |
| 224 | 226 |
| 225 TEST_F(RendererWebMediaPlayerDelegateTest, MaxLowEndIdleDelegates) { | 227 TEST_F(RendererWebMediaPlayerDelegateTest, MaxLowEndIdleDelegates) { |
| 226 SetIsLowEndDeviceForTesting(); | 228 SetIsLowEndDeviceForTesting(); |
| 227 | 229 |
| 228 delegate_manager_->AddObserver(&observer_1_); | 230 int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); |
| 229 delegate_manager_->AddObserver(&observer_2_); | 231 delegate_manager_->SetIdle(delegate_id_1, true); |
| 232 int delegate_id_2 = delegate_manager_->AddObserver(&observer_2_); |
| 233 delegate_manager_->SetIdle(delegate_id_2, true); |
| 234 RunLoopOnce(); |
| 230 | 235 |
| 231 // Just adding a third idle observer should suspend the others. | 236 // Just adding a third idle observer should suspend all idle players. |
| 232 EXPECT_CALL(observer_1_, OnSuspendRequested(false)); | 237 EXPECT_CALL(observer_1_, OnIdleTimeout()); |
| 233 EXPECT_CALL(observer_2_, OnSuspendRequested(false)); | 238 EXPECT_CALL(observer_2_, OnIdleTimeout()); |
| 239 int delegate_id_3 = delegate_manager_->AddObserver(&observer_3_); |
| 240 delegate_manager_->SetIdle(delegate_id_3, true); |
| 241 EXPECT_CALL(observer_3_, OnIdleTimeout()); |
| 234 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(1)); | 242 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(1)); |
| 235 delegate_manager_->AddObserver(&observer_3_); | 243 RunLoopOnce(); |
| 236 } | |
| 237 | |
| 238 // Make sure it's safe to call DidPause(), which modifies the idle delegate | |
| 239 // list, from OnSuspendRequested(), which iterates over the idle delegate list. | |
| 240 TEST_F(RendererWebMediaPlayerDelegateTest, ReentrantDelegateCallsAreSafe) { | |
| 241 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); | |
| 242 EXPECT_CALL(observer_1_, OnSuspendRequested(false)) | |
| 243 .WillOnce(RunClosure(base::Bind(&RendererWebMediaPlayerDelegate::DidPause, | |
| 244 base::Unretained(delegate_manager_.get()), | |
| 245 delegate_id_1, false))); | |
| 246 // Run an idle cleanup. | |
| 247 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); | |
| 248 base::RunLoop().RunUntilIdle(); | |
| 249 } | 244 } |
| 250 | 245 |
| 251 TEST_F(RendererWebMediaPlayerDelegateTest, | 246 TEST_F(RendererWebMediaPlayerDelegateTest, |
| 252 SuspendRequestsAreOnlySentOnceIfHandled) { | 247 SuspendRequestsAreOnlySentOnceIfHandled) { |
| 253 delegate_manager_->AddObserver(&observer_1_); | 248 int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); |
| 254 // Return true from OnSuspendRequested() to indicate that it was handled. So | 249 delegate_manager_->SetIdle(delegate_id_1, true); |
| 255 // even though the player did not call PlayerGone() it should be removed from | 250 EXPECT_CALL(observer_1_, OnIdleTimeout()); |
| 256 // future idle cleanup polls. | |
| 257 EXPECT_CALL(observer_1_, OnSuspendRequested(false)).WillOnce(Return(true)); | |
| 258 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); | 251 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); |
| 259 base::RunLoop().RunUntilIdle(); | 252 base::RunLoop().RunUntilIdle(); |
| 260 } | 253 } |
| 261 | |
| 262 TEST_F(RendererWebMediaPlayerDelegateTest, | |
| 263 SuspendRequestsAreSentAgainIfNotHandled) { | |
| 264 delegate_manager_->AddObserver(&observer_1_); | |
| 265 // Return false from OnSuspendRequested() to indicate that it was not handled. | |
| 266 // The observer should get another OnSuspendRequested. | |
| 267 EXPECT_CALL(observer_1_, OnSuspendRequested(false)) | |
| 268 .WillOnce(Return(false)) | |
| 269 .WillOnce(Return(true)); | |
| 270 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); | |
| 271 base::RunLoop().RunUntilIdle(); | |
| 272 } | |
| 273 | 254 |
| 274 TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesAreSuspended) { | 255 TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesAreSuspended) { |
| 275 // Add one non-idle observer and one idle observer. | 256 // Add one non-idle observer and one idle observer. |
| 276 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); | 257 const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1_); |
| 277 delegate_manager_->DidPlay(delegate_id_1, true, true, false, | 258 const int delegate_id_2 = delegate_manager_->AddObserver(&observer_2_); |
| 278 media::MediaContentType::Persistent); | 259 delegate_manager_->SetIdle(delegate_id_2, true); |
| 279 delegate_manager_->AddObserver(&observer_2_); | |
| 280 | 260 |
| 281 // The idle cleanup task should suspend the second delegate while the first is | 261 // The idle cleanup task should suspend the second delegate while the first is |
| 282 // kept alive. | 262 // kept alive. |
| 283 { | 263 { |
| 284 EXPECT_CALL(observer_2_, OnSuspendRequested(false)).WillOnce(Return(true)); | 264 EXPECT_CALL(observer_2_, OnIdleTimeout()); |
| 285 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); | 265 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); |
| 286 base::RunLoop().RunUntilIdle(); | 266 RunLoopOnce(); |
| 287 } | 267 } |
| 288 | 268 |
| 289 // Pausing should count as idle if playback didn't reach end of stream, but | 269 // Once the player is idle, it should be suspended after |kIdleTimeout|. |
| 290 // in this case the player will not remove the MediaSession. | 270 delegate_manager_->SetIdle(delegate_id_1, true); |
| 291 delegate_manager_->DidPause(delegate_id_1, false /* reached_end_of_stream */); | |
| 292 const int delegate_id_3 = delegate_manager_->AddObserver(&observer_3_); | |
| 293 delegate_manager_->DidPlay(delegate_id_3, true, true, false, | |
| 294 media::MediaContentType::Persistent); | |
| 295 | |
| 296 // Adding the observer should instantly queue the timeout task. Once run only | |
| 297 // the first player should be suspended. | |
| 298 { | 271 { |
| 299 EXPECT_CALL(observer_1_, OnSuspendRequested(false)).WillOnce(Return(true)); | 272 EXPECT_CALL(observer_1_, OnIdleTimeout()); |
| 300 base::RunLoop run_loop; | |
| 301 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
| 302 run_loop.QuitClosure()); | |
| 303 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); | 273 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); |
| 304 run_loop.Run(); | 274 RunLoopOnce(); |
| 305 } | |
| 306 | |
| 307 delegate_manager_->DidPlay(delegate_id_1, true, true, false, | |
| 308 media::MediaContentType::Persistent); | |
| 309 | |
| 310 // Pausing after reaching end of stream should count as idle. | |
| 311 delegate_manager_->DidPause(delegate_id_1, true /* reached_end_of_stream */); | |
| 312 | |
| 313 // Once the timeout task runs the first delegate should be suspended while the | |
| 314 // third is kept alive. | |
| 315 { | |
| 316 EXPECT_CALL(observer_1_, OnSuspendRequested(false)).WillOnce(Return(true)); | |
| 317 base::RunLoop run_loop; | |
| 318 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
| 319 run_loop.QuitClosure()); | |
| 320 tick_clock_.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1)); | |
| 321 run_loop.Run(); | |
| 322 } | 275 } |
| 323 } | 276 } |
| 324 | 277 |
| 325 TEST_F(RendererWebMediaPlayerDelegateTest, PlayingVideosSet) { | 278 TEST_F(RendererWebMediaPlayerDelegateTest, IsBackgroundVideoPlaybackUnlocked) { |
| 326 int delegate_id = delegate_manager_->AddObserver(&observer_1_); | |
| 327 EXPECT_FALSE(HasPlayingVideo(delegate_id)); | |
| 328 | |
| 329 // Playing a local video adds it to the set. | |
| 330 delegate_manager_->DidPlay(delegate_id, true, true, false, | |
| 331 MediaContentType::Persistent); | |
| 332 EXPECT_TRUE(HasPlayingVideo(delegate_id)); | |
| 333 | |
| 334 // Pause doesn't remove the video from the set. | |
| 335 delegate_manager_->DidPause(delegate_id, false); | |
| 336 EXPECT_TRUE(HasPlayingVideo(delegate_id)); | |
| 337 | |
| 338 // Reaching the end removes the video from the set. | |
| 339 delegate_manager_->DidPause(delegate_id, true); | |
| 340 EXPECT_FALSE(HasPlayingVideo(delegate_id)); | |
| 341 | |
| 342 // Removing the player removes the video from the set. | |
| 343 delegate_manager_->DidPlay(delegate_id, true, true, false, | |
| 344 MediaContentType::Persistent); | |
| 345 delegate_manager_->PlayerGone(delegate_id); | |
| 346 EXPECT_FALSE(HasPlayingVideo(delegate_id)); | |
| 347 | |
| 348 // Playing a remote video removes it from the set. | |
| 349 delegate_manager_->DidPlay(delegate_id, true, true, false, | |
| 350 MediaContentType::Persistent); | |
| 351 delegate_manager_->DidPlay(delegate_id, true, true, true, | |
| 352 MediaContentType::Persistent); | |
| 353 EXPECT_FALSE(HasPlayingVideo(delegate_id)); | |
| 354 | |
| 355 // Playing a local video without audio adds it to the set (because of WMPA). | |
| 356 delegate_manager_->DidPlay(delegate_id, true, false, false, | |
| 357 MediaContentType::Persistent); | |
| 358 EXPECT_TRUE(HasPlayingVideo(delegate_id)); | |
| 359 | |
| 360 // Playing a local audio removes it from the set. | |
| 361 delegate_manager_->DidPlay(delegate_id, false, true, false, | |
| 362 MediaContentType::Persistent); | |
| 363 EXPECT_FALSE(HasPlayingVideo(delegate_id)); | |
| 364 | |
| 365 // Removing the observer also removes the video from the set. | |
| 366 delegate_manager_->DidPlay(delegate_id, true, true, false, | |
| 367 MediaContentType::Persistent); | |
| 368 delegate_manager_->RemoveObserver(delegate_id); | |
| 369 EXPECT_FALSE(HasPlayingVideo(delegate_id)); | |
| 370 } | |
| 371 | |
| 372 TEST_F(RendererWebMediaPlayerDelegateTest, IsPlayingBackgroundVideo) { | |
| 373 NiceMock<MockWebMediaPlayerDelegateObserver> observer; | 279 NiceMock<MockWebMediaPlayerDelegateObserver> observer; |
| 374 int delegate_id = delegate_manager_->AddObserver(&observer); | 280 int delegate_id = delegate_manager_->AddObserver(&observer); |
| 375 EXPECT_FALSE(delegate_manager_->IsPlayingBackgroundVideo()); | 281 EXPECT_FALSE(delegate_manager_->IsBackgroundVideoPlaybackUnlocked()); |
| 376 | 282 |
| 377 // Showing the frame always clears the flag. | 283 // Showing the frame always clears the flag. |
| 378 SetPlayingBackgroundVideo(true); | 284 SetBackgroundVideoPlaybackUnlocked(true); |
| 379 delegate_manager_->WasShown(); | 285 delegate_manager_->WasShown(); |
| 380 EXPECT_FALSE(delegate_manager_->IsPlayingBackgroundVideo()); | 286 EXPECT_FALSE(delegate_manager_->IsBackgroundVideoPlaybackUnlocked()); |
| 381 | |
| 382 // Pausing anything other than a local playing video doesn't affect the flag. | |
| 383 SetPlayingBackgroundVideo(true); | |
| 384 CallOnMediaDelegatePause(delegate_id); | |
| 385 EXPECT_TRUE(delegate_manager_->IsPlayingBackgroundVideo()); | |
| 386 | 287 |
| 387 // Pausing a currently playing video clears the flag. | 288 // Pausing a currently playing video clears the flag. |
| 388 delegate_manager_->DidPlay(delegate_id, true, true, false, | 289 delegate_manager_->DidPlay(delegate_id, true, true, |
| 389 MediaContentType::Persistent); | 290 MediaContentType::Persistent); |
| 291 SetBackgroundVideoPlaybackUnlocked(true); |
| 390 CallOnMediaDelegatePause(delegate_id); | 292 CallOnMediaDelegatePause(delegate_id); |
| 391 EXPECT_FALSE(delegate_manager_->IsPlayingBackgroundVideo()); | 293 EXPECT_FALSE(delegate_manager_->IsBackgroundVideoPlaybackUnlocked()); |
| 392 | 294 |
| 393 // TODO(avayvod): this test can't mock the IsHidden() method. | 295 // TODO(avayvod): this test can't mock the IsFrameHidden() method. |
| 394 // Just test that the value changes or doesn't depending on whether the video | 296 // Just test that the value changes or doesn't depending on whether the video |
| 395 // is currently playing. | 297 // is currently playing. |
| 396 bool old_value = !delegate_manager_->IsHidden(); | 298 if (delegate_manager_->IsFrameHidden()) { |
| 397 SetPlayingBackgroundVideo(old_value); | 299 SetBackgroundVideoPlaybackUnlocked(false); |
| 398 delegate_manager_->DidPause(delegate_id, true); | 300 CallOnMediaDelegatePlay(delegate_id); |
| 399 CallOnMediaDelegatePlay(delegate_id); | 301 EXPECT_TRUE(delegate_manager_->IsBackgroundVideoPlaybackUnlocked()); |
| 400 EXPECT_EQ(old_value, delegate_manager_->IsPlayingBackgroundVideo()); | 302 CallOnMediaDelegatePause(delegate_id); |
| 401 | 303 EXPECT_FALSE(delegate_manager_->IsBackgroundVideoPlaybackUnlocked()); |
| 402 delegate_manager_->DidPlay(delegate_id, true, true, false, | 304 } else { |
| 403 MediaContentType::Persistent); | 305 SetBackgroundVideoPlaybackUnlocked(false); |
| 404 CallOnMediaDelegatePlay(delegate_id); | 306 CallOnMediaDelegatePlay(delegate_id); |
| 405 EXPECT_NE(old_value, delegate_manager_->IsPlayingBackgroundVideo()); | 307 EXPECT_FALSE(delegate_manager_->IsBackgroundVideoPlaybackUnlocked()); |
| 308 CallOnMediaDelegatePause(delegate_id); |
| 309 EXPECT_FALSE(delegate_manager_->IsBackgroundVideoPlaybackUnlocked()); |
| 310 } |
| 406 } | 311 } |
| 407 | 312 |
| 408 #if defined(OS_ANDROID) | 313 #if defined(OS_ANDROID) |
| 409 | 314 |
| 410 TEST_F(RendererWebMediaPlayerDelegateTest, Histograms) { | 315 TEST_F(RendererWebMediaPlayerDelegateTest, Histograms) { |
| 411 NiceMock<MockWebMediaPlayerDelegateObserver> observer; | 316 NiceMock<MockWebMediaPlayerDelegateObserver> observer; |
| 412 int delegate_id = delegate_manager_->AddObserver(&observer); | 317 int delegate_id = delegate_manager_->AddObserver(&observer); |
| 413 base::HistogramTester histogram_tester; | 318 base::HistogramTester histogram_tester; |
| 414 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 0); | 319 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 0); |
| 415 | 320 |
| 416 // Pausing or showing doesn't record anything as background playback | 321 // Play/pause while not hidden doesn't record anything. |
| 417 // hasn't started yet. | 322 delegate_manager_->DidPlay(delegate_id, true, true, |
| 418 delegate_manager_->DidPlay(delegate_id, true, true, false, | |
| 419 MediaContentType::Persistent); | 323 MediaContentType::Persistent); |
| 420 CallOnMediaDelegatePause(delegate_id); | 324 RunLoopOnce(); |
| 325 delegate_manager_->DidPause(delegate_id); |
| 326 RunLoopOnce(); |
| 421 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 0); | 327 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 0); |
| 422 | 328 |
| 423 delegate_manager_->DidPlay(delegate_id, true, true, false, | 329 // Play/pause while hidden does. |
| 330 delegate_manager_->SetFrameHiddenForTesting(true); |
| 331 delegate_manager_->DidPlay(delegate_id, true, true, |
| 424 MediaContentType::Persistent); | 332 MediaContentType::Persistent); |
| 425 delegate_manager_->WasShown(); | 333 RunLoopOnce(); |
| 426 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 0); | 334 delegate_manager_->DidPause(delegate_id); |
| 427 | 335 RunLoopOnce(); |
| 428 // Doing this things after the background playback has started should record | |
| 429 // the time. | |
| 430 delegate_manager_->DidPlay(delegate_id, true, true, false, | |
| 431 MediaContentType::Persistent); | |
| 432 SetPlayingBackgroundVideo(true); | |
| 433 CallOnMediaDelegatePause(delegate_id); | |
| 434 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 1); | 336 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 1); |
| 435 | 337 |
| 436 delegate_manager_->DidPlay(delegate_id, true, true, false, | 338 // As does ending background playback by becoming visible. |
| 339 delegate_manager_->SetFrameHiddenForTesting(true); |
| 340 delegate_manager_->DidPlay(delegate_id, true, true, |
| 437 MediaContentType::Persistent); | 341 MediaContentType::Persistent); |
| 438 SetPlayingBackgroundVideo(true); | 342 RunLoopOnce(); |
| 439 delegate_manager_->WasShown(); | 343 delegate_manager_->SetFrameHiddenForTesting(false); |
| 344 RunLoopOnce(); |
| 440 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 2); | 345 histogram_tester.ExpectTotalCount("Media.Android.BackgroundVideoTime", 2); |
| 441 } | 346 } |
| 442 | 347 |
| 443 #endif // OS_ANDROID | 348 #endif // OS_ANDROID |
| 444 | 349 |
| 445 } // namespace media | 350 } // namespace media |
| OLD | NEW |