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

Side by Side Diff: content/browser/media/cdm/browser_cdm_manager.cc

Issue 850183002: media: Support unprefixed EME API on Android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase and address comments. Created 5 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "content/browser/media/cdm/browser_cdm_manager.h" 5 #include "content/browser/media/cdm/browser_cdm_manager.h"
6 6
7 #include <string>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/command_line.h" 10 #include "base/command_line.h"
9 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
10 #include "base/task_runner.h" 13 #include "base/task_runner.h"
11 #include "content/common/media/cdm_messages.h" 14 #include "content/common/media/cdm_messages.h"
12 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/content_browser_client.h" 16 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/browser/render_frame_host.h" 17 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/render_process_host.h" 18 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/render_view_host.h" 19 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/web_contents.h" 20 #include "content/public/browser/web_contents.h"
18 #include "content/public/common/content_switches.h" 21 #include "content/public/common/content_switches.h"
19 #include "media/base/browser_cdm.h" 22 #include "media/base/browser_cdm.h"
20 #include "media/base/browser_cdm_factory.h" 23 #include "media/base/browser_cdm_factory.h"
24 #include "media/base/cdm_promise.h"
21 #include "media/base/media_switches.h" 25 #include "media/base/media_switches.h"
22 26
23 namespace content { 27 namespace content {
24 28
25 using media::BrowserCdm; 29 using media::BrowserCdm;
26 using media::MediaKeys; 30 using media::MediaKeys;
27 31
32 namespace {
33
28 // Maximum lengths for various EME API parameters. These are checks to 34 // Maximum lengths for various EME API parameters. These are checks to
29 // prevent unnecessarily large parameters from being passed around, and the 35 // prevent unnecessarily large parameters from being passed around, and the
30 // lengths are somewhat arbitrary as the EME spec doesn't specify any limits. 36 // lengths are somewhat arbitrary as the EME spec doesn't specify any limits.
31 const size_t kMaxInitDataLength = 64 * 1024; // 64 KB 37 const size_t kMaxInitDataLength = 64 * 1024; // 64 KB
32 const size_t kMaxSessionResponseLength = 64 * 1024; // 64 KB 38 const size_t kMaxSessionResponseLength = 64 * 1024; // 64 KB
33 const size_t kMaxKeySystemLength = 256; 39 const size_t kMaxKeySystemLength = 256;
34 40
35 // The ID used in this class is a concatenation of |render_frame_id| and 41 // The ID used in this class is a concatenation of |render_frame_id| and
36 // |cdm_id|, i.e. (render_frame_id << 32) + cdm_id. 42 // |cdm_id|, i.e. (render_frame_id << 32) + cdm_id.
37 43
38 static uint64 GetId(int render_frame_id, int cdm_id) { 44 uint64 GetId(int render_frame_id, int cdm_id) {
39 return (static_cast<uint64>(render_frame_id) << 32) + 45 return (static_cast<uint64>(render_frame_id) << 32) +
40 static_cast<uint64>(cdm_id); 46 static_cast<uint64>(cdm_id);
41 } 47 }
42 48
43 static bool IdBelongsToFrame(uint64 id, int render_frame_id) { 49 bool IdBelongsToFrame(uint64 id, int render_frame_id) {
44 return (id >> 32) == static_cast<uint64>(render_frame_id); 50 return (id >> 32) == static_cast<uint64>(render_frame_id);
45 } 51 }
46 52
53 // media::CdmPromiseTemplate implementation backed by a BrowserCdmManager.
54 template <typename... T>
55 class CdmPromiseInternal : public media::CdmPromiseTemplate<T...> {
56 public:
57 CdmPromiseInternal(BrowserCdmManager* manager,
58 int render_frame_id,
59 int cdm_id,
60 uint32_t promise_id)
61 : manager_(manager),
62 render_frame_id_(render_frame_id),
63 cdm_id_(cdm_id),
64 promise_id_(promise_id) {
65 DCHECK(manager_);
66 }
67
68 ~CdmPromiseInternal() final {}
69
70 // CdmPromiseTemplate<> implementation.
71 void resolve(const T&... result) final {
72 MarkPromiseSettled();
73 manager_->ResolvePromise(render_frame_id_, cdm_id_, promise_id_, result...);
74 }
75
76 void reject(MediaKeys::Exception exception,
77 uint32_t system_code,
78 const std::string& error_message) final {
79 MarkPromiseSettled();
80 manager_->RejectPromise(render_frame_id_, cdm_id_, promise_id_, exception,
81 system_code, error_message);
82 }
83
84 private:
85 using media::CdmPromiseTemplate<T...>::MarkPromiseSettled;
86
87 BrowserCdmManager* const manager_;
88 const int render_frame_id_;
89 const int cdm_id_;
90 const uint32_t promise_id_;
91 };
92
93 typedef CdmPromiseInternal<> SimplePromise;
94 typedef CdmPromiseInternal<std::string> NewSessionPromise;
95
96 } // namespace
97
47 // Render process ID to BrowserCdmManager map. 98 // Render process ID to BrowserCdmManager map.
48 typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap; 99 typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap;
49 base::LazyInstance<BrowserCdmManagerMap> g_browser_cdm_manager_map = 100 base::LazyInstance<BrowserCdmManagerMap> g_browser_cdm_manager_map =
50 LAZY_INSTANCE_INITIALIZER; 101 LAZY_INSTANCE_INITIALIZER;
51 102
52 BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) { 103 BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) {
53 DCHECK_CURRENTLY_ON(BrowserThread::UI); 104 DCHECK_CURRENTLY_ON(BrowserThread::UI);
54 105
55 if (!g_browser_cdm_manager_map.Get().count(render_process_id)) 106 if (!g_browser_cdm_manager_map.Get().count(render_process_id))
56 return NULL; 107 return NULL;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 return NULL; 151 return NULL;
101 152
102 return task_runner_.get(); 153 return task_runner_.get();
103 } 154 }
104 155
105 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) { 156 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) {
106 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 157 DCHECK(task_runner_->RunsTasksOnCurrentThread());
107 bool handled = true; 158 bool handled = true;
108 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg) 159 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg)
109 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm) 160 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm)
110 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSession, OnCreateSession) 161 IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate)
162 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest,
163 OnCreateSessionAndGenerateRequest)
111 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession) 164 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession)
112 IPC_MESSAGE_HANDLER(CdmHostMsg_ReleaseSession, OnReleaseSession) 165 IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession)
113 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm) 166 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm)
114 IPC_MESSAGE_UNHANDLED(handled = false) 167 IPC_MESSAGE_UNHANDLED(handled = false)
115 IPC_END_MESSAGE_MAP() 168 IPC_END_MESSAGE_MAP()
116 return handled; 169 return handled;
117 } 170 }
118 171
119 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) { 172 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) {
120 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 173 DCHECK(task_runner_->RunsTasksOnCurrentThread());
121 return cdm_map_.get(GetId(render_frame_id, cdm_id)); 174 return cdm_map_.get(GetId(render_frame_id, cdm_id));
122 } 175 }
123 176
124 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) { 177 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) {
125 if (!task_runner_->RunsTasksOnCurrentThread()) { 178 if (!task_runner_->RunsTasksOnCurrentThread()) {
126 task_runner_->PostTask( 179 task_runner_->PostTask(
127 FROM_HERE, 180 FROM_HERE,
128 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame, 181 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame,
129 this, render_frame_id)); 182 this, render_frame_id));
130 return; 183 return;
131 } 184 }
132 RemoveAllCdmForFrame(render_frame_id); 185 RemoveAllCdmForFrame(render_frame_id);
133 } 186 }
134 187
135 void BrowserCdmManager::OnSessionCreated(int render_frame_id, 188 template <>
189 void BrowserCdmManager::ResolvePromise<>(int render_frame_id,
136 int cdm_id, 190 int cdm_id,
137 uint32 session_id, 191 uint32_t promise_id) {
138 const std::string& web_session_id) { 192 Send(new CdmMsg_ResolvePromise(render_frame_id, cdm_id, promise_id));
139 Send(new CdmMsg_SessionCreated(
140 render_frame_id, cdm_id, session_id, web_session_id));
141 } 193 }
142 194
143 void BrowserCdmManager::OnSessionMessage(int render_frame_id, 195 template <>
144 int cdm_id, 196 void BrowserCdmManager::ResolvePromise<std::string>(
145 uint32 session_id, 197 int render_frame_id,
146 const std::vector<uint8>& message, 198 int cdm_id,
147 const GURL& destination_url) { 199 uint32_t promise_id,
148 GURL verified_gurl = destination_url; 200 const std::string& session_id) {
201 Send(new CdmMsg_ResolvePromiseWithSession(render_frame_id, cdm_id, promise_id,
202 session_id));
203 }
204
205 void BrowserCdmManager::RejectPromise(int render_frame_id,
206 int cdm_id,
207 uint32_t promise_id,
208 media::MediaKeys::Exception exception,
209 uint32_t system_code,
210 const std::string& error_message) {
211 Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception,
212 system_code, error_message));
213 }
214
215 void BrowserCdmManager::OnSessionMessage(
216 int render_frame_id,
217 int cdm_id,
218 const std::string& session_id,
219 media::MediaKeys::MessageType message_type,
220 const std::vector<uint8>& message,
221 const GURL& legacy_destination_url) {
222 GURL verified_gurl = legacy_destination_url;
149 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { 223 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
150 DLOG(WARNING) << "SessionMessage destination_url is invalid : " 224 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : "
151 << destination_url.possibly_invalid_spec(); 225 << legacy_destination_url.possibly_invalid_spec();
152 verified_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. 226 verified_gurl =
227 GURL::EmptyGURL(); // Replace invalid legacy_destination_url.
153 } 228 }
154 229
155 Send(new CdmMsg_SessionMessage( 230 Send(new CdmMsg_SessionMessage(render_frame_id, cdm_id, session_id,
156 render_frame_id, cdm_id, session_id, message, verified_gurl)); 231 message_type, message, verified_gurl));
157 }
158
159 void BrowserCdmManager::OnSessionReady(int render_frame_id,
160 int cdm_id,
161 uint32 session_id) {
162 Send(new CdmMsg_SessionReady(render_frame_id, cdm_id, session_id));
163 } 232 }
164 233
165 void BrowserCdmManager::OnSessionClosed(int render_frame_id, 234 void BrowserCdmManager::OnSessionClosed(int render_frame_id,
166 int cdm_id, 235 int cdm_id,
167 uint32 session_id) { 236 const std::string& session_id) {
168 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id)); 237 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id));
169 } 238 }
170 239
171 void BrowserCdmManager::OnSessionError(int render_frame_id, 240 void BrowserCdmManager::OnLegacySessionError(
172 int cdm_id, 241 int render_frame_id,
173 uint32 session_id, 242 int cdm_id,
174 MediaKeys::KeyError error_code, 243 const std::string& session_id,
175 uint32 system_code) { 244 MediaKeys::Exception exception_code,
176 Send(new CdmMsg_SessionError( 245 uint32 system_code,
177 render_frame_id, cdm_id, session_id, error_code, system_code)); 246 const std::string& error_message) {
247 Send(new CdmMsg_LegacySessionError(render_frame_id, cdm_id, session_id,
248 exception_code, system_code,
249 error_message));
250 }
251
252 void BrowserCdmManager::OnSessionKeysChange(int render_frame_id,
253 int cdm_id,
254 const std::string& session_id,
255 bool has_additional_usable_key,
256 media::CdmKeysInfo keys_info) {
257 std::vector<media::CdmKeyInformation> key_info_vector;
258 for (const auto& key_info : keys_info)
259 key_info_vector.push_back(*key_info);
260 Send(new CdmMsg_SessionKeysChange(render_frame_id, cdm_id, session_id,
261 has_additional_usable_key,
262 key_info_vector));
263 }
264
265 void BrowserCdmManager::OnSessionExpirationUpdate(
266 int render_frame_id,
267 int cdm_id,
268 const std::string& session_id,
269 const base::Time& new_expiry_time) {
270 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id,
271 new_expiry_time));
178 } 272 }
179 273
180 void BrowserCdmManager::OnInitializeCdm(int render_frame_id, 274 void BrowserCdmManager::OnInitializeCdm(int render_frame_id,
181 int cdm_id, 275 int cdm_id,
182 const std::string& key_system, 276 const std::string& key_system,
183 const GURL& security_origin) { 277 const GURL& security_origin) {
184 if (key_system.size() > kMaxKeySystemLength) { 278 if (key_system.size() > kMaxKeySystemLength) {
185 // This failure will be discovered and reported by OnCreateSession() 279 // This failure will be discovered and reported by OnCreateSession()
186 // as GetCdm() will return null. 280 // as GetCdm() will return null.
187 NOTREACHED() << "Invalid key system: " << key_system; 281 NOTREACHED() << "Invalid key system: " << key_system;
188 return; 282 return;
189 } 283 }
190 284
191 AddCdm(render_frame_id, cdm_id, key_system, security_origin); 285 AddCdm(render_frame_id, cdm_id, key_system, security_origin);
192 } 286 }
193 287
194 void BrowserCdmManager::OnCreateSession( 288 void BrowserCdmManager::OnSetServerCertificate(
195 int render_frame_id, 289 int render_frame_id,
196 int cdm_id, 290 int cdm_id,
197 uint32 session_id, 291 uint32_t promise_id,
198 CdmHostMsg_CreateSession_ContentType content_type, 292 const std::vector<uint8_t>& certificate) {
293 scoped_ptr<SimplePromise> promise(
294 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
295
296 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
297 if (!cdm) {
298 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
299 return;
300 }
301
302 if (certificate.empty()) {
303 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate.");
304 return;
305 }
306
307 cdm->SetServerCertificate(&certificate[0], certificate.size(),
308 promise.Pass());
309 }
310
311 void BrowserCdmManager::OnCreateSessionAndGenerateRequest(
312 int render_frame_id,
313 int cdm_id,
314 uint32_t promise_id,
315 CdmHostMsg_CreateSession_InitDataType init_data_type,
199 const std::vector<uint8>& init_data) { 316 const std::vector<uint8>& init_data) {
317 scoped_ptr<NewSessionPromise> promise(
318 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id));
319
200 if (init_data.size() > kMaxInitDataLength) { 320 if (init_data.size() > kMaxInitDataLength) {
201 LOG(WARNING) << "InitData for ID: " << cdm_id 321 LOG(WARNING) << "InitData for ID: " << cdm_id
202 << " too long: " << init_data.size(); 322 << " too long: " << init_data.size();
203 SendSessionError(render_frame_id, cdm_id, session_id); 323 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long.");
204 return; 324 return;
205 } 325 }
206 326
207 // Convert the session content type into a MIME type. "audio" and "video" 327 // Convert the session content type into a MIME type. "audio" and "video"
208 // don't matter, so using "video" for the MIME type. 328 // don't matter, so using "video" for the MIME type.
209 // Ref: 329 // Ref:
210 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte d-media.html#dom-createsession 330 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte d-media.html#dom-createsession
211 std::string mime_type; 331 std::string mime_type;
212 switch (content_type) { 332 switch (init_data_type) {
213 case CREATE_SESSION_TYPE_WEBM: 333 case CREATE_SESSION_TYPE_WEBM:
214 mime_type = "video/webm"; 334 mime_type = "video/webm";
215 break; 335 break;
216 case CREATE_SESSION_TYPE_MP4: 336 case CREATE_SESSION_TYPE_MP4:
217 mime_type = "video/mp4"; 337 mime_type = "video/mp4";
218 break; 338 break;
219 default: 339 default:
220 NOTREACHED(); 340 NOTREACHED();
341 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
342 "Invalid init data type.");
221 return; 343 return;
222 } 344 }
223 345
224 #if defined(OS_ANDROID) 346 #if defined(OS_ANDROID)
225 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 347 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
226 switches::kDisableInfobarForProtectedMediaIdentifier)) { 348 switches::kDisableInfobarForProtectedMediaIdentifier)) {
227 CreateSessionIfPermitted( 349 GenerateRequestIfPermitted(render_frame_id, cdm_id, mime_type, init_data,
228 render_frame_id, cdm_id, session_id, mime_type, init_data, true); 350 promise.Pass(), true);
229 return; 351 return;
230 } 352 }
231 #endif 353 #endif
232 354
233 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 355 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
234 if (!cdm) { 356 if (!cdm) {
235 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 357 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
236 SendSessionError(render_frame_id, cdm_id, session_id); 358 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
237 return; 359 return;
238 } 360 }
239 361
240 std::map<uint64, GURL>::const_iterator iter = 362 std::map<uint64, GURL>::const_iterator iter =
241 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); 363 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id));
242 if (iter == cdm_security_origin_map_.end()) { 364 if (iter == cdm_security_origin_map_.end()) {
243 NOTREACHED(); 365 NOTREACHED();
244 SendSessionError(render_frame_id, cdm_id, session_id); 366 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
245 return; 367 return;
246 } 368 }
247 GURL security_origin = iter->second; 369 GURL security_origin = iter->second;
248 370
249 RequestSessionPermission(render_frame_id, 371 RequestSessionPermission(render_frame_id, security_origin, cdm_id, mime_type,
250 security_origin, 372 init_data, promise.Pass());
251 cdm_id,
252 session_id,
253 mime_type,
254 init_data);
255 } 373 }
256 374
257 void BrowserCdmManager::OnUpdateSession( 375 void BrowserCdmManager::OnUpdateSession(int render_frame_id,
258 int render_frame_id, 376 int cdm_id,
259 int cdm_id, 377 uint32_t promise_id,
260 uint32 session_id, 378 const std::string& session_id,
261 const std::vector<uint8>& response) { 379 const std::vector<uint8>& response) {
380 scoped_ptr<SimplePromise> promise(
381 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
382
262 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 383 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
263 if (!cdm) { 384 if (!cdm) {
264 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 385 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
265 SendSessionError(render_frame_id, cdm_id, session_id);
266 return; 386 return;
267 } 387 }
268 388
269 if (response.size() > kMaxSessionResponseLength) { 389 if (response.size() > kMaxSessionResponseLength) {
270 LOG(WARNING) << "Response for ID " << cdm_id 390 LOG(WARNING) << "Response for ID " << cdm_id
271 << " is too long: " << response.size(); 391 << " is too long: " << response.size();
272 SendSessionError(render_frame_id, cdm_id, session_id); 392 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long.");
273 return; 393 return;
274 } 394 }
275 395
276 cdm->UpdateSession(session_id, &response[0], response.size()); 396 if (response.empty()) {
277 } 397 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty.");
278
279 void BrowserCdmManager::OnReleaseSession(int render_frame_id,
280 int cdm_id,
281 uint32 session_id) {
282 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
283 if (!cdm) {
284 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
285 SendSessionError(render_frame_id, cdm_id, session_id);
286 return; 398 return;
287 } 399 }
288 400
289 cdm->ReleaseSession(session_id); 401 cdm->UpdateSession(session_id, &response[0], response.size(), promise.Pass());
402 }
403
404 void BrowserCdmManager::OnCloseSession(int render_frame_id,
405 int cdm_id,
406 uint32_t promise_id,
407 const std::string& session_id) {
408 scoped_ptr<SimplePromise> promise(
409 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
410
411 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
412 if (!cdm) {
413 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
414 return;
415 }
416
417 cdm->CloseSession(session_id, promise.Pass());
290 } 418 }
291 419
292 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { 420 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) {
293 RemoveCdm(GetId(render_frame_id, cdm_id)); 421 RemoveCdm(GetId(render_frame_id, cdm_id));
294 } 422 }
295 423
296 void BrowserCdmManager::SendSessionError(int render_frame_id,
297 int cdm_id,
298 uint32 session_id) {
299 OnSessionError(
300 render_frame_id, cdm_id, session_id, MediaKeys::kUnknownError, 0);
301 }
302
303 #define BROWSER_CDM_MANAGER_CB(func) \ 424 #define BROWSER_CDM_MANAGER_CB(func) \
304 base::Bind(&BrowserCdmManager::func, this, render_frame_id, cdm_id) 425 base::Bind(&BrowserCdmManager::func, this, render_frame_id, cdm_id)
305 426
306 void BrowserCdmManager::AddCdm(int render_frame_id, 427 void BrowserCdmManager::AddCdm(int render_frame_id,
307 int cdm_id, 428 int cdm_id,
308 const std::string& key_system, 429 const std::string& key_system,
309 const GURL& security_origin) { 430 const GURL& security_origin) {
310 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 431 DCHECK(task_runner_->RunsTasksOnCurrentThread());
311 DCHECK(!GetCdm(render_frame_id, cdm_id)); 432 DCHECK(!GetCdm(render_frame_id, cdm_id));
312 433
313 scoped_ptr<BrowserCdm> cdm( 434 scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
314 media::CreateBrowserCdm(key_system, 435 key_system, BROWSER_CDM_MANAGER_CB(OnSessionMessage),
315 BROWSER_CDM_MANAGER_CB(OnSessionCreated), 436 BROWSER_CDM_MANAGER_CB(OnSessionClosed),
316 BROWSER_CDM_MANAGER_CB(OnSessionMessage), 437 BROWSER_CDM_MANAGER_CB(OnLegacySessionError),
317 BROWSER_CDM_MANAGER_CB(OnSessionReady), 438 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange),
318 BROWSER_CDM_MANAGER_CB(OnSessionClosed), 439 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate)));
319 BROWSER_CDM_MANAGER_CB(OnSessionError)));
320 440
321 if (!cdm) { 441 if (!cdm) {
322 // This failure will be discovered and reported by OnCreateSession() 442 // This failure will be discovered and reported by
323 // as GetCdm() will return null. 443 // OnCreateSessionAndGenerateRequest() as GetCdm() will return null.
324 DVLOG(1) << "failed to create CDM."; 444 DVLOG(1) << "failed to create CDM.";
325 return; 445 return;
326 } 446 }
327 447
328 uint64 id = GetId(render_frame_id, cdm_id); 448 uint64 id = GetId(render_frame_id, cdm_id);
329 cdm_map_.add(id, cdm.Pass()); 449 cdm_map_.add(id, cdm.Pass());
330 cdm_security_origin_map_[id] = security_origin; 450 cdm_security_origin_map_[id] = security_origin;
331 } 451 }
332 452
333 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) { 453 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) {
(...skipping 17 matching lines...) Expand all
351 if (cdm_cancel_permission_map_.count(id)) { 471 if (cdm_cancel_permission_map_.count(id)) {
352 cdm_cancel_permission_map_[id].Run(); 472 cdm_cancel_permission_map_[id].Run();
353 cdm_cancel_permission_map_.erase(id); 473 cdm_cancel_permission_map_.erase(id);
354 } 474 }
355 } 475 }
356 476
357 void BrowserCdmManager::RequestSessionPermission( 477 void BrowserCdmManager::RequestSessionPermission(
358 int render_frame_id, 478 int render_frame_id,
359 const GURL& security_origin, 479 const GURL& security_origin,
360 int cdm_id, 480 int cdm_id,
361 uint32 session_id, 481 const std::string& init_data_type,
362 const std::string& content_type, 482 const std::vector<uint8>& init_data,
363 const std::vector<uint8>& init_data) { 483 scoped_ptr<media::NewSessionCdmPromise> promise) {
364 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 484 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
365 BrowserThread::PostTask( 485 BrowserThread::PostTask(
366 BrowserThread::UI, 486 BrowserThread::UI, FROM_HERE,
367 FROM_HERE, 487 base::Bind(&BrowserCdmManager::RequestSessionPermission, this,
368 base::Bind(&BrowserCdmManager::RequestSessionPermission, 488 render_frame_id, security_origin, cdm_id, init_data_type,
369 this, 489 init_data, base::Passed(&promise)));
370 render_frame_id,
371 security_origin,
372 cdm_id,
373 session_id,
374 content_type,
375 init_data));
376 return; 490 return;
377 } 491 }
378 492
379 RenderFrameHost* rfh = 493 RenderFrameHost* rfh =
380 RenderFrameHost::FromID(render_process_id_, render_frame_id); 494 RenderFrameHost::FromID(render_process_id_, render_frame_id);
381 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); 495 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
382 DCHECK(web_contents); 496 DCHECK(web_contents);
383 GetContentClient()->browser()->RequestPermission( 497 GetContentClient()->browser()->RequestPermission(
384 content::PERMISSION_PROTECTED_MEDIA, 498 content::PERMISSION_PROTECTED_MEDIA, web_contents,
385 web_contents,
386 0, // bridge id 499 0, // bridge id
387 security_origin, 500 security_origin,
388 // Only implemented for Android infobars which do not support 501 // Only implemented for Android infobars which do not support
389 // user gestures. 502 // user gestures.
390 true, 503 true, base::Bind(&BrowserCdmManager::GenerateRequestIfPermitted, this,
391 base::Bind(&BrowserCdmManager::CreateSessionIfPermitted, 504 render_frame_id, cdm_id, init_data_type, init_data,
392 this, 505 base::Passed(&promise)));
393 render_frame_id,
394 cdm_id,
395 session_id,
396 content_type,
397 init_data));
398 } 506 }
399 507
400 void BrowserCdmManager::CreateSessionIfPermitted( 508 void BrowserCdmManager::GenerateRequestIfPermitted(
401 int render_frame_id, 509 int render_frame_id,
402 int cdm_id, 510 int cdm_id,
403 uint32 session_id, 511 const std::string& init_data_type,
404 const std::string& content_type,
405 const std::vector<uint8>& init_data, 512 const std::vector<uint8>& init_data,
513 scoped_ptr<media::NewSessionCdmPromise> promise,
406 bool permitted) { 514 bool permitted) {
407 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id)); 515 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id));
408 if (!permitted) { 516 if (!permitted) {
409 SendSessionError(render_frame_id, cdm_id, session_id); 517 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
410 return; 518 return;
411 } 519 }
412 520
413 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 521 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
414 if (!cdm) { 522 if (!cdm) {
415 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 523 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
416 SendSessionError(render_frame_id, cdm_id, session_id);
417 return; 524 return;
418 } 525 }
419 526
420 // This could fail, in which case a SessionError will be fired. 527 // Only temporary session is supported in browser CDM path. Add SessionType
ddorwin 2015/01/15 17:36:52 tiny nit: The first sentence doesn't read well. "O
xhwang 2015/01/15 19:03:44 Done.
421 cdm->CreateSession(session_id, content_type, &init_data[0], init_data.size()); 528 // support if needed.
529 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION,
530 init_data_type, &init_data[0],
531 init_data.size(), promise.Pass());
422 } 532 }
423 533
424 } // namespace content 534 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698