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"
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"
33 using media::BrowserCdm
;
34 using media::MediaKeys
;
38 #if defined(OS_ANDROID)
39 // Android only supports 128-bit key IDs.
40 const size_t kAndroidKeyIdBytes
= 128 / 8;
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
...> {
59 CdmPromiseInternal(BrowserCdmManager
* manager
,
64 render_frame_id_(render_frame_id
),
66 promise_id_(promise_id
) {
70 ~CdmPromiseInternal() final
{}
72 // CdmPromiseTemplate<> implementation.
73 void resolve(const T
&... result
) final
;
75 void reject(MediaKeys::Exception exception
,
77 const std::string
& error_message
) final
{
79 manager_
->RejectPromise(render_frame_id_
, cdm_id_
, promise_id_
, exception
,
80 system_code
, error_message
);
84 using media::CdmPromiseTemplate
<T
...>::MarkPromiseSettled
;
86 BrowserCdmManager
* const manager_
;
87 const int render_frame_id_
;
89 const uint32_t promise_id_
;
93 void CdmPromiseInternal
<>::resolve() {
95 manager_
->ResolvePromise(render_frame_id_
, cdm_id_
, promise_id_
);
99 void CdmPromiseInternal
<std::string
>::resolve(const std::string
& session_id
) {
100 MarkPromiseSettled();
101 manager_
->ResolvePromiseWithSession(render_frame_id_
, cdm_id_
, promise_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
{
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()))
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
);
140 void RemoveHostObserverAndDestroy(RenderProcessHost
* host
) {
141 CHECK(g_browser_cdm_manager_map
.Get().erase(host
->GetID()));
142 host
->RemoveObserver(this);
146 const scoped_refptr
<BrowserCdmManager
> browser_cdm_manager_
;
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()) {
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
)) {
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
)
198 return task_runner_
.get();
201 bool BrowserCdmManager::OnMessageReceived(const IPC::Message
& msg
) {
202 DCHECK(task_runner_
->RunsTasksOnCurrentThread());
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()
219 media::BrowserCdm
* BrowserCdmManager::GetCdm(int render_frame_id
,
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(
229 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame
,
230 this, render_frame_id
));
233 RemoveAllCdmForFrame(render_frame_id
);
236 void BrowserCdmManager::ResolvePromise(int render_frame_id
,
238 uint32_t promise_id
) {
239 Send(new CdmMsg_ResolvePromise(render_frame_id
, cdm_id
, promise_id
));
242 void BrowserCdmManager::ResolvePromiseWithSession(
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.");
254 Send(new CdmMsg_ResolvePromiseWithSession(render_frame_id
, cdm_id
, promise_id
,
258 void BrowserCdmManager::RejectPromise(int render_frame_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(
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();
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
,
289 const std::string
& session_id
) {
290 Send(new CdmMsg_SessionClosed(render_frame_id
, cdm_id
, session_id
));
293 void BrowserCdmManager::OnLegacySessionError(
296 const std::string
& session_id
,
297 MediaKeys::Exception exception_code
,
299 const std::string
& error_message
) {
300 Send(new CdmMsg_LegacySessionError(render_frame_id
, cdm_id
, session_id
,
301 exception_code
, system_code
,
305 void BrowserCdmManager::OnSessionKeysChange(int render_frame_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
,
318 void BrowserCdmManager::OnSessionExpirationUpdate(
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
,
327 void BrowserCdmManager::OnInitializeCdm(
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.");
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(
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
);
355 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
359 if (certificate
.empty()) {
360 promise
->reject(MediaKeys::INVALID_ACCESS_ERROR
, 0, "Empty certificate.");
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.");
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.");
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
;
398 #if defined(USE_PROPRIETARY_CODECS)
399 case INIT_DATA_TYPE_CENC
:
400 eme_init_data_type
= media::EmeInitDataType::CENC
;
405 promise
->reject(MediaKeys::INVALID_ACCESS_ERROR
, 0,
406 "Invalid init data type.");
410 BrowserCdm
* cdm
= GetCdm(render_frame_id
, cdm_id
);
412 DLOG(WARNING
) << "No CDM found for: " << render_frame_id
<< ", " << cdm_id
;
413 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
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(
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
);
437 DLOG(WARNING
) << "No CDM found for: " << render_frame_id
<< ", " << cdm_id
;
438 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
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
,
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
);
461 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
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.");
472 if (response
.empty()) {
473 promise
->reject(MediaKeys::INVALID_ACCESS_ERROR
, 0, "Response is empty.");
477 cdm
->UpdateSession(session_id
, response
, promise
.Pass());
480 void BrowserCdmManager::OnCloseSession(int render_frame_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
);
491 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
495 cdm
->CloseSession(session_id
, promise
.Pass());
498 void BrowserCdmManager::OnRemoveSession(int render_frame_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
);
509 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
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
,
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
)));
547 DVLOG(1) << "failed to create CDM.";
548 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "Failed to create CDM.");
552 uint64 id
= GetId(render_frame_id
, cdm_id
);
553 cdm_map_
.add(id
, cdm
.Pass());
554 cdm_security_origin_map_
[id
] = security_origin
;
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());
575 cdm_security_origin_map_
.erase(id
);
578 void BrowserCdmManager::CheckPermissionStatus(
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
));
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(
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);
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
));
630 permission_status_cb
.Run(allowed
);
634 void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted(
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.");
649 BrowserCdm
* cdm
= GetCdm(render_frame_id
, cdm_id
);
651 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
655 cdm
->CreateSessionAndGenerateRequest(session_type
, init_data_type
,
656 init_data
, promise
.Pass());
659 void BrowserCdmManager::LoadSessionIfPermitted(
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.");
674 BrowserCdm
* cdm
= GetCdm(render_frame_id
, cdm_id
);
676 promise
->reject(MediaKeys::INVALID_STATE_ERROR
, 0, "CDM not found.");
680 cdm
->LoadSession(session_type
, session_id
, promise
.Pass());
683 } // namespace content