blob: 3166273cce2cb1ce25278debf4b47127f4b588bc [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
Anton Vayvod09fa66e2017-07-20 23:02:1268 void UpdateRemotePlaybackCompatibility(bool is_compatibe) override {}
69
miu9f7788e2017-01-25 00:46:0970 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
71
72 base::MessageLoop message_loop_;
73
74 protected:
75 std::unique_ptr<RendererController> controller_;
76 bool is_rendering_remotely_ = false;
77 bool is_remoting_cdm_ = false;
xjz4e5d4bf32017-02-15 21:26:3578 bool activate_viewport_intersection_monitoring_ = false;
79 bool disable_pipeline_suspend_ = false;
miu9f7788e2017-01-25 00:46:0980
81 private:
82 DISALLOW_COPY_AND_ASSIGN(RendererControllerTest);
83};
84
85TEST_F(RendererControllerTest, ToggleRendererOnFullscreenChange) {
86 EXPECT_FALSE(is_rendering_remotely_);
87 const scoped_refptr<SharedSession> shared_session =
88 FakeRemoterFactory::CreateSharedSession(false);
89 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:3590 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:0991 RunUntilIdle();
92 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:3593 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
94 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:0995 shared_session->OnSinkAvailable(kAllCapabilities);
96 RunUntilIdle();
97 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:3598 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
99 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09100 controller_->OnEnteredFullscreen();
101 RunUntilIdle();
102 EXPECT_FALSE(is_rendering_remotely_);
103 controller_->OnMetadataChanged(DefaultMetadata());
104 RunUntilIdle();
105 EXPECT_FALSE(is_rendering_remotely_);
106 controller_->OnRemotePlaybackDisabled(false);
107 RunUntilIdle();
108 EXPECT_FALSE(is_rendering_remotely_);
109 controller_->OnPlaying();
110 RunUntilIdle();
111 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
xjz4e5d4bf32017-02-15 21:26:35112 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09113
114 // Leaving fullscreen should shut down remoting.
115 controller_->OnExitedFullscreen();
116 RunUntilIdle();
117 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35118 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
119 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09120}
121
122TEST_F(RendererControllerTest, ToggleRendererOnSinkCapabilities) {
123 EXPECT_FALSE(is_rendering_remotely_);
124 const scoped_refptr<SharedSession> shared_session =
125 FakeRemoterFactory::CreateSharedSession(false);
126 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:35127 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09128 RunUntilIdle();
129 EXPECT_FALSE(is_rendering_remotely_);
130 controller_->OnMetadataChanged(DefaultMetadata());
131 RunUntilIdle();
132 EXPECT_FALSE(is_rendering_remotely_);
133 controller_->OnRemotePlaybackDisabled(false);
134 RunUntilIdle();
135 EXPECT_FALSE(is_rendering_remotely_);
136 controller_->OnPlaying();
137 RunUntilIdle();
138 EXPECT_FALSE(is_rendering_remotely_);
139 controller_->OnEnteredFullscreen();
140 RunUntilIdle();
141 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35142 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
143 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09144 // An available sink that does not support remote rendering should not cause
145 // the controller to toggle remote rendering on.
146 shared_session->OnSinkAvailable(mojom::RemotingSinkCapabilities::NONE);
147 RunUntilIdle();
148 EXPECT_FALSE(is_rendering_remotely_);
149 shared_session->OnSinkGone(); // Bye-bye useless sink!
150 RunUntilIdle();
151 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35152 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
153 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09154 // A sink that *does* support remote rendering *does* cause the controller to
155 // toggle remote rendering on.
156 shared_session->OnSinkAvailable(kAllCapabilities);
157 RunUntilIdle();
158 EXPECT_TRUE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35159 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
160 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09161 controller_->OnExitedFullscreen();
162 RunUntilIdle();
163 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35164 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
165 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09166}
167
168TEST_F(RendererControllerTest, ToggleRendererOnDisableChange) {
169 EXPECT_FALSE(is_rendering_remotely_);
170 const scoped_refptr<SharedSession> shared_session =
171 FakeRemoterFactory::CreateSharedSession(false);
172 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:35173 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09174 RunUntilIdle();
175 EXPECT_FALSE(is_rendering_remotely_);
176 controller_->OnRemotePlaybackDisabled(true);
177 RunUntilIdle();
178 EXPECT_FALSE(is_rendering_remotely_);
179 shared_session->OnSinkAvailable(kAllCapabilities);
180 RunUntilIdle();
181 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35182 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
183 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09184 controller_->OnMetadataChanged(DefaultMetadata());
185 RunUntilIdle();
186 EXPECT_FALSE(is_rendering_remotely_);
187 controller_->OnEnteredFullscreen();
188 RunUntilIdle();
189 EXPECT_FALSE(is_rendering_remotely_);
190 controller_->OnRemotePlaybackDisabled(false);
191 RunUntilIdle();
192 EXPECT_FALSE(is_rendering_remotely_);
193 controller_->OnPlaying();
194 RunUntilIdle();
195 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
xjz4e5d4bf32017-02-15 21:26:35196 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
197 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09198
199 // If the page disables remote playback (e.g., by setting the
200 // disableRemotePlayback attribute), this should shut down remoting.
201 controller_->OnRemotePlaybackDisabled(true);
202 RunUntilIdle();
203 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35204 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
205 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09206}
207
208TEST_F(RendererControllerTest, StartFailed) {
209 EXPECT_FALSE(is_rendering_remotely_);
210 const scoped_refptr<SharedSession> shared_session =
211 FakeRemoterFactory::CreateSharedSession(true);
212 controller_ = base::MakeUnique<RendererController>(shared_session);
xjz4e5d4bf32017-02-15 21:26:35213 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09214 RunUntilIdle();
215 EXPECT_FALSE(is_rendering_remotely_);
216 shared_session->OnSinkAvailable(kAllCapabilities);
217 RunUntilIdle();
218 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35219 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
220 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09221 controller_->OnEnteredFullscreen();
222 RunUntilIdle();
223 EXPECT_FALSE(is_rendering_remotely_);
224 controller_->OnMetadataChanged(DefaultMetadata());
225 RunUntilIdle();
226 EXPECT_FALSE(is_rendering_remotely_);
227 controller_->OnRemotePlaybackDisabled(false);
228 RunUntilIdle();
229 EXPECT_FALSE(is_rendering_remotely_);
230 controller_->OnPlaying();
231 RunUntilIdle();
232 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35233 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09234}
235
236TEST_F(RendererControllerTest, EncryptedWithRemotingCdm) {
237 EXPECT_FALSE(is_rendering_remotely_);
238 controller_ = base::MakeUnique<RendererController>(
239 FakeRemoterFactory::CreateSharedSession(false));
xjz4e5d4bf32017-02-15 21:26:35240 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09241 RunUntilIdle();
242 EXPECT_FALSE(is_rendering_remotely_);
243 controller_->OnMetadataChanged(EncryptedMetadata());
244 controller_->OnRemotePlaybackDisabled(false);
245 controller_->OnPlaying();
246 RunUntilIdle();
247 EXPECT_FALSE(is_rendering_remotely_);
248 const scoped_refptr<SharedSession> cdm_shared_session =
249 FakeRemoterFactory::CreateSharedSession(false);
250 std::unique_ptr<RemotingCdmController> cdm_controller =
251 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
252 cdm_shared_session->OnSinkAvailable(kAllCapabilities);
253 cdm_controller->ShouldCreateRemotingCdm(
254 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
255 RunUntilIdle();
256 EXPECT_FALSE(is_rendering_remotely_);
257 EXPECT_TRUE(is_remoting_cdm_);
258
259 // Create a RemotingCdm with |cdm_controller|.
260 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
261 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
262 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
263 std::move(cdm_controller));
264 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
265 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
266 controller_->OnSetCdm(remoting_cdm_context.get());
267 RunUntilIdle();
268 EXPECT_TRUE(is_rendering_remotely_);
269
270 // For encrypted contents, entering/exiting full screen has no effect.
271 controller_->OnEnteredFullscreen();
272 RunUntilIdle();
273 EXPECT_TRUE(is_rendering_remotely_);
274 controller_->OnExitedFullscreen();
275 RunUntilIdle();
276 EXPECT_TRUE(is_rendering_remotely_);
277
278 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
279 controller_->session()->state());
280 cdm_shared_session->OnSinkGone();
281 RunUntilIdle();
282 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
283 controller_->session()->state());
284 // Don't switch renderer in this case. Still using the remoting renderer to
285 // show the failure interstitial.
286 EXPECT_TRUE(is_rendering_remotely_);
287}
288
289TEST_F(RendererControllerTest, EncryptedWithLocalCdm) {
290 EXPECT_FALSE(is_rendering_remotely_);
291 const scoped_refptr<SharedSession> initial_shared_session =
292 FakeRemoterFactory::CreateSharedSession(false);
293 controller_ = base::MakeUnique<RendererController>(initial_shared_session);
xjz4e5d4bf32017-02-15 21:26:35294 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09295 RunUntilIdle();
296 EXPECT_FALSE(is_rendering_remotely_);
297 initial_shared_session->OnSinkAvailable(kAllCapabilities);
298 RunUntilIdle();
299 EXPECT_FALSE(is_rendering_remotely_);
300 controller_->OnEnteredFullscreen();
301 RunUntilIdle();
302 EXPECT_FALSE(is_rendering_remotely_);
303 controller_->OnMetadataChanged(EncryptedMetadata());
304 RunUntilIdle();
305 EXPECT_FALSE(is_rendering_remotely_);
306 controller_->OnRemotePlaybackDisabled(false);
307 RunUntilIdle();
308 EXPECT_FALSE(is_rendering_remotely_);
309 controller_->OnPlaying();
310 RunUntilIdle();
311 EXPECT_FALSE(is_rendering_remotely_);
312
313 const scoped_refptr<SharedSession> cdm_shared_session =
314 FakeRemoterFactory::CreateSharedSession(true);
315 std::unique_ptr<RemotingCdmController> cdm_controller =
316 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
317 cdm_shared_session->OnSinkAvailable(kAllCapabilities);
318 cdm_controller->ShouldCreateRemotingCdm(
319 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
320 RunUntilIdle();
321 EXPECT_FALSE(is_rendering_remotely_);
322 EXPECT_FALSE(is_remoting_cdm_);
323}
324
325TEST_F(RendererControllerTest, EncryptedWithFailedRemotingCdm) {
326 EXPECT_FALSE(is_rendering_remotely_);
327 controller_ = base::MakeUnique<RendererController>(
328 FakeRemoterFactory::CreateSharedSession(false));
xjz4e5d4bf32017-02-15 21:26:35329 controller_->SetClient(this);
miu9f7788e2017-01-25 00:46:09330 RunUntilIdle();
331 EXPECT_FALSE(is_rendering_remotely_);
332 controller_->OnEnteredFullscreen();
333 RunUntilIdle();
334 EXPECT_FALSE(is_rendering_remotely_);
335 controller_->OnMetadataChanged(EncryptedMetadata());
336 RunUntilIdle();
337 EXPECT_FALSE(is_rendering_remotely_);
338 controller_->OnRemotePlaybackDisabled(false);
339 RunUntilIdle();
340 EXPECT_FALSE(is_rendering_remotely_);
341 controller_->OnPlaying();
342 RunUntilIdle();
343 EXPECT_FALSE(is_rendering_remotely_);
344
345 const scoped_refptr<SharedSession> cdm_shared_session =
346 FakeRemoterFactory::CreateSharedSession(false);
347 std::unique_ptr<RemotingCdmController> cdm_controller =
348 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
349 cdm_shared_session->OnSinkAvailable(kAllCapabilities);
350 cdm_controller->ShouldCreateRemotingCdm(
351 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
352 RunUntilIdle();
353 EXPECT_FALSE(is_rendering_remotely_);
354 EXPECT_TRUE(is_remoting_cdm_);
355
356 cdm_shared_session->OnSinkGone();
357 RunUntilIdle();
358 EXPECT_FALSE(is_rendering_remotely_);
359 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
360 controller_->session()->state());
361
362 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
363 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
364 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
365 std::move(cdm_controller));
366 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
367 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
368 controller_->OnSetCdm(remoting_cdm_context.get());
369 RunUntilIdle();
370 // Switch to using the remoting renderer, even when the remoting CDM session
371 // was already terminated, to show the failure interstitial.
372 EXPECT_TRUE(is_rendering_remotely_);
373 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
374 controller_->session()->state());
375}
376
377} // namespace remoting
378} // namespace media