Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / content / browser / media / cdm / browser_cdm_manager.cc
blobeefceba28b97d1a73cd31834fb3b34d231a554ae
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(const base::WeakPtr<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 if (manager_) {
80 manager_->RejectPromise(render_frame_id_, cdm_id_, promise_id_, exception,
81 system_code, error_message);
85 private:
86 using media::CdmPromiseTemplate<T...>::MarkPromiseSettled;
88 base::WeakPtr<BrowserCdmManager> const manager_;
89 const int render_frame_id_;
90 const int cdm_id_;
91 const uint32_t promise_id_;
94 template <>
95 void CdmPromiseInternal<>::resolve() {
96 MarkPromiseSettled();
97 if (manager_)
98 manager_->ResolvePromise(render_frame_id_, cdm_id_, promise_id_);
101 template <>
102 void CdmPromiseInternal<std::string>::resolve(const std::string& session_id) {
103 MarkPromiseSettled();
104 if (manager_) {
105 manager_->ResolvePromiseWithSession(render_frame_id_, cdm_id_, promise_id_,
106 session_id);
110 typedef CdmPromiseInternal<> SimplePromise;
111 typedef CdmPromiseInternal<std::string> NewSessionPromise;
113 // Render process ID to BrowserCdmManager map.
114 typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap;
115 base::LazyInstance<BrowserCdmManagerMap>::Leaky g_browser_cdm_manager_map =
116 LAZY_INSTANCE_INITIALIZER;
118 // Keeps the BrowserCdmManager alive, and in the global map, for as long as the
119 // RenderProcessHost is connected to the child process. This class is a
120 // self-owned observer.
121 class BrowserCdmManagerProcessWatcher : public RenderProcessHostObserver {
122 public:
123 BrowserCdmManagerProcessWatcher(
124 int render_process_id,
125 const scoped_refptr<BrowserCdmManager>& manager)
126 : browser_cdm_manager_(manager) {
127 RenderProcessHost::FromID(render_process_id)->AddObserver(this);
128 CHECK(g_browser_cdm_manager_map.Get()
129 .insert(std::make_pair(render_process_id, manager.get()))
130 .second);
133 // RenderProcessHostObserver:
134 void RenderProcessExited(RenderProcessHost* host,
135 base::TerminationStatus /* status */,
136 int /* exit_code */) override {
137 RemoveHostObserverAndDestroy(host);
140 void RenderProcessHostDestroyed(RenderProcessHost* host) override {
141 RemoveHostObserverAndDestroy(host);
144 private:
145 void RemoveHostObserverAndDestroy(RenderProcessHost* host) {
146 CHECK(g_browser_cdm_manager_map.Get().erase(host->GetID()));
147 host->RemoveObserver(this);
148 delete this;
151 const scoped_refptr<BrowserCdmManager> browser_cdm_manager_;
154 } // namespace
156 // static
157 BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) {
158 DCHECK_CURRENTLY_ON(BrowserThread::UI);
159 auto& map = g_browser_cdm_manager_map.Get();
160 auto iterator = map.find(render_process_id);
161 return (iterator == map.end()) ? nullptr : iterator->second;
164 BrowserCdmManager::BrowserCdmManager(
165 int render_process_id,
166 const scoped_refptr<base::TaskRunner>& task_runner)
167 : BrowserMessageFilter(CdmMsgStart),
168 render_process_id_(render_process_id),
169 task_runner_(task_runner),
170 weak_ptr_factory_(this) {
171 DVLOG(1) << __FUNCTION__ << ": " << render_process_id_;
172 DCHECK_CURRENTLY_ON(BrowserThread::UI);
174 new BrowserCdmManagerProcessWatcher(render_process_id, this);
176 if (!task_runner_.get()) {
177 task_runner_ =
178 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
182 BrowserCdmManager::~BrowserCdmManager() {
183 DVLOG(1) << __FUNCTION__ << ": " << render_process_id_;
184 DCHECK_CURRENTLY_ON(BrowserThread::UI);
187 // Makes sure BrowserCdmManager is always deleted on the Browser UI thread.
188 void BrowserCdmManager::OnDestruct() const {
189 DVLOG(1) << __FUNCTION__ << ": " << render_process_id_;
190 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
191 delete this;
192 } else {
193 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
197 base::TaskRunner* BrowserCdmManager::OverrideTaskRunnerForMessage(
198 const IPC::Message& message) {
199 // Only handles CDM messages.
200 if (IPC_MESSAGE_CLASS(message) != CdmMsgStart)
201 return NULL;
203 return task_runner_.get();
206 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) {
207 DCHECK(task_runner_->RunsTasksOnCurrentThread());
208 bool handled = true;
209 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg)
210 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm)
211 IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate)
212 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest,
213 OnCreateSessionAndGenerateRequest)
214 IPC_MESSAGE_HANDLER(CdmHostMsg_LoadSession, OnLoadSession)
215 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession)
216 IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession)
217 IPC_MESSAGE_HANDLER(CdmHostMsg_RemoveSession, OnRemoveSession)
218 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm)
219 IPC_MESSAGE_UNHANDLED(handled = false)
220 IPC_END_MESSAGE_MAP()
221 return handled;
224 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id,
225 int cdm_id) const {
226 DCHECK(task_runner_->RunsTasksOnCurrentThread());
227 return cdm_map_.get(GetId(render_frame_id, cdm_id));
230 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) {
231 if (!task_runner_->RunsTasksOnCurrentThread()) {
232 task_runner_->PostTask(
233 FROM_HERE,
234 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame,
235 this, render_frame_id));
236 return;
238 RemoveAllCdmForFrame(render_frame_id);
241 void BrowserCdmManager::ResolvePromise(int render_frame_id,
242 int cdm_id,
243 uint32_t promise_id) {
244 Send(new CdmMsg_ResolvePromise(render_frame_id, cdm_id, promise_id));
247 void BrowserCdmManager::ResolvePromiseWithSession(
248 int render_frame_id,
249 int cdm_id,
250 uint32_t promise_id,
251 const std::string& session_id) {
252 if (session_id.length() > media::limits::kMaxSessionIdLength) {
253 RejectPromise(render_frame_id, cdm_id, promise_id,
254 MediaKeys::INVALID_ACCESS_ERROR, 0,
255 "Session ID is too long.");
256 return;
259 Send(new CdmMsg_ResolvePromiseWithSession(render_frame_id, cdm_id, promise_id,
260 session_id));
263 void BrowserCdmManager::RejectPromise(int render_frame_id,
264 int cdm_id,
265 uint32_t promise_id,
266 media::MediaKeys::Exception exception,
267 uint32_t system_code,
268 const std::string& error_message) {
269 Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception,
270 system_code, error_message));
273 void BrowserCdmManager::OnSessionMessage(
274 int render_frame_id,
275 int cdm_id,
276 const std::string& session_id,
277 media::MediaKeys::MessageType message_type,
278 const std::vector<uint8>& message,
279 const GURL& legacy_destination_url) {
280 GURL verified_gurl = legacy_destination_url;
281 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
282 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : "
283 << legacy_destination_url.possibly_invalid_spec();
284 verified_gurl =
285 GURL::EmptyGURL(); // Replace invalid legacy_destination_url.
288 Send(new CdmMsg_SessionMessage(render_frame_id, cdm_id, session_id,
289 message_type, message, verified_gurl));
292 void BrowserCdmManager::OnSessionClosed(int render_frame_id,
293 int cdm_id,
294 const std::string& session_id) {
295 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id));
298 void BrowserCdmManager::OnLegacySessionError(
299 int render_frame_id,
300 int cdm_id,
301 const std::string& session_id,
302 MediaKeys::Exception exception_code,
303 uint32 system_code,
304 const std::string& error_message) {
305 Send(new CdmMsg_LegacySessionError(render_frame_id, cdm_id, session_id,
306 exception_code, system_code,
307 error_message));
310 void BrowserCdmManager::OnSessionKeysChange(int render_frame_id,
311 int cdm_id,
312 const std::string& session_id,
313 bool has_additional_usable_key,
314 media::CdmKeysInfo keys_info) {
315 std::vector<media::CdmKeyInformation> key_info_vector;
316 for (const auto& key_info : keys_info)
317 key_info_vector.push_back(*key_info);
318 Send(new CdmMsg_SessionKeysChange(render_frame_id, cdm_id, session_id,
319 has_additional_usable_key,
320 key_info_vector));
323 void BrowserCdmManager::OnSessionExpirationUpdate(
324 int render_frame_id,
325 int cdm_id,
326 const std::string& session_id,
327 const base::Time& new_expiry_time) {
328 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id,
329 new_expiry_time));
332 void BrowserCdmManager::OnInitializeCdm(
333 int render_frame_id,
334 int cdm_id,
335 uint32_t promise_id,
336 const CdmHostMsg_InitializeCdm_Params& params) {
337 if (params.key_system.size() > media::limits::kMaxKeySystemLength) {
338 NOTREACHED() << "Invalid key system: " << params.key_system;
339 RejectPromise(render_frame_id, cdm_id, promise_id,
340 MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system.");
341 return;
344 AddCdm(render_frame_id, cdm_id, promise_id, params.key_system,
345 params.security_origin, params.use_hw_secure_codecs);
348 void BrowserCdmManager::OnSetServerCertificate(
349 int render_frame_id,
350 int cdm_id,
351 uint32_t promise_id,
352 const std::vector<uint8_t>& certificate) {
353 DCHECK(task_runner_->RunsTasksOnCurrentThread());
355 scoped_ptr<SimplePromise> promise(new SimplePromise(
356 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
358 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
359 if (!cdm) {
360 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
361 return;
364 if (certificate.empty()) {
365 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate.");
366 return;
369 cdm->SetServerCertificate(certificate, promise.Pass());
372 void BrowserCdmManager::OnCreateSessionAndGenerateRequest(
373 const CdmHostMsg_CreateSessionAndGenerateRequest_Params& params) {
374 DCHECK(task_runner_->RunsTasksOnCurrentThread());
376 int render_frame_id = params.render_frame_id;
377 int cdm_id = params.cdm_id;
378 const std::vector<uint8>& init_data = params.init_data;
379 scoped_ptr<NewSessionPromise> promise(
380 new NewSessionPromise(weak_ptr_factory_.GetWeakPtr(),
381 render_frame_id, cdm_id, params.promise_id));
383 if (init_data.size() > media::limits::kMaxInitDataLength) {
384 LOG(WARNING) << "InitData for ID: " << cdm_id
385 << " too long: " << init_data.size();
386 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long.");
387 return;
389 #if defined(OS_ANDROID)
390 // 'webm' initData is a single key ID. On Android the length is restricted.
391 if (params.init_data_type == INIT_DATA_TYPE_WEBM &&
392 init_data.size() != kAndroidKeyIdBytes) {
393 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
394 "'webm' initData is not the correct length.");
395 return;
397 #endif
399 media::EmeInitDataType eme_init_data_type;
400 switch (params.init_data_type) {
401 case INIT_DATA_TYPE_WEBM:
402 eme_init_data_type = media::EmeInitDataType::WEBM;
403 break;
404 #if defined(USE_PROPRIETARY_CODECS)
405 case INIT_DATA_TYPE_CENC:
406 eme_init_data_type = media::EmeInitDataType::CENC;
407 break;
408 #endif
409 default:
410 NOTREACHED();
411 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
412 "Invalid init data type.");
413 return;
416 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
417 if (!cdm) {
418 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
419 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
420 return;
423 CheckPermissionStatus(
424 render_frame_id, cdm_id,
425 base::Bind(&BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted,
426 this, render_frame_id, cdm_id, params.session_type,
427 eme_init_data_type, init_data, base::Passed(&promise)));
430 void BrowserCdmManager::OnLoadSession(
431 int render_frame_id,
432 int cdm_id,
433 uint32_t promise_id,
434 media::MediaKeys::SessionType session_type,
435 const std::string& session_id) {
436 DCHECK(task_runner_->RunsTasksOnCurrentThread());
438 scoped_ptr<NewSessionPromise> promise(new NewSessionPromise(
439 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
441 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
442 if (!cdm) {
443 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
444 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
445 return;
448 CheckPermissionStatus(
449 render_frame_id, cdm_id,
450 base::Bind(&BrowserCdmManager::LoadSessionIfPermitted,
451 this, render_frame_id, cdm_id, session_type,
452 session_id, base::Passed(&promise)));
455 void BrowserCdmManager::OnUpdateSession(int render_frame_id,
456 int cdm_id,
457 uint32_t promise_id,
458 const std::string& session_id,
459 const std::vector<uint8>& response) {
460 DCHECK(task_runner_->RunsTasksOnCurrentThread());
462 scoped_ptr<SimplePromise> promise(new SimplePromise(
463 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
465 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
466 if (!cdm) {
467 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
468 return;
471 if (response.size() > media::limits::kMaxSessionResponseLength) {
472 LOG(WARNING) << "Response for ID " << cdm_id
473 << " is too long: " << response.size();
474 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long.");
475 return;
478 if (response.empty()) {
479 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty.");
480 return;
483 cdm->UpdateSession(session_id, response, promise.Pass());
486 void BrowserCdmManager::OnCloseSession(int render_frame_id,
487 int cdm_id,
488 uint32_t promise_id,
489 const std::string& session_id) {
490 DCHECK(task_runner_->RunsTasksOnCurrentThread());
492 scoped_ptr<SimplePromise> promise(new SimplePromise(
493 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
495 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
496 if (!cdm) {
497 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
498 return;
501 cdm->CloseSession(session_id, promise.Pass());
504 void BrowserCdmManager::OnRemoveSession(int render_frame_id,
505 int cdm_id,
506 uint32_t promise_id,
507 const std::string& session_id) {
508 DCHECK(task_runner_->RunsTasksOnCurrentThread());
510 scoped_ptr<SimplePromise> promise(new SimplePromise(
511 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
513 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
514 if (!cdm) {
515 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
516 return;
519 cdm->RemoveSession(session_id, promise.Pass());
522 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) {
523 DCHECK(task_runner_->RunsTasksOnCurrentThread());
524 RemoveCdm(GetId(render_frame_id, cdm_id));
527 // Use a weak pointer here instead of |this| to avoid circular references.
528 #define BROWSER_CDM_MANAGER_CB(func) \
529 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \
530 render_frame_id, cdm_id)
532 void BrowserCdmManager::AddCdm(int render_frame_id,
533 int cdm_id,
534 uint32_t promise_id,
535 const std::string& key_system,
536 const GURL& security_origin,
537 bool use_hw_secure_codecs) {
538 DCHECK(task_runner_->RunsTasksOnCurrentThread());
539 DCHECK(!GetCdm(render_frame_id, cdm_id));
541 scoped_ptr<SimplePromise> promise(new SimplePromise(
542 weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
544 scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
545 key_system, use_hw_secure_codecs,
546 BROWSER_CDM_MANAGER_CB(OnSessionMessage),
547 BROWSER_CDM_MANAGER_CB(OnSessionClosed),
548 BROWSER_CDM_MANAGER_CB(OnLegacySessionError),
549 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange),
550 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate)));
552 if (!cdm) {
553 DVLOG(1) << "failed to create CDM.";
554 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "Failed to create CDM.");
555 return;
558 uint64 id = GetId(render_frame_id, cdm_id);
559 cdm_map_.add(id, cdm.Pass());
560 cdm_security_origin_map_[id] = security_origin;
561 promise->resolve();
564 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) {
565 DCHECK(task_runner_->RunsTasksOnCurrentThread());
567 std::vector<uint64> ids_to_remove;
568 for (CdmMap::iterator it = cdm_map_.begin(); it != cdm_map_.end(); ++it) {
569 if (IdBelongsToFrame(it->first, render_frame_id))
570 ids_to_remove.push_back(it->first);
573 for (size_t i = 0; i < ids_to_remove.size(); ++i)
574 RemoveCdm(ids_to_remove[i]);
577 void BrowserCdmManager::RemoveCdm(uint64 id) {
578 DCHECK(task_runner_->RunsTasksOnCurrentThread());
580 cdm_map_.erase(id);
581 cdm_security_origin_map_.erase(id);
584 void BrowserCdmManager::CheckPermissionStatus(
585 int render_frame_id,
586 int cdm_id,
587 const PermissionStatusCB& permission_status_cb) {
588 // Always called on |task_runner_|, which may not be on the UI thread.
589 DCHECK(task_runner_->RunsTasksOnCurrentThread());
591 GURL security_origin;
592 std::map<uint64, GURL>::const_iterator iter =
593 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id));
594 DCHECK(iter != cdm_security_origin_map_.end());
595 if (iter != cdm_security_origin_map_.end())
596 security_origin = iter->second;
598 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
599 BrowserThread::PostTask(
600 BrowserThread::UI, FROM_HERE,
601 base::Bind(&BrowserCdmManager::CheckPermissionStatusOnUIThread, this,
602 render_frame_id, security_origin, permission_status_cb));
603 } else {
604 CheckPermissionStatusOnUIThread(render_frame_id, security_origin,
605 permission_status_cb);
609 // Note: This function runs on the UI thread, which may be different from
610 // |task_runner_|. Be careful about thread safety!
611 void BrowserCdmManager::CheckPermissionStatusOnUIThread(
612 int render_frame_id,
613 const GURL& security_origin,
614 const base::Callback<void(bool)>& permission_status_cb) {
615 DCHECK_CURRENTLY_ON(BrowserThread::UI);
617 RenderFrameHost* rfh =
618 RenderFrameHost::FromID(render_process_id_, render_frame_id);
619 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
620 PermissionManager* permission_manager =
621 web_contents->GetBrowserContext()->GetPermissionManager();
622 if (!permission_manager) {
623 permission_status_cb.Run(false);
624 return;
627 PermissionStatus permission_status = permission_manager->GetPermissionStatus(
628 PermissionType::PROTECTED_MEDIA_IDENTIFIER, security_origin,
629 web_contents->GetLastCommittedURL().GetOrigin());
631 bool allowed = (permission_status == PERMISSION_STATUS_GRANTED);
632 if (!task_runner_->RunsTasksOnCurrentThread()) {
633 task_runner_->PostTask(FROM_HERE,
634 base::Bind(permission_status_cb, allowed));
635 } else {
636 permission_status_cb.Run(allowed);
640 void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted(
641 int render_frame_id,
642 int cdm_id,
643 media::MediaKeys::SessionType session_type,
644 media::EmeInitDataType init_data_type,
645 const std::vector<uint8>& init_data,
646 scoped_ptr<media::NewSessionCdmPromise> promise,
647 bool permission_was_allowed) {
648 DCHECK(task_runner_->RunsTasksOnCurrentThread());
650 if (!permission_was_allowed) {
651 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
652 return;
655 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
656 if (!cdm) {
657 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
658 return;
661 cdm->CreateSessionAndGenerateRequest(session_type, init_data_type,
662 init_data, promise.Pass());
665 void BrowserCdmManager::LoadSessionIfPermitted(
666 int render_frame_id,
667 int cdm_id,
668 media::MediaKeys::SessionType session_type,
669 const std::string& session_id,
670 scoped_ptr<media::NewSessionCdmPromise> promise,
671 bool permission_was_allowed) {
672 DCHECK_NE(media::MediaKeys::SessionType::TEMPORARY_SESSION, session_type);
673 DCHECK(task_runner_->RunsTasksOnCurrentThread());
675 if (!permission_was_allowed) {
676 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
677 return;
680 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
681 if (!cdm) {
682 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
683 return;
686 cdm->LoadSession(session_type, session_id, promise.Pass());
689 } // namespace content