blob: cbc1ed0fc5ac2ca528895b5a36c276cdd068ee41 [file] [log] [blame]
miu9f7788e2017-01-25 00:46:091// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "media/remoting/renderer_controller.h"
6
7#include "base/callback.h"
8#include "base/memory/ptr_util.h"
9#include "base/message_loop/message_loop.h"
10#include "base/run_loop.h"
11#include "media/base/audio_decoder_config.h"
12#include "media/base/cdm_config.h"
13#include "media/base/limits.h"
14#include "media/base/media_util.h"
15#include "media/base/test_helpers.h"
16#include "media/base/video_decoder_config.h"
17#include "media/remoting/fake_remoter.h"
18#include "media/remoting/remoting_cdm.h"
19#include "mojo/public/cpp/bindings/strong_binding.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace media {
23namespace remoting {
24
25namespace {
26
27constexpr mojom::RemotingSinkCapabilities kAllCapabilities =
28 mojom::RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING;
29
30PipelineMetadata DefaultMetadata() {
31 PipelineMetadata data;
32 data.has_audio = true;
33 data.has_video = true;
34 data.video_decoder_config = TestVideoConfig::Normal();
35 return data;
36}
37
38PipelineMetadata EncryptedMetadata() {
39 PipelineMetadata data;
40 data.has_audio = true;
41 data.has_video = true;
42 data.video_decoder_config = TestVideoConfig::NormalEncrypted();
43 return data;
44}
45
46} // namespace
47
xjz4e5d4bf32017-02-15 21:26:3548class RendererControllerTest : public ::testing::Test,
49 public MediaObserverClient {
miu9f7788e2017-01-25 00:46:0950 public:
51 RendererControllerTest() {}
52 ~RendererControllerTest() override {}
53
54 void TearDown() final { RunUntilIdle(); }
55
56 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
57
xjz4e5d4bf32017-02-15 21:26:3558 // MediaObserverClient implementation.
59 void SwitchRenderer(bool disable_pipeline_auto_suspend) override {
miu9f7788e2017-01-25 00:46:0960 is_rendering_remotely_ = controller_->remote_rendering_started();
xjz4e5d4bf32017-02-15 21:26:3561 disable_pipeline_suspend_ = disable_pipeline_auto_suspend;
62 }
63
64 void ActivateViewportIntersectionMonitoring(bool activate) override {
65 activate_viewport_intersection_monitoring_ = activate;
miu9f7788e2017-01-25 00:46:0966 }
67
68 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
69
70 base::MessageLoop message_loop_;
71
72 protected:
73 std::unique_ptr<RendererController> controller_;
74 bool is_rendering_remotely_ = false;
75 bool is_remoting_cdm_ = false;
xjz4e5d4bf32017-02-15 21:26:3576 bool activate_viewport_intersection_monitoring_ = false;
77 bool disable_pipeline_suspend_ = false;
miu9f7788e2017-01-25 00:46:0978
79 private:
80 DISALLOW_COPY_AND_ASSIGN(RendererControllerTest);
81};
82
83TEST_F(RendererControllerTest, ToggleRendererOnFullscreenChange) {
84 EXPECT_FALSE(is_rendering_remotely_);
85 const scoped_refptr<SharedSession> shared_session =
86 FakeRemoterFactory::CreateSharedSession(false);
87 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:3588 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:0989 RunUntilIdle();
90 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:3591 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
92 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:0993 shared_session->OnSinkAvailable(kAllCapabilities);
94 RunUntilIdle();
95 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:3596 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
97 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:0998 controller_->OnEnteredFullscreen();
99 RunUntilIdle();
100 EXPECT_FALSE(is_rendering_remotely_);
101 controller_->OnMetadataChanged(DefaultMetadata());
102 RunUntilIdle();
103 EXPECT_FALSE(is_rendering_remotely_);
104 controller_->OnRemotePlaybackDisabled(false);
105 RunUntilIdle();
106 EXPECT_FALSE(is_rendering_remotely_);
107 controller_->OnPlaying();
108 RunUntilIdle();
109 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
xjz4e5d4bf32017-02-15 21:26:35110 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09111
112 // Leaving fullscreen should shut down remoting.
113 controller_->OnExitedFullscreen();
114 RunUntilIdle();
115 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35116 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
117 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09118}
119
120TEST_F(RendererControllerTest, ToggleRendererOnSinkCapabilities) {
121 EXPECT_FALSE(is_rendering_remotely_);
122 const scoped_refptr<SharedSession> shared_session =
123 FakeRemoterFactory::CreateSharedSession(false);
124 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:35125 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09126 RunUntilIdle();
127 EXPECT_FALSE(is_rendering_remotely_);
128 controller_->OnMetadataChanged(DefaultMetadata());
129 RunUntilIdle();
130 EXPECT_FALSE(is_rendering_remotely_);
131 controller_->OnRemotePlaybackDisabled(false);
132 RunUntilIdle();
133 EXPECT_FALSE(is_rendering_remotely_);
134 controller_->OnPlaying();
135 RunUntilIdle();
136 EXPECT_FALSE(is_rendering_remotely_);
137 controller_->OnEnteredFullscreen();
138 RunUntilIdle();
139 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35140 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
141 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09142 // An available sink that does not support remote rendering should not cause
143 // the controller to toggle remote rendering on.
144 shared_session->OnSinkAvailable(mojom::RemotingSinkCapabilities::NONE);
145 RunUntilIdle();
146 EXPECT_FALSE(is_rendering_remotely_);
147 shared_session->OnSinkGone(); // Bye-bye useless sink!
148 RunUntilIdle();
149 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35150 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
151 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09152 // A sink that *does* support remote rendering *does* cause the controller to
153 // toggle remote rendering on.
154 shared_session->OnSinkAvailable(kAllCapabilities);
155 RunUntilIdle();
156 EXPECT_TRUE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35157 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
158 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09159 controller_->OnExitedFullscreen();
160 RunUntilIdle();
161 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35162 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
163 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09164}
165
166TEST_F(RendererControllerTest, ToggleRendererOnDisableChange) {
167 EXPECT_FALSE(is_rendering_remotely_);
168 const scoped_refptr<SharedSession> shared_session =
169 FakeRemoterFactory::CreateSharedSession(false);
170 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:35171 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09172 RunUntilIdle();
173 EXPECT_FALSE(is_rendering_remotely_);
174 controller_->OnRemotePlaybackDisabled(true);
175 RunUntilIdle();
176 EXPECT_FALSE(is_rendering_remotely_);
177 shared_session->OnSinkAvailable(kAllCapabilities);
178 RunUntilIdle();
179 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35180 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
181 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09182 controller_->OnMetadataChanged(DefaultMetadata());
183 RunUntilIdle();
184 EXPECT_FALSE(is_rendering_remotely_);
185 controller_->OnEnteredFullscreen();
186 RunUntilIdle();
187 EXPECT_FALSE(is_rendering_remotely_);
188 controller_->OnRemotePlaybackDisabled(false);
189 RunUntilIdle();
190 EXPECT_FALSE(is_rendering_remotely_);
191 controller_->OnPlaying();
192 RunUntilIdle();
193 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
xjz4e5d4bf32017-02-15 21:26:35194 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
195 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09196
197 // If the page disables remote playback (e.g., by setting the
198 // disableRemotePlayback attribute), this should shut down remoting.
199 controller_->OnRemotePlaybackDisabled(true);
200 RunUntilIdle();
201 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35202 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
203 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09204}
205
206TEST_F(RendererControllerTest, StartFailed) {
207 EXPECT_FALSE(is_rendering_remotely_);
208 const scoped_refptr<SharedSession> shared_session =
209 FakeRemoterFactory::CreateSharedSession(true);
210 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:35211 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09212 RunUntilIdle();
213 EXPECT_FALSE(is_rendering_remotely_);
214 shared_session->OnSinkAvailable(kAllCapabilities);
215 RunUntilIdle();
216 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35217 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
218 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09219 controller_->OnEnteredFullscreen();
220 RunUntilIdle();
221 EXPECT_FALSE(is_rendering_remotely_);
222 controller_->OnMetadataChanged(DefaultMetadata());
223 RunUntilIdle();
224 EXPECT_FALSE(is_rendering_remotely_);
225 controller_->OnRemotePlaybackDisabled(false);
226 RunUntilIdle();
227 EXPECT_FALSE(is_rendering_remotely_);
228 controller_->OnPlaying();
229 RunUntilIdle();
230 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35231 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09232}
233
234TEST_F(RendererControllerTest, EncryptedWithRemotingCdm) {
235 EXPECT_FALSE(is_rendering_remotely_);
236 controller_ = base::MakeUnique<RendererController>(
237 FakeRemoterFactory::CreateSharedSession(false));
xjz4e5d4bf32017-02-15 21:26:35238 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09239 RunUntilIdle();
240 EXPECT_FALSE(is_rendering_remotely_);
241 controller_->OnMetadataChanged(EncryptedMetadata());
242 controller_->OnRemotePlaybackDisabled(false);
243 controller_->OnPlaying();
244 RunUntilIdle();
245 EXPECT_FALSE(is_rendering_remotely_);
246 const scoped_refptr<SharedSession> cdm_shared_session =
247 FakeRemoterFactory::CreateSharedSession(false);
248 std::unique_ptr<RemotingCdmController> cdm_controller =
249 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
250 cdm_shared_session->OnSinkAvailable(kAllCapabilities);
251 cdm_controller->ShouldCreateRemotingCdm(
252 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
253 RunUntilIdle();
254 EXPECT_FALSE(is_rendering_remotely_);
255 EXPECT_TRUE(is_remoting_cdm_);
256
257 // Create a RemotingCdm with |cdm_controller|.
258 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
259 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
260 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
261 std::move(cdm_controller));
262 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
263 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
264 controller_->OnSetCdm(remoting_cdm_context.get());
265 RunUntilIdle();
266 EXPECT_TRUE(is_rendering_remotely_);
267
268 // For encrypted contents, entering/exiting full screen has no effect.
269 controller_->OnEnteredFullscreen();
270 RunUntilIdle();
271 EXPECT_TRUE(is_rendering_remotely_);
272 controller_->OnExitedFullscreen();
273 RunUntilIdle();
274 EXPECT_TRUE(is_rendering_remotely_);
275
276 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
277 controller_->session()->state());
278 cdm_shared_session->OnSinkGone();
279 RunUntilIdle();
280 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
281 controller_->session()->state());
282 // Don't switch renderer in this case. Still using the remoting renderer to
283 // show the failure interstitial.
284 EXPECT_TRUE(is_rendering_remotely_);
285}
286
287TEST_F(RendererControllerTest, EncryptedWithLocalCdm) {
288 EXPECT_FALSE(is_rendering_remotely_);
289 const scoped_refptr<SharedSession> initial_shared_session =
290 FakeRemoterFactory::CreateSharedSession(false);
291 controller_ = base::MakeUnique<RendererController>(initial_shared_session);
xjz4e5d4bf32017-02-15 21:26:35292 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09293 RunUntilIdle();
294 EXPECT_FALSE(is_rendering_remotely_);
295 initial_shared_session->OnSinkAvailable(kAllCapabilities);
296 RunUntilIdle();
297 EXPECT_FALSE(is_rendering_remotely_);
298 controller_->OnEnteredFullscreen();
299 RunUntilIdle();
300 EXPECT_FALSE(is_rendering_remotely_);
301 controller_->OnMetadataChanged(EncryptedMetadata());
302 RunUntilIdle();
303 EXPECT_FALSE(is_rendering_remotely_);
304 controller_->OnRemotePlaybackDisabled(false);
305 RunUntilIdle();
306 EXPECT_FALSE(is_rendering_remotely_);
307 controller_->OnPlaying();
308 RunUntilIdle();
309 EXPECT_FALSE(is_rendering_remotely_);
310
311 const scoped_refptr<SharedSession> cdm_shared_session =
312 FakeRemoterFactory::CreateSharedSession(true);
313 std::unique_ptr<RemotingCdmController> cdm_controller =
314 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
315 cdm_shared_session->OnSinkAvailable(kAllCapabilities);
316 cdm_controller->ShouldCreateRemotingCdm(
317 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
318 RunUntilIdle();
319 EXPECT_FALSE(is_rendering_remotely_);
320 EXPECT_FALSE(is_remoting_cdm_);
321}
322
323TEST_F(RendererControllerTest, EncryptedWithFailedRemotingCdm) {
324 EXPECT_FALSE(is_rendering_remotely_);
325 controller_ = base::MakeUnique<RendererController>(
326 FakeRemoterFactory::CreateSharedSession(false));
xjz4e5d4bf32017-02-15 21:26:35327 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09328 RunUntilIdle();
329 EXPECT_FALSE(is_rendering_remotely_);
330 controller_->OnEnteredFullscreen();
331 RunUntilIdle();
332 EXPECT_FALSE(is_rendering_remotely_);
333 controller_->OnMetadataChanged(EncryptedMetadata());
334 RunUntilIdle();
335 EXPECT_FALSE(is_rendering_remotely_);
336 controller_->OnRemotePlaybackDisabled(false);
337 RunUntilIdle();
338 EXPECT_FALSE(is_rendering_remotely_);
339 controller_->OnPlaying();
340 RunUntilIdle();
341 EXPECT_FALSE(is_rendering_remotely_);
342
343 const scoped_refptr<SharedSession> cdm_shared_session =
344 FakeRemoterFactory::CreateSharedSession(false);
345 std::unique_ptr<RemotingCdmController> cdm_controller =
346 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
347 cdm_shared_session->OnSinkAvailable(kAllCapabilities);
348 cdm_controller->ShouldCreateRemotingCdm(
349 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
350 RunUntilIdle();
351 EXPECT_FALSE(is_rendering_remotely_);
352 EXPECT_TRUE(is_remoting_cdm_);
353
354 cdm_shared_session->OnSinkGone();
355 RunUntilIdle();
356 EXPECT_FALSE(is_rendering_remotely_);
357 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
358 controller_->session()->state());
359
360 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
361 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
362 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
363 std::move(cdm_controller));
364 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
365 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
366 controller_->OnSetCdm(remoting_cdm_context.get());
367 RunUntilIdle();
368 // Switch to using the remoting renderer, even when the remoting CDM session
369 // was already terminated, to show the failure interstitial.
370 EXPECT_TRUE(is_rendering_remotely_);
371 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
372 controller_->session()->state());
373}
374
375} // namespace remoting
376} // namespace media