Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1621)

Side by Side Diff: media/remoting/remoting_renderer_controller_unittest.cc

Issue 2457563002: Media Remoting: Add remoting control logic for encrypted contents. (Closed)
Patch Set: Addressed comments. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/remoting/remoting_renderer_controller.h"
6
7 #include "base/callback.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "media/base/audio_decoder_config.h"
11 #include "media/base/cdm_config.h"
12 #include "media/base/limits.h"
13 #include "media/base/media_util.h"
14 #include "media/base/video_decoder_config.h"
15 #include "media/remoting/remoting_cdm.h"
16 #include "mojo/public/cpp/bindings/strong_binding.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace media {
20 namespace {
21
22 constexpr gfx::Size kCodedSize(320, 240);
23 constexpr gfx::Rect kVisibleRect(320, 240);
24 constexpr gfx::Size kNaturalSize(320, 240);
25
26 PipelineMetadata DefaultMetadata() {
27 PipelineMetadata data;
28 data.has_audio = true;
29 data.has_video = true;
30 data.video_decoder_config = VideoDecoderConfig(
xhwang 2016/11/01 08:21:29 You can use TestVideoConfig::Normal(), etc: https
xjz 2016/11/01 21:55:53 Done.
31 kCodecVP8, VP8PROFILE_ANY, VideoPixelFormat::PIXEL_FORMAT_I420,
32 ColorSpace::COLOR_SPACE_SD_REC601, kCodedSize, kVisibleRect, kNaturalSize,
33 EmptyExtraData(), Unencrypted());
34 data.audio_decoder_config = AudioDecoderConfig(
35 kCodecOpus, SampleFormat::kSampleFormatU8,
36 ChannelLayout::CHANNEL_LAYOUT_MONO, limits::kMinSampleRate,
37 EmptyExtraData(), Unencrypted());
38 return data;
39 }
40
41 PipelineMetadata EncryptedMetadata() {
42 PipelineMetadata data;
43 data.has_audio = true;
44 data.has_video = true;
45 data.video_decoder_config = VideoDecoderConfig(
46 kCodecVP8, VP8PROFILE_ANY, VideoPixelFormat::PIXEL_FORMAT_I420,
47 ColorSpace::COLOR_SPACE_SD_REC601, kCodedSize, kVisibleRect, kNaturalSize,
48 EmptyExtraData(), AesCtrEncryptionScheme());
xhwang 2016/11/01 08:21:29 ditto, you can use TestVideoConfig::NormalEncrypte
xjz 2016/11/01 21:55:53 Done.
49 data.audio_decoder_config = AudioDecoderConfig(
50 kCodecOpus, SampleFormat::kSampleFormatU8,
51 ChannelLayout::CHANNEL_LAYOUT_MONO, limits::kMinSampleRate,
52 EmptyExtraData(), Unencrypted());
53 return data;
54 }
55
56 class FakeRemoter final : public mojom::Remoter {
57 public:
58 // |start_will_fail| indicates whether starting remoting will fail.
59 FakeRemoter(mojom::RemotingSourcePtr source, bool start_will_fail)
60 : source_(std::move(source)),
61 start_will_fail_(start_will_fail),
62 weak_factory_(this) {}
63 ~FakeRemoter() override {}
64
65 // mojom::Remoter implementations.
66 void Start() override {
67 if (start_will_fail_) {
68 base::ThreadTaskRunnerHandle::Get()->PostTask(
69 FROM_HERE,
70 base::Bind(&FakeRemoter::StartFailed, weak_factory_.GetWeakPtr()));
71 } else {
72 base::ThreadTaskRunnerHandle::Get()->PostTask(
73 FROM_HERE,
74 base::Bind(&FakeRemoter::Started, weak_factory_.GetWeakPtr()));
75 }
76 }
77
78 void StartDataStreams(
79 mojo::ScopedDataPipeConsumerHandle audio_pipe,
80 mojo::ScopedDataPipeConsumerHandle video_pipe,
81 mojom::RemotingDataStreamSenderRequest audio_sender_request,
82 mojom::RemotingDataStreamSenderRequest video_sender_request) override {}
83
84 void Stop(mojom::RemotingStopReason reason) override {
85 base::ThreadTaskRunnerHandle::Get()->PostTask(
86 FROM_HERE,
87 base::Bind(&FakeRemoter::Stopped, weak_factory_.GetWeakPtr(), reason));
88 }
89
90 void SendMessageToSink(const std::vector<uint8_t>& message) override {}
91
92 private:
93 void Started() { source_->OnStarted(); }
94 void StartFailed() {
95 source_->OnStartFailed(mojom::RemotingStartFailReason::ROUTE_TERMINATED);
96 }
97 void Stopped(mojom::RemotingStopReason reason) { source_->OnStopped(reason); }
98
99 const mojom::RemotingSourcePtr source_;
100 bool start_will_fail_;
101
102 base::WeakPtrFactory<FakeRemoter> weak_factory_;
103
104 DISALLOW_COPY_AND_ASSIGN(FakeRemoter);
105 };
106
107 class FakeRemoterFactory final : public mojom::RemoterFactory {
108 public:
109 // |start_will_fail| indicates whether starting remoting will fail.
110 explicit FakeRemoterFactory(bool start_will_fail)
111 : start_will_fail_(start_will_fail) {}
112 ~FakeRemoterFactory() override {}
113
114 void Create(mojom::RemotingSourcePtr source,
115 mojom::RemoterRequest request) override {
116 mojo::MakeStrongBinding(
117 base::MakeUnique<FakeRemoter>(std::move(source), start_will_fail_),
118 std::move(request));
119 }
120
121 private:
122 bool start_will_fail_;
123
124 DISALLOW_COPY_AND_ASSIGN(FakeRemoterFactory);
125 };
126
127 scoped_refptr<RemotingSourceImpl> CreateRemotingSourceImpl(
128 bool start_will_fail) {
129 mojom::RemotingSourcePtr remoting_source;
130 mojom::RemotingSourceRequest remoting_source_request =
131 mojo::GetProxy(&remoting_source);
132 mojom::RemoterPtr remoter;
133 std::unique_ptr<mojom::RemoterFactory> remoter_factory =
134 base::MakeUnique<FakeRemoterFactory>(start_will_fail);
135 remoter_factory->Create(std::move(remoting_source), mojo::GetProxy(&remoter));
136 return new RemotingSourceImpl(std::move(remoting_source_request),
137 std::move(remoter));
138 }
139
140 } // namespace
141
142 class RemotingRendererControllerTest : public ::testing::Test {
143 public:
144 RemotingRendererControllerTest() {}
145 ~RemotingRendererControllerTest() override {}
146
147 void TearDown() final { RunUntilIdle(); }
148
149 static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
150
151 void ToggleRenderer() {
152 is_rendering_remotely_ =
153 remoting_renderer_controller_->remote_rendering_started();
154 }
155
156 void CreateCdm(bool is_remoting) { is_remoting_cdm_ = is_remoting; }
157
158 base::MessageLoop message_loop_;
159
160 protected:
161 std::unique_ptr<RemotingRendererController> remoting_renderer_controller_;
162 bool is_rendering_remotely_ = false;
163 bool is_remoting_cdm_ = false;
164
165 private:
166 DISALLOW_COPY_AND_ASSIGN(RemotingRendererControllerTest);
167 };
168
169 TEST_F(RemotingRendererControllerTest, ToggleRenderer) {
170 EXPECT_FALSE(is_rendering_remotely_);
171 scoped_refptr<RemotingSourceImpl> remoting_source_impl =
172 CreateRemotingSourceImpl(false);
173 remoting_renderer_controller_ =
174 base::MakeUnique<RemotingRendererController>(remoting_source_impl);
175 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind(
176 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this)));
177 RunUntilIdle();
178 EXPECT_FALSE(is_rendering_remotely_);
179 remoting_source_impl->OnSinkAvailable();
180 RunUntilIdle();
181 EXPECT_FALSE(is_rendering_remotely_);
182 remoting_renderer_controller_->OnEnteredFullscreen();
183 RunUntilIdle();
184 EXPECT_FALSE(is_rendering_remotely_);
185 remoting_renderer_controller_->OnMetadataChanged(DefaultMetadata());
186 RunUntilIdle();
187 EXPECT_TRUE(is_rendering_remotely_);
188 remoting_renderer_controller_->OnExitedFullscreen();
189 RunUntilIdle();
190 EXPECT_FALSE(is_rendering_remotely_);
191 }
192
193 TEST_F(RemotingRendererControllerTest, StartFailed) {
194 EXPECT_FALSE(is_rendering_remotely_);
195 scoped_refptr<RemotingSourceImpl> remoting_source_impl =
196 CreateRemotingSourceImpl(true);
197 remoting_renderer_controller_ =
198 base::MakeUnique<RemotingRendererController>(remoting_source_impl);
199 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind(
200 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this)));
201 RunUntilIdle();
202 EXPECT_FALSE(is_rendering_remotely_);
203 remoting_source_impl->OnSinkAvailable();
204 RunUntilIdle();
205 EXPECT_FALSE(is_rendering_remotely_);
206 remoting_renderer_controller_->OnEnteredFullscreen();
207 RunUntilIdle();
208 EXPECT_FALSE(is_rendering_remotely_);
209 remoting_renderer_controller_->OnMetadataChanged(DefaultMetadata());
210 RunUntilIdle();
211 EXPECT_FALSE(is_rendering_remotely_);
212 }
213
214 TEST_F(RemotingRendererControllerTest, EncryptedWithRemotingCdm) {
215 EXPECT_FALSE(is_rendering_remotely_);
216 remoting_renderer_controller_ = base::MakeUnique<RemotingRendererController>(
217 CreateRemotingSourceImpl(false));
218 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind(
219 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this)));
220 RunUntilIdle();
221 EXPECT_FALSE(is_rendering_remotely_);
222 remoting_renderer_controller_->OnMetadataChanged(EncryptedMetadata());
223 RunUntilIdle();
224 EXPECT_FALSE(is_rendering_remotely_);
225 scoped_refptr<RemotingSourceImpl> cdm_remoting_source_impl =
226 CreateRemotingSourceImpl(false);
227 std::unique_ptr<RemotingCdmController> remoting_cdm_controller =
228 base::MakeUnique<RemotingCdmController>(cdm_remoting_source_impl);
229 cdm_remoting_source_impl->OnSinkAvailable();
230 remoting_cdm_controller->ShouldCreateRemotingCdm(base::Bind(
231 &RemotingRendererControllerTest::CreateCdm, base::Unretained(this)));
232 RunUntilIdle();
233 EXPECT_FALSE(is_rendering_remotely_);
234 EXPECT_TRUE(is_remoting_cdm_);
235
236 // Create a RemotingCdm with |remoting_cdm_controller|.
237 CdmConfig cdm_config;
238 GURL gurl;
239 std::string empty_string;
240 scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
241 empty_string, gurl, cdm_config, SessionMessageCB(), SessionClosedCB(),
242 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
243 std::move(remoting_cdm_controller));
244 remoting_renderer_controller_->OnSetCdm(remoting_cdm.get());
245 RunUntilIdle();
246 EXPECT_TRUE(is_rendering_remotely_);
247
248 // For encrypted contents, entering/exiting full screen has no effect.
249 remoting_renderer_controller_->OnEnteredFullscreen();
250 RunUntilIdle();
251 EXPECT_TRUE(is_rendering_remotely_);
252 remoting_renderer_controller_->OnExitedFullscreen();
253 RunUntilIdle();
254 EXPECT_TRUE(is_rendering_remotely_);
255
256 EXPECT_NE(RemotingSessionState::SESSION_PERMANENTLY_STOPPED,
257 remoting_renderer_controller_->remoting_source()->state());
258 cdm_remoting_source_impl->OnSinkGone();
259 RunUntilIdle();
260 EXPECT_EQ(RemotingSessionState::SESSION_PERMANENTLY_STOPPED,
261 remoting_renderer_controller_->remoting_source()->state());
262 // Don't switch renderer in this case. Still in remoting.
263 EXPECT_TRUE(is_rendering_remotely_);
264 }
265
266 TEST_F(RemotingRendererControllerTest, EncryptedWithLocalCdm) {
267 EXPECT_FALSE(is_rendering_remotely_);
268 scoped_refptr<RemotingSourceImpl> renderer_remoting_source_impl =
269 CreateRemotingSourceImpl(false);
270 remoting_renderer_controller_ = base::MakeUnique<RemotingRendererController>(
271 renderer_remoting_source_impl);
272 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind(
273 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this)));
274 RunUntilIdle();
275 EXPECT_FALSE(is_rendering_remotely_);
276 renderer_remoting_source_impl->OnSinkAvailable();
277 RunUntilIdle();
278 EXPECT_FALSE(is_rendering_remotely_);
279 remoting_renderer_controller_->OnEnteredFullscreen();
280 RunUntilIdle();
281 EXPECT_FALSE(is_rendering_remotely_);
282 remoting_renderer_controller_->OnMetadataChanged(EncryptedMetadata());
283 RunUntilIdle();
284 EXPECT_FALSE(is_rendering_remotely_);
285
286 scoped_refptr<RemotingSourceImpl> cdm_remoting_source_impl =
287 CreateRemotingSourceImpl(true);
288 std::unique_ptr<RemotingCdmController> remoting_cdm_controller =
289 base::MakeUnique<RemotingCdmController>(cdm_remoting_source_impl);
290 cdm_remoting_source_impl->OnSinkAvailable();
291 remoting_cdm_controller->ShouldCreateRemotingCdm(base::Bind(
292 &RemotingRendererControllerTest::CreateCdm, base::Unretained(this)));
293 RunUntilIdle();
294 EXPECT_FALSE(is_rendering_remotely_);
295 EXPECT_FALSE(is_remoting_cdm_);
296 }
297
298 TEST_F(RemotingRendererControllerTest, EncryptedWithFailedRemotingCdm) {
299 EXPECT_FALSE(is_rendering_remotely_);
300 remoting_renderer_controller_ = base::MakeUnique<RemotingRendererController>(
301 CreateRemotingSourceImpl(false));
302 remoting_renderer_controller_->SetSwitchRendererCallback(base::Bind(
303 &RemotingRendererControllerTest::ToggleRenderer, base::Unretained(this)));
304 RunUntilIdle();
305 EXPECT_FALSE(is_rendering_remotely_);
306 remoting_renderer_controller_->OnEnteredFullscreen();
307 RunUntilIdle();
308 EXPECT_FALSE(is_rendering_remotely_);
309 remoting_renderer_controller_->OnMetadataChanged(EncryptedMetadata());
310 RunUntilIdle();
311 EXPECT_FALSE(is_rendering_remotely_);
312
313 scoped_refptr<RemotingSourceImpl> cdm_remoting_source_impl =
314 CreateRemotingSourceImpl(false);
315 std::unique_ptr<RemotingCdmController> remoting_cdm_controller =
316 base::MakeUnique<RemotingCdmController>(cdm_remoting_source_impl);
317 cdm_remoting_source_impl->OnSinkAvailable();
318 remoting_cdm_controller->ShouldCreateRemotingCdm(base::Bind(
319 &RemotingRendererControllerTest::CreateCdm, base::Unretained(this)));
320 RunUntilIdle();
321 EXPECT_FALSE(is_rendering_remotely_);
322 EXPECT_TRUE(is_remoting_cdm_);
323
324 cdm_remoting_source_impl->OnSinkGone();
325 RunUntilIdle();
326 EXPECT_FALSE(is_rendering_remotely_);
327 EXPECT_NE(RemotingSessionState::SESSION_PERMANENTLY_STOPPED,
328 remoting_renderer_controller_->remoting_source()->state());
329
330 CdmConfig cdm_config;
331 GURL gurl;
332 std::string empty_string;
333 scoped_refptr<RemotingCdm> remoting_cdm = new RemotingCdm(
334 empty_string, gurl, cdm_config, SessionMessageCB(), SessionClosedCB(),
335 SessionKeysChangeCB(), SessionExpirationUpdateCB(), CdmCreatedCB(),
336 std::move(remoting_cdm_controller));
337 remoting_renderer_controller_->OnSetCdm(remoting_cdm.get());
338 RunUntilIdle();
339 // Switch to remoting renderer even when the remoting CDM session was already
340 // terminated.
341 EXPECT_TRUE(is_rendering_remotely_);
342 EXPECT_EQ(RemotingSessionState::SESSION_PERMANENTLY_STOPPED,
343 remoting_renderer_controller_->remoting_source()->state());
344 }
345
346 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698