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

Side by Side Diff: media/mojo/clients/mojo_cdm_unittest.cc

Issue 2592913002: [eme] Break mojo connection during call (Closed)
Patch Set: rebase Created 3 years, 11 months 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
« media/base/mock_filters.h ('K') | « media/mojo/clients/mojo_cdm.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <stdint.h> 5 #include <stdint.h>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/memory/ref_counted.h"
10 #include "base/run_loop.h" 11 #include "base/run_loop.h"
11 #include "base/test/test_message_loop.h" 12 #include "base/test/test_message_loop.h"
13 #include "base/time/time.h"
12 #include "media/base/cdm_config.h" 14 #include "media/base/cdm_config.h"
13 #include "media/base/content_decryption_module.h" 15 #include "media/base/content_decryption_module.h"
14 #include "media/base/mock_filters.h" 16 #include "media/base/mock_filters.h"
15 #include "media/cdm/default_cdm_factory.h" 17 #include "media/cdm/default_cdm_factory.h"
16 #include "media/mojo/clients/mojo_cdm.h" 18 #include "media/mojo/clients/mojo_cdm.h"
17 #include "media/mojo/interfaces/content_decryption_module.mojom.h" 19 #include "media/mojo/interfaces/content_decryption_module.mojom.h"
18 #include "media/mojo/services/mojo_cdm_service.h" 20 #include "media/mojo/services/mojo_cdm_service.h"
19 #include "media/mojo/services/mojo_cdm_service_context.h" 21 #include "media/mojo/services/mojo_cdm_service_context.h"
20 #include "mojo/public/cpp/bindings/interface_request.h" 22 #include "mojo/public/cpp/bindings/interface_request.h"
21 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/gtest/include/gtest/gtest.h"
22 24
23 using ::testing::_; 25 using ::testing::_;
26 using ::testing::DoAll;
27 using ::testing::Invoke;
28 using ::testing::NiceMock;
24 using ::testing::StrictMock; 29 using ::testing::StrictMock;
30 using ::testing::WithArg;
31 using ::testing::WithArgs;
32 using ::testing::WithoutArgs;
25 33
26 MATCHER(NotEmpty, "") { 34 MATCHER(NotEmpty, "") {
27 return !arg.empty(); 35 return !arg.empty();
28 } 36 }
29 37
38 ACTION_P2(CdmCreated, cdm, error_message) {
39 arg0.Run(cdm, error_message);
40 }
41
42 ACTION_P(ResolvePromise, cdm) {
43 cdm->ResolvePromise(arg0);
44 }
45
46 ACTION_P(RejectPromise, cdm) {
47 cdm->RejectPromise(arg0);
48 }
49
50 ACTION_P2(ResolvePromiseWithSession, cdm, session_id) {
51 cdm->ResolvePromiseWithSession(arg0, session_id);
52 }
53
30 namespace media { 54 namespace media {
31 55
32 namespace { 56 namespace {
33 57
34 const char kClearKeyKeySystem[] = "org.w3.clearkey"; 58 const char kClearKeyKeySystem[] = "org.w3.clearkey";
35 const char kTestSecurityOrigin[] = "https://www.test.com"; 59 const char kTestSecurityOrigin[] = "https://www.test.com";
36 60
37 // Random key ID used to create a session. 61 // Random key ID used to create a session.
38 const uint8_t kKeyId[] = { 62 const uint8_t kKeyId[] = {
39 // base64 equivalent is AQIDBAUGBwgJCgsMDQ4PEA 63 // base64 equivalent is AQIDBAUGBwgJCgsMDQ4PEA
40 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 64 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
41 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 65 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
42 }; 66 };
43 67
44 } // namespace 68 } // namespace
45 69
46 class MojoCdmTest : public ::testing::Test { 70 class MojoCdmTest : public ::testing::Test {
47 public: 71 public:
48 enum ExpectedResult { SUCCESS, CONNECTION_ERROR, FAILURE }; 72 enum ExpectedResult {
73 SUCCESS,
74 CONNECTION_ERROR_BEFORE,
75 CONNECTION_ERROR_DURING,
76 FAILURE
77 };
49 78
50 MojoCdmTest() 79 MojoCdmTest()
51 : mojo_cdm_service_(base::MakeUnique<MojoCdmService>( 80 : mojo_cdm_service_(base::MakeUnique<MojoCdmService>(
52 mojo_cdm_service_context_.GetWeakPtr(), 81 mojo_cdm_service_context_.GetWeakPtr(),
53 &cdm_factory_)), 82 &cdm_factory_)),
54 cdm_binding_(mojo_cdm_service_.get()) {} 83 cdm_binding_(mojo_cdm_service_.get()) {}
55 84
56 virtual ~MojoCdmTest() {} 85 virtual ~MojoCdmTest() {}
57 86
58 void Initialize(const std::string& key_system, 87 void Initialize(ExpectedResult expected_result) {
59 ExpectedResult expected_result) {
60 mojom::ContentDecryptionModulePtr remote_cdm; 88 mojom::ContentDecryptionModulePtr remote_cdm;
61 auto cdm_request = mojo::MakeRequest(&remote_cdm); 89 auto cdm_request = mojo::MakeRequest(&remote_cdm);
62 90
91 cdm_binding_.Bind(std::move(cdm_request));
92 remote_cdm_ = new NiceMock<MockCdm>();
xhwang 2017/01/05 06:59:53 Can we use StrictMock?
jrummell 2017/01/05 23:47:22 Yes, but then we have to ignore calls to GetCdmCon
93
63 switch (expected_result) { 94 switch (expected_result) {
64 case SUCCESS: 95 case SUCCESS:
96 // Return |remote_cdm_| when creating the CDM. SetCallbacks() is
97 // called so the MockCdm has the correct callbacks to use.
98 EXPECT_CALL(cdm_factory_, Create(_, _, _, _, _, _, _, _))
99 .WillOnce(DoAll(WithArgs<3, 4, 5, 6>(Invoke(
100 remote_cdm_.get(), &MockCdm::SetCallbacks)),
101 WithArg<7>(CdmCreated(remote_cdm_, ""))));
xhwang 2017/01/05 06:59:53 This is pretty cool but seems a bit overkill. For
jrummell 2017/01/05 23:47:22 Done.
102 break;
103
65 case FAILURE: 104 case FAILURE:
66 cdm_binding_.Bind(std::move(cdm_request)); 105 // Don't return a CDM.
106 EXPECT_CALL(cdm_factory_, Create(_, _, _, _, _, _, _, _))
107 .WillOnce(WithArg<7>(CdmCreated(nullptr, "CDM creation failed")));
67 break; 108 break;
68 case CONNECTION_ERROR: 109
69 cdm_request.ResetWithReason(0, "Request dropped for testing."); 110 case CONNECTION_ERROR_BEFORE:
111 // Break the connection before the call.
112 ForceConnectionError();
113 break;
114
115 case CONNECTION_ERROR_DURING:
116 // Break the connection during the call. Also return the CDM, which
117 // should get ignored once the pipe is broken.
118 EXPECT_CALL(cdm_factory_, Create(_, _, _, _, _, _, _, _))
119 .WillOnce(DoAll(
120 WithoutArgs(Invoke(this, &MojoCdmTest::ForceConnectionError)),
121 WithArgs<3, 4, 5, 6>(
122 Invoke(remote_cdm_.get(), &MockCdm::SetCallbacks)),
123 WithArg<7>(CdmCreated(remote_cdm_, ""))));
70 break; 124 break;
71 } 125 }
72 126
73 MojoCdm::Create(key_system, GURL(kTestSecurityOrigin), CdmConfig(), 127 MojoCdm::Create(kClearKeyKeySystem, GURL(kTestSecurityOrigin), CdmConfig(),
74 std::move(remote_cdm), 128 std::move(remote_cdm),
75 base::Bind(&MockCdmClient::OnSessionMessage, 129 base::Bind(&MockCdmClient::OnSessionMessage,
76 base::Unretained(&cdm_client_)), 130 base::Unretained(&cdm_client_)),
77 base::Bind(&MockCdmClient::OnSessionClosed, 131 base::Bind(&MockCdmClient::OnSessionClosed,
78 base::Unretained(&cdm_client_)), 132 base::Unretained(&cdm_client_)),
79 base::Bind(&MockCdmClient::OnSessionKeysChange, 133 base::Bind(&MockCdmClient::OnSessionKeysChange,
80 base::Unretained(&cdm_client_)), 134 base::Unretained(&cdm_client_)),
81 base::Bind(&MockCdmClient::OnSessionExpirationUpdate, 135 base::Bind(&MockCdmClient::OnSessionExpirationUpdate,
82 base::Unretained(&cdm_client_)), 136 base::Unretained(&cdm_client_)),
83 base::Bind(&MojoCdmTest::OnCdmCreated, 137 base::Bind(&MojoCdmTest::OnCdmCreated,
84 base::Unretained(this), expected_result)); 138 base::Unretained(this), expected_result));
85
86 base::RunLoop().RunUntilIdle(); 139 base::RunLoop().RunUntilIdle();
87 } 140 }
88 141
89 void OnCdmCreated(ExpectedResult expected_result, 142 void OnCdmCreated(ExpectedResult expected_result,
90 const scoped_refptr<ContentDecryptionModule>& cdm, 143 const scoped_refptr<ContentDecryptionModule>& cdm,
91 const std::string& error_message) { 144 const std::string& error_message) {
92 if (!cdm) { 145 if (!cdm) {
93 EXPECT_NE(SUCCESS, expected_result); 146 EXPECT_NE(SUCCESS, expected_result);
94 DVLOG(1) << error_message; 147 DVLOG(1) << error_message;
95 return; 148 return;
96 } 149 }
97 150
98 EXPECT_EQ(SUCCESS, expected_result); 151 EXPECT_EQ(SUCCESS, expected_result);
99 mojo_cdm_ = cdm; 152 mojo_cdm_ = cdm;
100 } 153 }
101 154
102 void ForceConnectionError() { 155 void ForceConnectionError() {
103 // If there is an existing session it will get closed when the connection
104 // is broken.
105 if (!session_id_.empty()) {
106 EXPECT_CALL(cdm_client_, OnSessionClosed(session_id_));
107 }
108
109 cdm_binding_.CloseWithReason(2, "Test closed connection."); 156 cdm_binding_.CloseWithReason(2, "Test closed connection.");
110
111 base::RunLoop().RunUntilIdle(); 157 base::RunLoop().RunUntilIdle();
112 } 158 }
113 159
114 void SetServerCertificateAndExpect(const std::vector<uint8_t>& certificate, 160 void SetServerCertificateAndExpect(const std::vector<uint8_t>& certificate,
115 ExpectedResult expected_result) { 161 ExpectedResult expected_result) {
162 switch (expected_result) {
163 case SUCCESS:
164 // Resolve the promise when SetServerCertificate() is called.
165 EXPECT_CALL(*remote_cdm_.get(), OnSetServerCertificate(certificate, _))
166 .WillOnce(WithArg<1>(ResolvePromise(remote_cdm_.get())));
167 break;
168
169 case FAILURE:
170 // Reject the promise when SetServerCertificate() is called.
171 EXPECT_CALL(*remote_cdm_.get(), OnSetServerCertificate(certificate, _))
172 .WillOnce(WithArg<1>(RejectPromise(remote_cdm_.get())));
173 break;
174
175 case CONNECTION_ERROR_BEFORE:
176 // Break the connection before the call, so SetServerCertificate() is
177 // never called.
178 ForceConnectionError();
179 EXPECT_CALL(*remote_cdm_.get(), OnSetServerCertificate(_, _)).Times(0);
xhwang 2017/01/05 06:59:53 If you use a StrongMock, you don't need Times(0) b
jrummell 2017/01/05 23:47:22 Done.
180 break;
181
182 case CONNECTION_ERROR_DURING:
183 // Break the connection before resolving the promise. Note that the
184 // resolved promise never gets sent across the broken pipe.
185 EXPECT_CALL(*remote_cdm_.get(), OnSetServerCertificate(certificate, _))
186 .WillOnce(DoAll(
187 WithoutArgs(Invoke(this, &MojoCdmTest::ForceConnectionError)),
188 WithArg<1>(ResolvePromise(remote_cdm_.get()))));
xhwang 2017/01/05 06:59:53 nit: Can we try not resolving the promise here? I
jrummell 2017/01/05 23:47:22 Rejecting or resolving the promise doesn't get pas
189 break;
190 }
191
116 mojo_cdm_->SetServerCertificate( 192 mojo_cdm_->SetServerCertificate(
117 certificate, 193 certificate,
118 base::MakeUnique<MockCdmPromise>(expected_result == SUCCESS)); 194 base::MakeUnique<MockCdmPromise>(expected_result == SUCCESS));
119 195 base::RunLoop().RunUntilIdle();
120 base::RunLoop().RunUntilIdle(); 196 }
121 } 197
122 198 void CreateSessionAndExpect(const std::string& session_id,
123 void CreateSessionAndExpect(EmeInitDataType data_type,
124 const std::vector<uint8_t>& key_id,
125 ExpectedResult expected_result) { 199 ExpectedResult expected_result) {
200 // Specify parameters needed to call CreateSessionAndGenerateRequest() in
201 // order to verify that the data is passed properly.
202 const CdmSessionType session_type = CdmSessionType::TEMPORARY_SESSION;
203 const EmeInitDataType data_type = EmeInitDataType::WEBM;
204 const std::vector<uint8_t> key_id(kKeyId, kKeyId + arraysize(kKeyId));
205 std::string created_session_id;
206
207 switch (expected_result) {
208 case SUCCESS:
209 // Resolve the promise when CreateSessionAndGenerateRequest() is called.
210 EXPECT_CALL(*remote_cdm_.get(), OnCreateSessionAndGenerateRequest(
211 session_type, data_type, key_id, _))
212 .WillOnce(WithArg<3>(
213 ResolvePromiseWithSession(remote_cdm_.get(), session_id)));
214 break;
215
216 case FAILURE:
217 // Reject the promise when CreateSessionAndGenerateRequest() is called.
218 EXPECT_CALL(*remote_cdm_.get(), OnCreateSessionAndGenerateRequest(
219 session_type, data_type, key_id, _))
220 .WillOnce(WithArg<3>(RejectPromise(remote_cdm_.get())));
221 break;
222
223 case CONNECTION_ERROR_BEFORE:
224 // Break the connection before the call, so
225 // CreateSessionAndGenerateRequest() is never called.
226 ForceConnectionError();
227 EXPECT_CALL(*remote_cdm_.get(),
228 OnCreateSessionAndGenerateRequest(_, _, _, _))
229 .Times(0);
230 break;
231
232 case CONNECTION_ERROR_DURING:
233 // Break the connection before resolving the promise. Note that the
234 // resolved promise never gets sent across the broken pipe.
235 EXPECT_CALL(*remote_cdm_.get(), OnCreateSessionAndGenerateRequest(
236 session_type, data_type, key_id, _))
237 .WillOnce(DoAll(
238 WithoutArgs(Invoke(this, &MojoCdmTest::ForceConnectionError)),
239 WithArg<3>(
240 ResolvePromiseWithSession(remote_cdm_.get(), session_id))));
241 break;
242 }
xhwang 2017/01/05 06:59:53 There are a lot of duplication on this switch-case
jrummell 2017/01/05 23:47:22 ProcessPromise is a bit of work, but done.
243
244 // Note that although it's called CreateSessionAndGenerateRequest, no
245 // request is generated.
246 mojo_cdm_->CreateSessionAndGenerateRequest(
247 session_type, data_type, key_id,
248 base::MakeUnique<MockCdmSessionPromise>(expected_result == SUCCESS,
249 &created_session_id));
250 base::RunLoop().RunUntilIdle();
251
252 // If the session was "created" ...
126 if (expected_result == SUCCESS) { 253 if (expected_result == SUCCESS) {
127 EXPECT_CALL(cdm_client_, OnSessionMessage(NotEmpty(), _, _)); 254 // Returned session ID must match the session ID provided.
128 } 255 EXPECT_EQ(session_id, created_session_id);
129 256
130 mojo_cdm_->CreateSessionAndGenerateRequest( 257 // MojoCdm expects the session to be closed, so invoke SessionClosedCB
131 CdmSessionType::TEMPORARY_SESSION, data_type, key_id, 258 // to "close" it.
132 base::MakeUnique<MockCdmSessionPromise>(expected_result == SUCCESS, 259 EXPECT_CALL(cdm_client_, OnSessionClosed(session_id));
133 &session_id_)); 260 remote_cdm_->CallSessionClosedCB(session_id);
134 261 base::RunLoop().RunUntilIdle();
135 base::RunLoop().RunUntilIdle(); 262 }
136 } 263 }
137 264
138 void CloseSessionAndExpect(ExpectedResult expected_result) { 265 void LoadSessionAndExpect(const std::string& session_id,
139 DCHECK(!session_id_.empty()) << "CloseSessionAndExpect() must be called " 266 ExpectedResult expected_result) {
140 "after a successful " 267 const CdmSessionType session_type =
141 "CreateSessionAndExpect()"; 268 CdmSessionType::PERSISTENT_LICENSE_SESSION;
142 269 std::string loaded_session_id;
270
271 switch (expected_result) {
272 case SUCCESS:
273 // Resolve the promise when LoadSession() is called.
274 EXPECT_CALL(*remote_cdm_.get(),
275 OnLoadSession(session_type, session_id, _))
276 .WillOnce(WithArgs<2, 1>(Invoke(
277 remote_cdm_.get(), &MockCdm::ResolvePromiseWithSession)));
278 break;
279
280 case FAILURE:
281 // Reject the promise when LoadSession() is called.
282 EXPECT_CALL(*remote_cdm_.get(),
283 OnLoadSession(session_type, session_id, _))
284 .WillOnce(WithArg<2>(RejectPromise(remote_cdm_.get())));
285 break;
286
287 case CONNECTION_ERROR_BEFORE:
288 // Break the connection before the call, so LoadSession() is never
289 // called.
290 ForceConnectionError();
291 EXPECT_CALL(*remote_cdm_.get(), OnLoadSession(_, _, _)).Times(0);
292 break;
293
294 case CONNECTION_ERROR_DURING:
295 // Break the connection before resolving the promise. Note that the
296 // resolved promise never gets sent across the broken pipe.
297 EXPECT_CALL(*remote_cdm_.get(),
298 OnLoadSession(session_type, session_id, _))
299 .WillOnce(DoAll(
300 WithoutArgs(Invoke(this, &MojoCdmTest::ForceConnectionError)),
301 WithArgs<2, 1>(Invoke(remote_cdm_.get(),
302 &MockCdm::ResolvePromiseWithSession))));
303 break;
304 }
305
306 mojo_cdm_->LoadSession(session_type, session_id,
307 base::MakeUnique<MockCdmSessionPromise>(
308 expected_result == SUCCESS, &loaded_session_id));
309 base::RunLoop().RunUntilIdle();
310
311 // If the session was "loaded" ...
143 if (expected_result == SUCCESS) { 312 if (expected_result == SUCCESS) {
144 EXPECT_CALL(cdm_client_, OnSessionClosed(session_id_)); 313 // Returned session ID must match the session ID provided.
145 } 314 EXPECT_EQ(session_id, loaded_session_id);
146 315
147 mojo_cdm_->CloseSession(session_id_, base::MakeUnique<MockCdmPromise>( 316 // MojoCdm expects the session to be closed, so invoke SessionClosedCB
317 // to "close" it.
318 EXPECT_CALL(cdm_client_, OnSessionClosed(session_id));
319 remote_cdm_->CallSessionClosedCB(session_id);
320 base::RunLoop().RunUntilIdle();
321 }
322 }
323
324 void UpdateSessionAndExpect(const std::string& session_id,
325 ExpectedResult expected_result) {
326 // Specify parameters to UpdateSession() in order to verify that
327 // the data is passed properly.
328 const std::vector<uint8_t> response = {1, 2, 3, 4, 5, 6};
329
330 switch (expected_result) {
331 case SUCCESS:
332 // Resolve the promise when UpdateSession() is called.
333 EXPECT_CALL(*remote_cdm_.get(),
334 OnUpdateSession(session_id, response, _))
335 .WillOnce(WithArg<2>(ResolvePromise(remote_cdm_.get())));
336 break;
337
338 case FAILURE:
339 // Reject the promise when UpdateSession() is called.
340 EXPECT_CALL(*remote_cdm_.get(),
341 OnUpdateSession(session_id, response, _))
342 .WillOnce(WithArg<2>(RejectPromise(remote_cdm_.get())));
343 break;
344
345 case CONNECTION_ERROR_BEFORE:
346 // Break the connection before the call, so UpdateSession() is never
347 // called.
348 ForceConnectionError();
349 EXPECT_CALL(*remote_cdm_.get(), OnUpdateSession(_, _, _)).Times(0);
350 break;
351
352 case CONNECTION_ERROR_DURING:
353 // Break the connection before resolving the promise. Note that the
354 // resolved promise never gets sent across the broken pipe.
355 EXPECT_CALL(*remote_cdm_.get(),
356 OnUpdateSession(session_id, response, _))
357 .WillOnce(DoAll(
358 WithoutArgs(Invoke(this, &MojoCdmTest::ForceConnectionError)),
359 WithArg<2>(ResolvePromise(remote_cdm_.get()))));
360 break;
361 }
362
363 mojo_cdm_->UpdateSession(
364 session_id, response,
365 base::MakeUnique<MockCdmPromise>(expected_result == SUCCESS));
366 base::RunLoop().RunUntilIdle();
367 }
368
369 void CloseSessionAndExpect(const std::string& session_id,
370 ExpectedResult expected_result) {
371 switch (expected_result) {
372 case SUCCESS:
373 // Resolve the promise when CloseSession() is called.
374 EXPECT_CALL(*remote_cdm_.get(), OnCloseSession(session_id, _))
375 .WillOnce(WithArg<1>(ResolvePromise(remote_cdm_.get())));
376 break;
377
378 case FAILURE:
379 // Reject the promise when CloseSession() is called.
380 EXPECT_CALL(*remote_cdm_.get(), OnCloseSession(session_id, _))
381 .WillOnce(WithArg<1>(RejectPromise(remote_cdm_.get())));
382 break;
383
384 case CONNECTION_ERROR_BEFORE:
385 // Break the connection before the call, so CloseSession() is never
386 // called.
387 ForceConnectionError();
388 EXPECT_CALL(*remote_cdm_.get(), OnCloseSession(_, _)).Times(0);
389 break;
390
391 case CONNECTION_ERROR_DURING:
392 // Break the connection before resolving the promise. Note that the
393 // resolved promise never gets sent across the broken pipe.
394 EXPECT_CALL(*remote_cdm_.get(), OnCloseSession(session_id, _))
395 .WillOnce(DoAll(
396 WithoutArgs(Invoke(this, &MojoCdmTest::ForceConnectionError)),
397 WithArg<1>(ResolvePromise(remote_cdm_.get()))));
398 break;
399 }
400
401 mojo_cdm_->CloseSession(session_id, base::MakeUnique<MockCdmPromise>(
402 expected_result == SUCCESS));
403 base::RunLoop().RunUntilIdle();
404 }
405
406 void RemoveSessionAndExpect(const std::string& session_id,
407 ExpectedResult expected_result) {
408 switch (expected_result) {
409 case SUCCESS:
410 // Resolve the promise when RemoveSession() is called.
411 EXPECT_CALL(*remote_cdm_.get(), OnRemoveSession(session_id, _))
412 .WillOnce(WithArg<1>(ResolvePromise(remote_cdm_.get())));
413 break;
414
415 case FAILURE:
416 // Reject the promise when RemoveSession() is called.
417 EXPECT_CALL(*remote_cdm_.get(), OnRemoveSession(session_id, _))
418 .WillOnce(WithArg<1>(RejectPromise(remote_cdm_.get())));
419 break;
420
421 case CONNECTION_ERROR_BEFORE:
422 // Break the connection before the call, so RemoveSession() never
423 // called.
424 ForceConnectionError();
425 EXPECT_CALL(*remote_cdm_.get(), OnRemoveSession(_, _)).Times(0);
426 break;
427
428 case CONNECTION_ERROR_DURING:
429 // Break the connection before resolving the promise. Note that the
430 // resolved promise never gets sent across the broken pipe.
431 EXPECT_CALL(*remote_cdm_.get(), OnRemoveSession(session_id, _))
432 .WillOnce(DoAll(
433 WithoutArgs(Invoke(this, &MojoCdmTest::ForceConnectionError)),
434 WithArg<1>(ResolvePromise(remote_cdm_.get()))));
435 break;
436 }
437
438 mojo_cdm_->RemoveSession(session_id, base::MakeUnique<MockCdmPromise>(
148 expected_result == SUCCESS)); 439 expected_result == SUCCESS));
149
150 base::RunLoop().RunUntilIdle(); 440 base::RunLoop().RunUntilIdle();
151 } 441 }
152 442
153 // Fixture members. 443 // Fixture members.
154 base::TestMessageLoop message_loop_; 444 base::TestMessageLoop message_loop_;
155 445
446 // |remote_cdm_| represents the CDM at the end of the mojo message pipe.
447 // |cdm_factory_| will return |remote_cdm_| when the CDM is needed.
448 scoped_refptr<NiceMock<MockCdm>> remote_cdm_;
449 MockCdmFactory cdm_factory_;
450
156 MojoCdmServiceContext mojo_cdm_service_context_; 451 MojoCdmServiceContext mojo_cdm_service_context_;
157 StrictMock<MockCdmClient> cdm_client_; 452 StrictMock<MockCdmClient> cdm_client_;
158 453
159 // TODO(jrummell): Use a MockCdmFactory to create a MockCdm here for more test
160 // coverage.
161 DefaultCdmFactory cdm_factory_;
162
163 std::unique_ptr<MojoCdmService> mojo_cdm_service_; 454 std::unique_ptr<MojoCdmService> mojo_cdm_service_;
164 mojo::Binding<mojom::ContentDecryptionModule> cdm_binding_; 455 mojo::Binding<mojom::ContentDecryptionModule> cdm_binding_;
165 scoped_refptr<ContentDecryptionModule> mojo_cdm_; 456 scoped_refptr<ContentDecryptionModule> mojo_cdm_;
166 457
167 // |session_id_| is the latest successful result of calling CreateSession().
168 std::string session_id_;
169
170 private: 458 private:
171 DISALLOW_COPY_AND_ASSIGN(MojoCdmTest); 459 DISALLOW_COPY_AND_ASSIGN(MojoCdmTest);
172 }; 460 };
173 461
174 TEST_F(MojoCdmTest, Create_Success) { 462 TEST_F(MojoCdmTest, Create_Success) {
175 Initialize(kClearKeyKeySystem, SUCCESS); 463 Initialize(SUCCESS);
176 }
177
178 TEST_F(MojoCdmTest, Create_ConnectionError) {
179 Initialize(kClearKeyKeySystem, CONNECTION_ERROR);
180 } 464 }
181 465
182 TEST_F(MojoCdmTest, Create_Failure) { 466 TEST_F(MojoCdmTest, Create_Failure) {
183 // This fails as DefaultCdmFactory only supports Clear Key. 467 Initialize(FAILURE);
184 Initialize("org.random.cdm", FAILURE); 468 }
185 } 469
186 470 TEST_F(MojoCdmTest, Create_ConnectionErrorBefore) {
187 TEST_F(MojoCdmTest, SetServerCertificate_AfterConnectionError) { 471 Initialize(CONNECTION_ERROR_BEFORE);
188 Initialize(kClearKeyKeySystem, SUCCESS); 472 }
189 ForceConnectionError(); 473
190 SetServerCertificateAndExpect({0, 1, 2}, FAILURE); 474 TEST_F(MojoCdmTest, Create_ConnectionErrorDuring) {
191 } 475 Initialize(CONNECTION_ERROR_DURING);
192 476 }
193 TEST_F(MojoCdmTest, CreateSessionAndGenerateRequest_AfterConnectionError) { 477
194 std::vector<uint8_t> key_id(kKeyId, kKeyId + arraysize(kKeyId)); 478 TEST_F(MojoCdmTest, SetServerCertificate_Success) {
195 479 const std::vector<uint8_t> certificate = {0, 1, 2};
196 Initialize(kClearKeyKeySystem, SUCCESS); 480 Initialize(SUCCESS);
197 ForceConnectionError(); 481 SetServerCertificateAndExpect(certificate, SUCCESS);
198 CreateSessionAndExpect(EmeInitDataType::WEBM, key_id, FAILURE); 482 }
483
484 TEST_F(MojoCdmTest, SetServerCertificate_Failure) {
485 const std::vector<uint8_t> certificate = {1, 2, 3, 4, 5};
486 Initialize(SUCCESS);
487 SetServerCertificateAndExpect(certificate, FAILURE);
488 }
489
490 TEST_F(MojoCdmTest, SetServerCertificate_ConnectionErrorBefore) {
491 const std::vector<uint8_t> certificate = {3, 4};
492 Initialize(SUCCESS);
493 SetServerCertificateAndExpect(certificate, CONNECTION_ERROR_BEFORE);
494 }
495
496 TEST_F(MojoCdmTest, SetServerCertificate_ConnectionErrorDuring) {
497 const std::vector<uint8_t> certificate = {10, 11, 12};
498 Initialize(SUCCESS);
499 SetServerCertificateAndExpect(certificate, CONNECTION_ERROR_DURING);
500 }
501
502 TEST_F(MojoCdmTest, CreateSession_Success) {
503 const std::string session_id = "create1";
504 Initialize(SUCCESS);
505 CreateSessionAndExpect("create1", SUCCESS);
506 }
507
508 TEST_F(MojoCdmTest, CreateSession_Failure) {
509 const std::string session_id = "create2";
510 Initialize(SUCCESS);
511 CreateSessionAndExpect(session_id, FAILURE);
512 }
513
514 TEST_F(MojoCdmTest, CreateSession_ConnectionErrorBefore) {
515 const std::string session_id = "create3";
516 Initialize(SUCCESS);
517 CreateSessionAndExpect(session_id, CONNECTION_ERROR_BEFORE);
518 }
519
520 TEST_F(MojoCdmTest, CreateSession_ConnectionErrorDuring) {
521 const std::string session_id = "create4";
522 Initialize(SUCCESS);
523 CreateSessionAndExpect(session_id, CONNECTION_ERROR_DURING);
524 }
525
526 TEST_F(MojoCdmTest, LoadSession_Success) {
527 const std::string session_id = "load1";
528 Initialize(SUCCESS);
529 LoadSessionAndExpect(session_id, SUCCESS);
530 }
531
532 TEST_F(MojoCdmTest, LoadSession_Failure) {
533 const std::string session_id = "load2";
534 Initialize(SUCCESS);
535 LoadSessionAndExpect(session_id, FAILURE);
536 }
537
538 TEST_F(MojoCdmTest, LoadSession_ConnectionErrorBefore) {
539 const std::string session_id = "load3";
540 Initialize(SUCCESS);
541 LoadSessionAndExpect(session_id, CONNECTION_ERROR_BEFORE);
542 }
543
544 TEST_F(MojoCdmTest, LoadSession_ConnectionErrorDuring) {
545 const std::string session_id = "load4";
546 Initialize(SUCCESS);
547 LoadSessionAndExpect(session_id, CONNECTION_ERROR_DURING);
548 }
549
550 TEST_F(MojoCdmTest, UpdateSession_Success) {
551 const std::string session_id = "update1";
552 Initialize(SUCCESS);
553 UpdateSessionAndExpect(session_id, SUCCESS);
554 }
555
556 TEST_F(MojoCdmTest, UpdateSession_Failure) {
557 const std::string session_id = "update2";
558 Initialize(SUCCESS);
559 UpdateSessionAndExpect(session_id, FAILURE);
560 }
561
562 TEST_F(MojoCdmTest, UpdateSession_ConnectionErrorBefore) {
563 const std::string session_id = "update3";
564 Initialize(SUCCESS);
565 UpdateSessionAndExpect(session_id, CONNECTION_ERROR_BEFORE);
566 }
567
568 TEST_F(MojoCdmTest, UpdateSession_ConnectionErrorDuring) {
569 const std::string session_id = "update4";
570 Initialize(SUCCESS);
571 UpdateSessionAndExpect(session_id, CONNECTION_ERROR_DURING);
199 } 572 }
200 573
201 TEST_F(MojoCdmTest, CloseSession_Success) { 574 TEST_F(MojoCdmTest, CloseSession_Success) {
202 std::vector<uint8_t> key_id(kKeyId, kKeyId + arraysize(kKeyId)); 575 const std::string session_id = "close1";
203 576 Initialize(SUCCESS);
204 Initialize(kClearKeyKeySystem, SUCCESS); 577 CloseSessionAndExpect(session_id, SUCCESS);
205 CreateSessionAndExpect(EmeInitDataType::WEBM, key_id, SUCCESS); 578 }
206 CloseSessionAndExpect(SUCCESS); 579
207 } 580 TEST_F(MojoCdmTest, CloseSession_Failure) {
208 581 const std::string session_id = "close2";
209 TEST_F(MojoCdmTest, CloseSession_AfterConnectionError) { 582 Initialize(SUCCESS);
210 std::vector<uint8_t> key_id(kKeyId, kKeyId + arraysize(kKeyId)); 583 CloseSessionAndExpect(session_id, FAILURE);
211 584 }
212 Initialize(kClearKeyKeySystem, SUCCESS); 585
213 CreateSessionAndExpect(EmeInitDataType::WEBM, key_id, SUCCESS); 586 TEST_F(MojoCdmTest, CloseSession_ConnectionErrorBefore) {
214 ForceConnectionError(); 587 const std::string session_id = "close3";
215 CloseSessionAndExpect(FAILURE); 588 Initialize(SUCCESS);
589 CloseSessionAndExpect(session_id, CONNECTION_ERROR_BEFORE);
590 }
591
592 TEST_F(MojoCdmTest, CloseSession_ConnectionErrorDuring) {
593 const std::string session_id = "close4";
594 Initialize(SUCCESS);
595 CloseSessionAndExpect(session_id, CONNECTION_ERROR_DURING);
596 }
597
598 TEST_F(MojoCdmTest, RemoveSession_Success) {
599 const std::string session_id = "remove1";
600 Initialize(SUCCESS);
601 RemoveSessionAndExpect(session_id, SUCCESS);
602 }
603
604 TEST_F(MojoCdmTest, RemoveSession_Failure) {
605 const std::string session_id = "remove2";
606 Initialize(SUCCESS);
607 RemoveSessionAndExpect(session_id, FAILURE);
608 }
609
610 TEST_F(MojoCdmTest, RemoveSession_ConnectionErrorBefore) {
611 const std::string session_id = "remove3";
612 Initialize(SUCCESS);
613 RemoveSessionAndExpect(session_id, CONNECTION_ERROR_BEFORE);
614 }
615
616 TEST_F(MojoCdmTest, RemoveSession_ConnectionErrorDuring) {
617 const std::string session_id = "remove4";
618 Initialize(SUCCESS);
619 RemoveSessionAndExpect(session_id, CONNECTION_ERROR_DURING);
620 }
621
622 // Note that MojoCdm requires a session to exist when SessionClosedCB is called,
623 // so it is currently tested in the success cases for CreateSession/LoadSession.
624
625 TEST_F(MojoCdmTest, SessionMessageCB_Success) {
626 const std::string session_id = "message";
627 const ContentDecryptionModule::MessageType message_type =
628 ContentDecryptionModule::LICENSE_REQUEST;
629 const std::vector<uint8_t> message = {0, 1, 2};
630 Initialize(SUCCESS);
631 EXPECT_CALL(cdm_client_, OnSessionMessage(session_id, message_type, message));
632 remote_cdm_->CallSessionMessageCB(session_id, message_type, message);
633 base::RunLoop().RunUntilIdle();
634 }
635
636 TEST_F(MojoCdmTest, SessionExpirationChangeCB_Success) {
637 const std::string session_id = "expiration";
638 const base::Time time = base::Time::Now();
639 Initialize(SUCCESS);
640 EXPECT_CALL(cdm_client_, OnSessionExpirationUpdate(session_id, time));
641 remote_cdm_->CallSessionExpirationUpdateCB(session_id, time);
642 base::RunLoop().RunUntilIdle();
643 }
644
645 TEST_F(MojoCdmTest, SessionKeysChangeCB_Success) {
646 const std::string session_id = "change";
647 bool has_additional_usable_key = true;
648 CdmKeysInfo keys_info;
649 Initialize(SUCCESS);
650 EXPECT_CALL(cdm_client_,
651 OnSessionKeysChangeCalled(session_id, has_additional_usable_key));
652 remote_cdm_->CallSessionKeysChangeCB(session_id, has_additional_usable_key,
653 std::move(keys_info));
654 base::RunLoop().RunUntilIdle();
216 } 655 }
217 656
218 } // namespace media 657 } // namespace media
OLDNEW
« media/base/mock_filters.h ('K') | « media/mojo/clients/mojo_cdm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698