Add ICU message format support
[chromium-blink-merge.git] / content / browser / media / cdm / browser_cdm_manager.cc
blobe7d786c4524d733d6078c4f1f743b7060c58fcc6
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
3 // found in the LICENSE file.
5 #include "content/browser/media/cdm/browser_cdm_manager.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/lazy_instance.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/task_runner.h"
13 #include "content/public/browser/browser_context.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/content_browser_client.h"
16 #include "content/public/browser/permission_manager.h"
17 #include "content/public/browser/permission_type.h"
18 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "content/public/browser/render_process_host_observer.h"
21 #include "content/public/browser/web_contents.h"
22 #include "media/base/browser_cdm.h"
23 #include "media/base/browser_cdm_factory.h"
24 #include "media/base/cdm_promise.h"
25 #include "media/base/limits.h"
27 #if defined(OS_ANDROID)
28 #include "content/public/common/renderer_preferences.h"
29 #endif
31 namespace content {
33 using media::BrowserCdm;
34 using media::MediaKeys;
36 namespace {
38 #if defined(OS_ANDROID)
39 // Android only supports 128-bit key IDs.
40 const size_t kAndroidKeyIdBytes = 128 / 8;
41 #endif
43 // The ID used in this class is a concatenation of |render_frame_id| and
44 // |cdm_id|, i.e. (render_frame_id << 32) + cdm_id.
46 uint64 GetId(int render_frame_id, int cdm_id) {
47 return (static_cast<uint64>(render_frame_id) << 32) +
48 static_cast<uint64>(cdm_id);
51 bool IdBelongsToFrame(uint64 id, int render_frame_id) {
52 return (id >> 32) == static_cast<uint64>(render_frame_id);
55 // media::CdmPromiseTemplate implementation backed by a BrowserCdmManager.
56 template <typename... T>
57 class CdmPromiseInternal : public media::CdmPromiseTemplate<T...> {
58 public:
59 CdmPromiseInternal(BrowserCdmManager* manager,
60 int render_frame_id,
61 int cdm_id,
62 uint32_t promise_id)
63 : manager_(manager),
64 render_frame_id_(render_frame_id),
65 cdm_id_(cdm_id),
66 promise_id_(promise_id) {
67 DCHECK(manager_);
70 ~CdmPromiseInternal() final {}
72 // CdmPromiseTemplate<> implementation.
73 void resolve(const T&... result) final;
75 void reject(MediaKeys::Exception exception,
76 uint32_t system_code,
77 const std::string& error_message) final {
78 MarkPromiseSettled();
79 manager_->RejectPromise(render_frame_id_, cdm_id_, promise_id_, exception,
80 system_code, error_message);
83 private:
84 using media::CdmPromiseTemplate<T...>::MarkPromiseSettled;
86 BrowserCdmManager* const manager_;
87 const int render_frame_id_;
88 const int cdm_id_;
89 const uint32_t promise_id_;
92 template <>
93 void CdmPromiseInternal<>::resolve() {
94 MarkPromiseSettled();
95 manager_->ResolvePromise(render_frame_id_, cdm_id_, promise_id_);
98 template <>
99 void CdmPromiseInternal<std::string>::resolve(const std::string& session_id) {
100 MarkPromiseSettled();
101 manager_->ResolvePromiseWithSession(render_frame_id_, cdm_id_, promise_id_,
102 session_id);
105 typedef CdmPromiseInternal<> SimplePromise;
106 typedef CdmPromiseInternal<std::string> NewSessionPromise;
108 // Render process ID to BrowserCdmManager map.
109 typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap;
110 base::LazyInstance<BrowserCdmManagerMap>::Leaky g_browser_cdm_manager_map =
111 LAZY_INSTANCE_INITIALIZER;
113 // Keeps the BrowserCdmManager alive, and in the global map, for as long as the
114 // RenderProcessHost is connected to the child process. This class is a
115 // self-owned observer.
116 class BrowserCdmManagerProcessWatcher : public RenderProcessHostObserver {
117 public:
118 BrowserCdmManagerProcessWatcher(
119 int render_process_id,
120 const scoped_refptr<BrowserCdmManager>& manager)
121 : browser_cdm_manager_(manager) {
122 RenderProcessHost::FromID(render_process_id)->AddObserver(this);
123 CHECK(g_browser_cdm_manager_map.Get()
124 .insert(std::make_pair(render_process_id, manager.get()))
125 .second);
128 // RenderProcessHostObserver:
129 void RenderProcessExited(RenderProcessHost* host,
130 base::TerminationStatus /* status */,
131 int /* exit_code */) override {
132 RemoveHostObserverAndDestroy(host);
135 void RenderProcessHostDestroyed(RenderProcessHost* host) override {
136 RemoveHostObserverAndDestroy(host);
139 private:
140 void RemoveHostObserverAndDestroy(RenderProcessHost* host) {
141 CHECK(g_browser_cdm_manager_map.Get().erase(host->GetID()));
142 host->RemoveObserver(this);
143 delete this;
146 const scoped_refptr<BrowserCdmManager> browser_cdm_manager_;
149 } // namespace
151 // static
152 BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) {
153 DCHECK_CURRENTLY_ON(BrowserThread::UI);
154 auto& map = g_browser_cdm_manager_map.Get();
155 auto iterator = map.find(render_process_id);
156 return (iterator == map.end()) ? nullptr : iterator->second;
159 BrowserCdmManager::BrowserCdmManager(
160 int render_process_id,
161 const scoped_refptr<base::TaskRunner>& task_runner)
162 : BrowserMessageFilter(CdmMsgStart),
163 render_process_id_(render_process_id),
164 task_runner_(task_runner),
165 weak_ptr_factory_(this) {
166 DVLOG(1) << __FUNCTION__ << ": " << render_process_id_;
167 DCHECK_CURRENTLY_ON(BrowserThread::UI);
169 new BrowserCdmManagerProcessWatcher(render_process_id, this);
171 if (!task_runner_.get()) {
172 task_runner_ =
173 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
177 BrowserCdmManager::~BrowserCdmManager() {
178 DVLOG(1) << __FUNCTION__ << ": " << render_process_id_;
179 DCHECK_CURRENTLY_ON(BrowserThread::UI);
182 // Makes sure BrowserCdmManager is always deleted on the Browser UI thread.
183 void BrowserCdmManager::OnDestruct() const {
184 DVLOG(1) << __FUNCTION__ << ": " << render_process_id_;
185 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
186 delete this;
187 } else {
188 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
192 base::TaskRunner* BrowserCdmManager::OverrideTaskRunnerForMessage(
193 const IPC::Message& message) {
194 // Only handles CDM messages.
195 if (IPC_MESSAGE_CLASS(message) != CdmMsgStart)
196 return NULL;
198 return task_runner_.get();
201 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) {
202 DCHECK(task_runner_->RunsTasksOnCurrentThread());
203 bool handled = true;
204 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg)
205 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm)
206 IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate)
207 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest,
208 OnCreateSessionAndGenerateRequest)
209 IPC_MESSAGE_HANDLER(CdmHostMsg_LoadSession, OnLoadSession)
210 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession)
211 IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession)
212 IPC_MESSAGE_HANDLER(CdmHostMsg_RemoveSession, OnRemoveSession)
213 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm)
214 IPC_MESSAGE_UNHANDLED(handled = false)
215 IPC_END_MESSAGE_MAP()
216 return handled;
219 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id,
220 int cdm_id) const {
221 DCHECK(task_runner_->RunsTasksOnCurrentThread());
222 return cdm_map_.get(GetId(render_frame_id, cdm_id));
225 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) {
226 if (!task_runner_->RunsTasksOnCurrentThread()) {
227 task_runner_->PostTask(
228 FROM_HERE,
229 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame,
230 this, render_frame_id));
231 return;
233 RemoveAllCdmForFrame(render_frame_id);
236 void BrowserCdmManager::ResolvePromise(int render_frame_id,
237 int cdm_id,
238 uint32_t promise_id) {
239 Send(new CdmMsg_ResolvePromise(render_frame_id, cdm_id, promise_id));
242 void BrowserCdmManager::ResolvePromiseWithSession(
243 int render_frame_id,
244 int cdm_id,
245 uint32_t promise_id,
246 const std::string& session_id) {
247 if (session_id.length() > media::limits::kMaxSessionIdLength) {
248 RejectPromise(render_frame_id, cdm_id, promise_id,
249 MediaKeys::INVALID_ACCESS_ERROR, 0,
250 "Session ID is too long.");
251 return;
254 Send(new CdmMsg_ResolvePromiseWithSession(render_frame_id, cdm_id, promise_id,
255 session_id));
258 void BrowserCdmManager::RejectPromise(int render_frame_id,
259 int cdm_id,
260 uint32_t promise_id,
261 media::MediaKeys::Exception exception,
262 uint32_t system_code,
263 const std::string& error_message) {
264 Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception,
265 system_code, error_message));
268 void BrowserCdmManager::OnSessionMessage(
269 int render_frame_id,
270 int cdm_id,
271 const std::string& session_id,
272 media::MediaKeys::MessageType message_type,
273 const std::vector<uint8>& message,
274 const GURL& legacy_destination_url) {
275 GURL verified_gurl = legacy_destination_url;
276 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
277 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : "
278 << legacy_destination_url.possibly_invalid_spec();
279 verified_gurl =
280 GURL::EmptyGURL(); // Replace invalid legacy_destination_url.
283 Send(new CdmMsg_SessionMessage(render_frame_id, cdm_id, session_id,
284 message_type, message, verified_gurl));
287 void BrowserCdmManager::OnSessionClosed(int render_frame_id,
288 int cdm_id,
289 const std::string& session_id) {
290 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id));
293 void BrowserCdmManager::OnLegacySessionError(
294 int render_frame_id,
295 int cdm_id,
296 const std::string& session_id,
297 MediaKeys::Exception exception_code,
298 uint32 system_code,
299 const std::string& error_message) {
300 Send(new CdmMsg_LegacySessionError(render_frame_id, cdm_id, session_id,
301 exception_code, system_code,
302 error_message));
305 void BrowserCdmManager::OnSessionKeysChange(int render_frame_id,
306 int cdm_id,
307 const std::string& session_id,
308 bool has_additional_usable_key,
309 media::CdmKeysInfo keys_info) {
310 std::vector<media::CdmKeyInformation> key_info_vector;
311 for (const auto& key_info : keys_info)
312 key_info_vector.push_back(*key_info);
313 Send(new CdmMsg_SessionKeysChange(render_frame_id, cdm_id, session_id,
314 has_additional_usable_key,
315 key_info_vector));
318 void BrowserCdmManager::OnSessionExpirationUpdate(
319 int render_frame_id,
320 int cdm_id,
321 const std::string& session_id,
322 const base::Time& new_expiry_time) {
323 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id,
324 new_expiry_time));
327 void BrowserCdmManager::OnInitializeCdm(
328 int render_frame_id,
329 int cdm_id,
330 uint32_t promise_id,
331 const CdmHostMsg_InitializeCdm_Params& params) {
332 if (params.key_system.size() > media::limits::kMaxKeySystemLength) {
333 NOTREACHED() << "Invalid key system: " << params.key_system;
334 RejectPromise(render_frame_id, cdm_id, promise_id,
335 MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system.");
336 return;
339 AddCdm(render_frame_id, cdm_id, promise_id, params.key_system,
340 params.security_origin, params.use_hw_secure_codecs);
343 void BrowserCdmManager::OnSetServerCertificate(
344 int render_frame_id,
345 int cdm_id,
346 uint32_t promise_id,
347 const std::vector<uint8_t>& certificate) {
348 DCHECK(task_runner_->RunsTasksOnCurrentThread());
350 scoped_ptr<SimplePromise> promise(
351 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
353 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
354 if (!cdm) {
355 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
356 return;
359 if (certificate.empty()) {
360 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate.");
361 return;
364 cdm->SetServerCertificate(certificate, promise.Pass());
367 void BrowserCdmManager::OnCreateSessionAndGenerateRequest(
368 const CdmHostMsg_CreateSessionAndGenerateRequest_Params& params) {
369 DCHECK(task_runner_->RunsTasksOnCurrentThread());
371 int render_frame_id = params.render_frame_id;
372 int cdm_id = params.cdm_id;
373 const std::vector<uint8>& init_data = params.init_data;
374 scoped_ptr<NewSessionPromise> promise(
375 new NewSessionPromise(this, render_frame_id, cdm_id, params.promise_id));
377 if (init_data.size() > media::limits::kMaxInitDataLength) {
378 LOG(WARNING) << "InitData for ID: " << cdm_id
379 << " too long: " << init_data.size();
380 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long.");
381 return;
383 #if defined(OS_ANDROID)
384 // 'webm' initData is a single key ID. On Android the length is restricted.
385 if (params.init_data_type == INIT_DATA_TYPE_WEBM &&
386 init_data.size() != kAndroidKeyIdBytes) {
387 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
388 "'webm' initData is not the correct length.");
389 return;
391 #endif
393 media::EmeInitDataType eme_init_data_type;
394 switch (params.init_data_type) {
395 case INIT_DATA_TYPE_WEBM:
396 eme_init_data_type = media::EmeInitDataType::WEBM;
397 break;
398 #if defined(USE_PROPRIETARY_CODECS)
399 case INIT_DATA_TYPE_CENC:
400 eme_init_data_type = media::EmeInitDataType::CENC;
401 break;
402 #endif
403 default:
404 NOTREACHED();
405 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
406 "Invalid init data type.");
407 return;
410 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
411 if (!cdm) {
412 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
413 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
414 return;
417 CheckPermissionStatus(
418 render_frame_id, cdm_id,
419 base::Bind(&BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted,
420 this, render_frame_id, cdm_id, params.session_type,
421 eme_init_data_type, init_data, base::Passed(&promise)));
424 void BrowserCdmManager::OnLoadSession(
425 int render_frame_id,
426 int cdm_id,
427 uint32_t promise_id,
428 media::MediaKeys::SessionType session_type,
429 const std::string& session_id) {
430 DCHECK(task_runner_->RunsTasksOnCurrentThread());
432 scoped_ptr<NewSessionPromise> promise(
433 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id));
435 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
436 if (!cdm) {
437 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
438 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
439 return;
442 CheckPermissionStatus(
443 render_frame_id, cdm_id,
444 base::Bind(&BrowserCdmManager::LoadSessionIfPermitted,
445 this, render_frame_id, cdm_id, session_type,
446 session_id, base::Passed(&promise)));
449 void BrowserCdmManager::OnUpdateSession(int render_frame_id,
450 int cdm_id,
451 uint32_t promise_id,
452 const std::string& session_id,
453 const std::vector<uint8>& response) {
454 DCHECK(task_runner_->RunsTasksOnCurrentThread());
456 scoped_ptr<SimplePromise> promise(
457 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
459 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
460 if (!cdm) {
461 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
462 return;
465 if (response.size() > media::limits::kMaxSessionResponseLength) {
466 LOG(WARNING) << "Response for ID " << cdm_id
467 << " is too long: " << response.size();
468 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long.");
469 return;
472 if (response.empty()) {
473 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty.");
474 return;
477 cdm->UpdateSession(session_id, response, promise.Pass());
480 void BrowserCdmManager::OnCloseSession(int render_frame_id,
481 int cdm_id,
482 uint32_t promise_id,
483 const std::string& session_id) {
484 DCHECK(task_runner_->RunsTasksOnCurrentThread());
486 scoped_ptr<SimplePromise> promise(
487 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
489 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
490 if (!cdm) {
491 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
492 return;
495 cdm->CloseSession(session_id, promise.Pass());
498 void BrowserCdmManager::OnRemoveSession(int render_frame_id,
499 int cdm_id,
500 uint32_t promise_id,
501 const std::string& session_id) {
502 DCHECK(task_runner_->RunsTasksOnCurrentThread());
504 scoped_ptr<SimplePromise> promise(
505 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
507 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
508 if (!cdm) {
509 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
510 return;
513 cdm->RemoveSession(session_id, promise.Pass());
516 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) {
517 DCHECK(task_runner_->RunsTasksOnCurrentThread());
518 RemoveCdm(GetId(render_frame_id, cdm_id));
521 // Use a weak pointer here instead of |this| to avoid circular references.
522 #define BROWSER_CDM_MANAGER_CB(func) \
523 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \
524 render_frame_id, cdm_id)
526 void BrowserCdmManager::AddCdm(int render_frame_id,
527 int cdm_id,
528 uint32_t promise_id,
529 const std::string& key_system,
530 const GURL& security_origin,
531 bool use_hw_secure_codecs) {
532 DCHECK(task_runner_->RunsTasksOnCurrentThread());
533 DCHECK(!GetCdm(render_frame_id, cdm_id));
535 scoped_ptr<SimplePromise> promise(
536 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
538 scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
539 key_system, use_hw_secure_codecs,
540 BROWSER_CDM_MANAGER_CB(OnSessionMessage),
541 BROWSER_CDM_MANAGER_CB(OnSessionClosed),
542 BROWSER_CDM_MANAGER_CB(OnLegacySessionError),
543 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange),
544 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate)));
546 if (!cdm) {
547 DVLOG(1) << "failed to create CDM.";
548 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "Failed to create CDM.");
549 return;
552 uint64 id = GetId(render_frame_id, cdm_id);
553 cdm_map_.add(id, cdm.Pass());
554 cdm_security_origin_map_[id] = security_origin;
555 promise->resolve();
558 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) {
559 DCHECK(task_runner_->RunsTasksOnCurrentThread());
561 std::vector<uint64> ids_to_remove;
562 for (CdmMap::iterator it = cdm_map_.begin(); it != cdm_map_.end(); ++it) {
563 if (IdBelongsToFrame(it->first, render_frame_id))
564 ids_to_remove.push_back(it->first);
567 for (size_t i = 0; i < ids_to_remove.size(); ++i)
568 RemoveCdm(ids_to_remove[i]);
571 void BrowserCdmManager::RemoveCdm(uint64 id) {
572 DCHECK(task_runner_->RunsTasksOnCurrentThread());
574 cdm_map_.erase(id);
575 cdm_security_origin_map_.erase(id);
578 void BrowserCdmManager::CheckPermissionStatus(
579 int render_frame_id,
580 int cdm_id,
581 const PermissionStatusCB& permission_status_cb) {
582 // Always called on |task_runner_|, which may not be on the UI thread.
583 DCHECK(task_runner_->RunsTasksOnCurrentThread());
585 GURL security_origin;
586 std::map<uint64, GURL>::const_iterator iter =
587 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id));
588 DCHECK(iter != cdm_security_origin_map_.end());
589 if (iter != cdm_security_origin_map_.end())
590 security_origin = iter->second;
592 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
593 BrowserThread::PostTask(
594 BrowserThread::UI, FROM_HERE,
595 base::Bind(&BrowserCdmManager::CheckPermissionStatusOnUIThread, this,
596 render_frame_id, security_origin, permission_status_cb));
597 } else {
598 CheckPermissionStatusOnUIThread(render_frame_id, security_origin,
599 permission_status_cb);
603 // Note: This function runs on the UI thread, which may be different from
604 // |task_runner_|. Be careful about thread safety!
605 void BrowserCdmManager::CheckPermissionStatusOnUIThread(
606 int render_frame_id,
607 const GURL& security_origin,
608 const base::Callback<void(bool)>& permission_status_cb) {
609 DCHECK_CURRENTLY_ON(BrowserThread::UI);
611 RenderFrameHost* rfh =
612 RenderFrameHost::FromID(render_process_id_, render_frame_id);
613 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
614 PermissionManager* permission_manager =
615 web_contents->GetBrowserContext()->GetPermissionManager();
616 if (!permission_manager) {
617 permission_status_cb.Run(false);
618 return;
621 PermissionStatus permission_status = permission_manager->GetPermissionStatus(
622 PermissionType::PROTECTED_MEDIA_IDENTIFIER, security_origin,
623 web_contents->GetLastCommittedURL().GetOrigin());
625 bool allowed = (permission_status == PERMISSION_STATUS_GRANTED);
626 if (!task_runner_->RunsTasksOnCurrentThread()) {
627 task_runner_->PostTask(FROM_HERE,
628 base::Bind(permission_status_cb, allowed));
629 } else {
630 permission_status_cb.Run(allowed);
634 void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted(
635 int render_frame_id,
636 int cdm_id,
637 media::MediaKeys::SessionType session_type,
638 media::EmeInitDataType init_data_type,
639 const std::vector<uint8>& init_data,
640 scoped_ptr<media::NewSessionCdmPromise> promise,
641 bool permission_was_allowed) {
642 DCHECK(task_runner_->RunsTasksOnCurrentThread());
644 if (!permission_was_allowed) {
645 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
646 return;
649 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
650 if (!cdm) {
651 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
652 return;
655 cdm->CreateSessionAndGenerateRequest(session_type, init_data_type,
656 init_data, promise.Pass());
659 void BrowserCdmManager::LoadSessionIfPermitted(
660 int render_frame_id,
661 int cdm_id,
662 media::MediaKeys::SessionType session_type,
663 const std::string& session_id,
664 scoped_ptr<media::NewSessionCdmPromise> promise,
665 bool permission_was_allowed) {
666 DCHECK_NE(media::MediaKeys::SessionType::TEMPORARY_SESSION, session_type);
667 DCHECK(task_runner_->RunsTasksOnCurrentThread());
669 if (!permission_was_allowed) {
670 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
671 return;
674 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
675 if (!cdm) {
676 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
677 return;
680 cdm->LoadSession(session_type, session_id, promise.Pass());
683 } // namespace content