blob: 39f44e03950d23d77ca4e83bd95b3deed2b41f9e [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
Xiangjun Zhang6dc11102017-07-24 23:49:1127PipelineMetadata DefaultMetadata(VideoCodec codec) {
miu9f7788e2017-01-25 00:46:0928 PipelineMetadata data;
29 data.has_audio = true;
30 data.has_video = true;
Xiangjun Zhang6dc11102017-07-24 23:49:1131 data.video_decoder_config = TestVideoConfig::Normal(codec);
32 data.audio_decoder_config = TestAudioConfig::Normal();
miu9f7788e2017-01-25 00:46:0933 return data;
34}
35
36PipelineMetadata EncryptedMetadata() {
37 PipelineMetadata data;
38 data.has_audio = true;
39 data.has_video = true;
40 data.video_decoder_config = TestVideoConfig::NormalEncrypted();
41 return data;
42}
43
Xiangjun Zhang6dc11102017-07-24 23:49:1144mojom::RemotingSinkMetadata GetDefaultSinkMetadata(bool enable) {
45 mojom::RemotingSinkMetadata metadata;
46 if (enable) {
47 metadata.features.push_back(mojom::RemotingSinkFeature::RENDERING);
48 metadata.features.push_back(mojom::RemotingSinkFeature::CONTENT_DECRYPTION);
49 } else {
50 metadata.features.clear();
51 }
52 metadata.video_capabilities.push_back(
53 mojom::RemotingSinkVideoCapability::CODEC_VP8);
54 metadata.audio_capabilities.push_back(
55 mojom::RemotingSinkAudioCapability::CODEC_BASELINE_SET);
56 return metadata;
57}
58
miu9f7788e2017-01-25 00:46:0959} // namespace
60
xjz4e5d4bf32017-02-15 21:26:3561class RendererControllerTest : public ::testing::Test,
62 public MediaObserverClient {
miu9f7788e2017-01-25 00:46:0963 public:
64 RendererControllerTest() {}
65 ~RendererControllerTest() override {}
66
67 void TearDown() final { RunUntilIdle(); }
68
69 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
70
xjz4e5d4bf32017-02-15 21:26:3571 // MediaObserverClient implementation.
72 void SwitchRenderer(bool disable_pipeline_auto_suspend) override {
Xiangjun Zhangb8ccb2012017-07-24 21:44:2173 is_rendering_remotely_ = disable_pipeline_auto_suspend;
xjz4e5d4bf32017-02-15 21:26:3574 disable_pipeline_suspend_ = disable_pipeline_auto_suspend;
75 }
76
77 void ActivateViewportIntersectionMonitoring(bool activate) override {
78 activate_viewport_intersection_monitoring_ = activate;
miu9f7788e2017-01-25 00:46:0979 }
80
Anton Vayvod09fa66e2017-07-20 23:02:1281 void UpdateRemotePlaybackCompatibility(bool is_compatibe) override {}
82
miu9f7788e2017-01-25 00:46:0983 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
84
Xiangjun Zhangc92ec9b2017-07-25 21:56:4285 void InitializeControllerAndBecomeDominant(
Xiangjun Zhang6dc11102017-07-24 23:49:1186 const scoped_refptr<SharedSession> shared_session,
87 const PipelineMetadata& pipeline_metadata,
88 const mojom::RemotingSinkMetadata& sink_metadata) {
89 EXPECT_FALSE(is_rendering_remotely_);
90 controller_ = base::MakeUnique<RendererController>(shared_session);
91 controller_->SetClient(this);
92 RunUntilIdle();
93 EXPECT_FALSE(is_rendering_remotely_);
94 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
95 EXPECT_FALSE(disable_pipeline_suspend_);
96 shared_session->OnSinkAvailable(sink_metadata.Clone());
97 RunUntilIdle();
98 EXPECT_FALSE(is_rendering_remotely_);
99 EXPECT_FALSE(disable_pipeline_suspend_);
100 controller_->OnRemotePlaybackDisabled(false);
101 RunUntilIdle();
102 EXPECT_FALSE(is_rendering_remotely_);
103 EXPECT_FALSE(disable_pipeline_suspend_);
104 controller_->OnMetadataChanged(pipeline_metadata);
105 RunUntilIdle();
106 EXPECT_FALSE(is_rendering_remotely_);
107 EXPECT_FALSE(disable_pipeline_suspend_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42108 controller_->OnBecameDominantVisibleContent(true);
Xiangjun Zhang6dc11102017-07-24 23:49:11109 RunUntilIdle();
110 EXPECT_FALSE(is_rendering_remotely_);
111 EXPECT_FALSE(disable_pipeline_suspend_);
112 controller_->OnPlaying();
113 RunUntilIdle();
114 }
115
Xiangjun Zhangc92ec9b2017-07-25 21:56:42116 bool IsInDelayedStart() {
117 return controller_->delayed_start_stability_timer_.IsRunning();
118 }
119
120 void DelayedStartEnds() {
121 EXPECT_TRUE(IsInDelayedStart());
122 const base::Closure callback =
123 controller_->delayed_start_stability_timer_.user_task();
124 callback.Run();
125 controller_->delayed_start_stability_timer_.Stop();
126 }
127
miu9f7788e2017-01-25 00:46:09128 base::MessageLoop message_loop_;
129
130 protected:
131 std::unique_ptr<RendererController> controller_;
132 bool is_rendering_remotely_ = false;
133 bool is_remoting_cdm_ = false;
xjz4e5d4bf32017-02-15 21:26:35134 bool activate_viewport_intersection_monitoring_ = false;
135 bool disable_pipeline_suspend_ = false;
miu9f7788e2017-01-25 00:46:09136
137 private:
138 DISALLOW_COPY_AND_ASSIGN(RendererControllerTest);
139};
140
Xiangjun Zhangc92ec9b2017-07-25 21:56:42141TEST_F(RendererControllerTest, ToggleRendererOnDominantChange) {
miu9f7788e2017-01-25 00:46:09142 const scoped_refptr<SharedSession> shared_session =
143 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42144 InitializeControllerAndBecomeDominant(shared_session,
145 DefaultMetadata(VideoCodec::kCodecVP8),
146 GetDefaultSinkMetadata(true));
147 EXPECT_FALSE(is_rendering_remotely_);
148 EXPECT_TRUE(IsInDelayedStart());
149 DelayedStartEnds();
150 RunUntilIdle();
miu9f7788e2017-01-25 00:46:09151 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
xjz4e5d4bf32017-02-15 21:26:35152 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09153
154 // Leaving fullscreen should shut down remoting.
Xiangjun Zhangc92ec9b2017-07-25 21:56:42155 controller_->OnBecameDominantVisibleContent(false);
miu9f7788e2017-01-25 00:46:09156 RunUntilIdle();
157 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35158 EXPECT_FALSE(disable_pipeline_suspend_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42159 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
miu9f7788e2017-01-25 00:46:09160}
161
162TEST_F(RendererControllerTest, ToggleRendererOnSinkCapabilities) {
163 EXPECT_FALSE(is_rendering_remotely_);
164 const scoped_refptr<SharedSession> shared_session =
165 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42166 InitializeControllerAndBecomeDominant(shared_session,
167 DefaultMetadata(VideoCodec::kCodecVP8),
168 GetDefaultSinkMetadata(false));
miu9f7788e2017-01-25 00:46:09169 // An available sink that does not support remote rendering should not cause
170 // the controller to toggle remote rendering on.
miu9f7788e2017-01-25 00:46:09171 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42172 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
miu9f7788e2017-01-25 00:46:09173 shared_session->OnSinkGone(); // Bye-bye useless sink!
174 RunUntilIdle();
175 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35176 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
177 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09178 // A sink that *does* support remote rendering *does* cause the controller to
179 // toggle remote rendering on.
Xiangjun Zhang6dc11102017-07-24 23:49:11180 shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09181 RunUntilIdle();
xjz4e5d4bf32017-02-15 21:26:35182 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42183 EXPECT_FALSE(is_rendering_remotely_);
184 controller_->OnBecameDominantVisibleContent(true);
185 RunUntilIdle();
186 EXPECT_FALSE(is_rendering_remotely_);
187 EXPECT_FALSE(disable_pipeline_suspend_);
188 EXPECT_TRUE(IsInDelayedStart());
189 DelayedStartEnds();
190 RunUntilIdle();
191 EXPECT_TRUE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35192 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09193}
194
195TEST_F(RendererControllerTest, ToggleRendererOnDisableChange) {
196 EXPECT_FALSE(is_rendering_remotely_);
197 const scoped_refptr<SharedSession> shared_session =
198 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42199 InitializeControllerAndBecomeDominant(shared_session,
200 DefaultMetadata(VideoCodec::kCodecVP8),
201 GetDefaultSinkMetadata(true));
xjz4e5d4bf32017-02-15 21:26:35202 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42203 EXPECT_TRUE(IsInDelayedStart());
204 DelayedStartEnds();
205 RunUntilIdle();
206 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
xjz4e5d4bf32017-02-15 21:26:35207 EXPECT_TRUE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09208
209 // If the page disables remote playback (e.g., by setting the
210 // disableRemotePlayback attribute), this should shut down remoting.
211 controller_->OnRemotePlaybackDisabled(true);
212 RunUntilIdle();
213 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35214 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
215 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09216}
217
Xiangjun Zhang6dc11102017-07-24 23:49:11218TEST_F(RendererControllerTest, WithVP9VideoCodec) {
miu9f7788e2017-01-25 00:46:09219 const scoped_refptr<SharedSession> shared_session =
Xiangjun Zhang6dc11102017-07-24 23:49:11220 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42221 InitializeControllerAndBecomeDominant(shared_session,
222 DefaultMetadata(VideoCodec::kCodecVP9),
223 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11224 // An available sink that does not support VP9 video codec should not cause
225 // the controller to toggle remote rendering on.
miu9f7788e2017-01-25 00:46:09226 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35227 EXPECT_FALSE(disable_pipeline_suspend_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42228 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
Xiangjun Zhang6dc11102017-07-24 23:49:11229
230 shared_session->OnSinkGone(); // Bye-bye useless sink!
Xiangjun Zhang6dc11102017-07-24 23:49:11231 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
232 sink_metadata.video_capabilities.push_back(
233 mojom::RemotingSinkVideoCapability::CODEC_VP9);
234 // A sink that *does* support VP9 video codec *does* cause the controller to
235 // toggle remote rendering on.
236 shared_session->OnSinkAvailable(sink_metadata.Clone());
237 RunUntilIdle();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42238 EXPECT_TRUE(IsInDelayedStart());
239 DelayedStartEnds();
240 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11241 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
242 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
243 EXPECT_TRUE(disable_pipeline_suspend_);
244}
245
246TEST_F(RendererControllerTest, WithHEVCVideoCodec) {
247 const scoped_refptr<SharedSession> shared_session =
248 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42249 InitializeControllerAndBecomeDominant(shared_session,
250 DefaultMetadata(VideoCodec::kCodecHEVC),
251 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11252 // An available sink that does not support HEVC video codec should not cause
253 // the controller to toggle remote rendering on.
254 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42255 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
Xiangjun Zhang6dc11102017-07-24 23:49:11256 EXPECT_FALSE(disable_pipeline_suspend_);
257
258 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09259 RunUntilIdle();
260 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11261 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
262 EXPECT_FALSE(disable_pipeline_suspend_);
263 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
264 sink_metadata.video_capabilities.push_back(
265 mojom::RemotingSinkVideoCapability::CODEC_HEVC);
266 // A sink that *does* support HEVC video codec *does* cause the controller to
267 // toggle remote rendering on.
268 shared_session->OnSinkAvailable(sink_metadata.Clone());
269 RunUntilIdle();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42270 EXPECT_TRUE(IsInDelayedStart());
271 DelayedStartEnds();
272 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11273 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
274 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
275 EXPECT_TRUE(disable_pipeline_suspend_);
276}
277
278TEST_F(RendererControllerTest, WithAACAudioCodec) {
279 const scoped_refptr<SharedSession> shared_session =
280 FakeRemoterFactory::CreateSharedSession(false);
281 const AudioDecoderConfig audio_config = AudioDecoderConfig(
282 AudioCodec::kCodecAAC, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
283 44100, EmptyExtraData(), Unencrypted());
284 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
285 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42286 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
287 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11288 // An available sink that does not support AAC audio codec should not cause
289 // the controller to toggle remote rendering on.
290 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11291 EXPECT_FALSE(disable_pipeline_suspend_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42292 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
Xiangjun Zhang6dc11102017-07-24 23:49:11293
294 shared_session->OnSinkGone(); // Bye-bye useless sink!
miu9f7788e2017-01-25 00:46:09295 RunUntilIdle();
296 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11297 EXPECT_FALSE(disable_pipeline_suspend_);
298 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
299 sink_metadata.audio_capabilities.push_back(
300 mojom::RemotingSinkAudioCapability::CODEC_AAC);
301 // A sink that *does* support AAC audio codec *does* cause the controller to
302 // toggle remote rendering on.
303 shared_session->OnSinkAvailable(sink_metadata.Clone());
miu9f7788e2017-01-25 00:46:09304 RunUntilIdle();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42305 EXPECT_TRUE(IsInDelayedStart());
306 DelayedStartEnds();
307 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11308 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
309 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
310 EXPECT_TRUE(disable_pipeline_suspend_);
311}
312
313TEST_F(RendererControllerTest, WithOpusAudioCodec) {
314 const scoped_refptr<SharedSession> shared_session =
315 FakeRemoterFactory::CreateSharedSession(false);
316 const AudioDecoderConfig audio_config = AudioDecoderConfig(
317 AudioCodec::kCodecOpus, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO,
318 44100, EmptyExtraData(), Unencrypted());
319 PipelineMetadata pipeline_metadata = DefaultMetadata(VideoCodec::kCodecVP8);
320 pipeline_metadata.audio_decoder_config = audio_config;
Xiangjun Zhangc92ec9b2017-07-25 21:56:42321 InitializeControllerAndBecomeDominant(shared_session, pipeline_metadata,
322 GetDefaultSinkMetadata(true));
Xiangjun Zhang6dc11102017-07-24 23:49:11323 // An available sink that does not support Opus audio codec should not cause
324 // the controller to toggle remote rendering on.
325 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42326 EXPECT_FALSE(activate_viewport_intersection_monitoring_);
Xiangjun Zhang6dc11102017-07-24 23:49:11327 EXPECT_FALSE(disable_pipeline_suspend_);
328
329 shared_session->OnSinkGone(); // Bye-bye useless sink!
330 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11331 mojom::RemotingSinkMetadata sink_metadata = GetDefaultSinkMetadata(true);
332 sink_metadata.audio_capabilities.push_back(
333 mojom::RemotingSinkAudioCapability::CODEC_OPUS);
334 // A sink that *does* support Opus audio codec *does* cause the controller to
335 // toggle remote rendering on.
336 shared_session->OnSinkAvailable(sink_metadata.Clone());
337 RunUntilIdle();
Xiangjun Zhangc92ec9b2017-07-25 21:56:42338 EXPECT_TRUE(IsInDelayedStart());
339 DelayedStartEnds();
340 RunUntilIdle();
Xiangjun Zhang6dc11102017-07-24 23:49:11341 EXPECT_TRUE(is_rendering_remotely_); // All requirements now satisfied.
342 EXPECT_TRUE(activate_viewport_intersection_monitoring_);
343 EXPECT_TRUE(disable_pipeline_suspend_);
344}
345
346TEST_F(RendererControllerTest, StartFailed) {
347 const scoped_refptr<SharedSession> shared_session =
348 FakeRemoterFactory::CreateSharedSession(true);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42349 InitializeControllerAndBecomeDominant(shared_session,
350 DefaultMetadata(VideoCodec::kCodecVP8),
351 GetDefaultSinkMetadata(true));
352 RunUntilIdle();
353 EXPECT_TRUE(IsInDelayedStart());
354 DelayedStartEnds();
355 RunUntilIdle();
miu9f7788e2017-01-25 00:46:09356 EXPECT_FALSE(is_rendering_remotely_);
xjz4e5d4bf32017-02-15 21:26:35357 EXPECT_FALSE(disable_pipeline_suspend_);
miu9f7788e2017-01-25 00:46:09358}
359
360TEST_F(RendererControllerTest, EncryptedWithRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11361 const scoped_refptr<SharedSession> shared_session =
362 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42363 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
364 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09365 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhang6dc11102017-07-24 23:49:11366
miu9f7788e2017-01-25 00:46:09367 const scoped_refptr<SharedSession> cdm_shared_session =
368 FakeRemoterFactory::CreateSharedSession(false);
369 std::unique_ptr<RemotingCdmController> cdm_controller =
370 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11371 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09372 cdm_controller->ShouldCreateRemotingCdm(
373 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
374 RunUntilIdle();
375 EXPECT_FALSE(is_rendering_remotely_);
376 EXPECT_TRUE(is_remoting_cdm_);
377
378 // Create a RemotingCdm with |cdm_controller|.
379 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
380 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
381 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
382 std::move(cdm_controller));
383 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
384 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
385 controller_->OnSetCdm(remoting_cdm_context.get());
386 RunUntilIdle();
387 EXPECT_TRUE(is_rendering_remotely_);
388
Xiangjun Zhangc92ec9b2017-07-25 21:56:42389 // For encrypted contents, becoming/exiting dominant has no effect.
390 controller_->OnBecameDominantVisibleContent(true);
miu9f7788e2017-01-25 00:46:09391 RunUntilIdle();
392 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42393 EXPECT_FALSE(IsInDelayedStart());
394 controller_->OnBecameDominantVisibleContent(false);
395 RunUntilIdle();
396 EXPECT_TRUE(is_rendering_remotely_);
397 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09398
399 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
400 controller_->session()->state());
401 cdm_shared_session->OnSinkGone();
402 RunUntilIdle();
403 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
404 controller_->session()->state());
405 // Don't switch renderer in this case. Still using the remoting renderer to
406 // show the failure interstitial.
407 EXPECT_TRUE(is_rendering_remotely_);
408}
409
410TEST_F(RendererControllerTest, EncryptedWithLocalCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11411 const scoped_refptr<SharedSession> shared_session =
miu9f7788e2017-01-25 00:46:09412 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42413 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
414 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09415 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42416 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09417
418 const scoped_refptr<SharedSession> cdm_shared_session =
419 FakeRemoterFactory::CreateSharedSession(true);
420 std::unique_ptr<RemotingCdmController> cdm_controller =
421 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11422 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09423 cdm_controller->ShouldCreateRemotingCdm(
424 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
425 RunUntilIdle();
426 EXPECT_FALSE(is_rendering_remotely_);
427 EXPECT_FALSE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42428 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09429}
430
431TEST_F(RendererControllerTest, EncryptedWithFailedRemotingCdm) {
Xiangjun Zhang6dc11102017-07-24 23:49:11432 const scoped_refptr<SharedSession> shared_session =
433 FakeRemoterFactory::CreateSharedSession(false);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42434 InitializeControllerAndBecomeDominant(shared_session, EncryptedMetadata(),
435 GetDefaultSinkMetadata(true));
miu9f7788e2017-01-25 00:46:09436 EXPECT_FALSE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42437 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09438
439 const scoped_refptr<SharedSession> cdm_shared_session =
440 FakeRemoterFactory::CreateSharedSession(false);
441 std::unique_ptr<RemotingCdmController> cdm_controller =
442 base::MakeUnique<RemotingCdmController>(cdm_shared_session);
Xiangjun Zhang6dc11102017-07-24 23:49:11443 cdm_shared_session->OnSinkAvailable(GetDefaultSinkMetadata(true).Clone());
miu9f7788e2017-01-25 00:46:09444 cdm_controller->ShouldCreateRemotingCdm(
445 base::Bind(&RendererControllerTest::CreateCdm, base::Unretained(this)));
446 RunUntilIdle();
447 EXPECT_FALSE(is_rendering_remotely_);
448 EXPECT_TRUE(is_remoting_cdm_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42449 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09450
451 cdm_shared_session->OnSinkGone();
452 RunUntilIdle();
453 EXPECT_FALSE(is_rendering_remotely_);
454 EXPECT_NE(SharedSession::SESSION_PERMANENTLY_STOPPED,
455 controller_->session()->state());
456
457 const scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
458 std::string(), GURL(), CdmConfig(), SessionMessageCB(), SessionClosedCB(),
459 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
460 std::move(cdm_controller));
461 std::unique_ptr<RemotingCdmContext> remoting_cdm_context =
462 base::MakeUnique<RemotingCdmContext>(remoting_cdm.get());
463 controller_->OnSetCdm(remoting_cdm_context.get());
464 RunUntilIdle();
465 // Switch to using the remoting renderer, even when the remoting CDM session
466 // was already terminated, to show the failure interstitial.
467 EXPECT_TRUE(is_rendering_remotely_);
Xiangjun Zhangc92ec9b2017-07-25 21:56:42468 EXPECT_FALSE(IsInDelayedStart());
miu9f7788e2017-01-25 00:46:09469 EXPECT_EQ(SharedSession::SESSION_PERMANENTLY_STOPPED,
470 controller_->session()->state());
471}
472
473} // namespace remoting
474} // namespace media