Index: content/browser/media/cdm/browser_cdm_manager.cc |
diff --git a/content/browser/media/cdm/browser_cdm_manager.cc b/content/browser/media/cdm/browser_cdm_manager.cc |
deleted file mode 100644 |
index 7202c956f5f60b3bbda82f8ef7af1eb9722f7f1d..0000000000000000000000000000000000000000 |
--- a/content/browser/media/cdm/browser_cdm_manager.cc |
+++ /dev/null |
@@ -1,716 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "content/browser/media/cdm/browser_cdm_manager.h" |
- |
-#include <stddef.h> |
- |
-#include <memory> |
-#include <string> |
-#include <utility> |
- |
-#include "base/bind.h" |
-#include "base/bind_helpers.h" |
-#include "base/lazy_instance.h" |
-#include "base/task_runner.h" |
-#include "build/build_config.h" |
-#include "content/public/browser/browser_context.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "content/public/browser/content_browser_client.h" |
-#include "content/public/browser/permission_manager.h" |
-#include "content/public/browser/permission_type.h" |
-#include "content/public/browser/render_frame_host.h" |
-#include "content/public/browser/render_process_host.h" |
-#include "content/public/browser/render_process_host_observer.h" |
-#include "content/public/browser/storage_partition.h" |
-#include "content/public/browser/web_contents.h" |
-#include "media/base/cdm_config.h" |
-#include "media/base/cdm_factory.h" |
-#include "media/base/cdm_promise.h" |
-#include "media/base/limits.h" |
- |
-#if defined(OS_ANDROID) |
-#include "content/public/browser/android/provision_fetcher_factory.h" |
-#include "content/public/common/renderer_preferences.h" |
-#include "media/base/android/android_cdm_factory.h" |
-#endif |
- |
-namespace content { |
- |
-using media::MediaKeys; |
- |
-namespace { |
- |
-#if defined(OS_ANDROID) |
-// Android only supports 128-bit key IDs. |
-const size_t kAndroidKeyIdBytes = 128 / 8; |
-#endif |
- |
-// The ID used in this class is a concatenation of |render_frame_id| and |
-// |cdm_id|, i.e. (render_frame_id << 32) + cdm_id. |
- |
-uint64_t GetId(int render_frame_id, int cdm_id) { |
- return (static_cast<uint64_t>(render_frame_id) << 32) + |
- static_cast<uint64_t>(cdm_id); |
-} |
- |
-bool IdBelongsToFrame(uint64_t id, int render_frame_id) { |
- return (id >> 32) == static_cast<uint64_t>(render_frame_id); |
-} |
- |
-// media::CdmPromiseTemplate implementation backed by a BrowserCdmManager. |
-template <typename... T> |
-class CdmPromiseInternal : public media::CdmPromiseTemplate<T...> { |
- public: |
- CdmPromiseInternal(const base::WeakPtr<BrowserCdmManager>& manager, |
- int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id) |
- : manager_(manager), |
- render_frame_id_(render_frame_id), |
- cdm_id_(cdm_id), |
- promise_id_(promise_id) { |
- DCHECK(manager_); |
- } |
- |
- ~CdmPromiseInternal() final { |
- if (!IsPromiseSettled()) |
- RejectPromiseOnDestruction(); |
- } |
- |
- // CdmPromiseTemplate<> implementation. |
- void resolve(const T&... result) final; |
- |
- void reject(MediaKeys::Exception exception, |
- uint32_t system_code, |
- const std::string& error_message) final { |
- MarkPromiseSettled(); |
- if (manager_) { |
- manager_->RejectPromise(render_frame_id_, cdm_id_, promise_id_, exception, |
- system_code, error_message); |
- } |
- } |
- |
- private: |
- using media::CdmPromiseTemplate<T...>::IsPromiseSettled; |
- using media::CdmPromiseTemplate<T...>::MarkPromiseSettled; |
- using media::CdmPromiseTemplate<T...>::RejectPromiseOnDestruction; |
- |
- base::WeakPtr<BrowserCdmManager> const manager_; |
- const int render_frame_id_; |
- const int cdm_id_; |
- const uint32_t promise_id_; |
-}; |
- |
-template <> |
-void CdmPromiseInternal<>::resolve() { |
- MarkPromiseSettled(); |
- if (manager_) |
- manager_->ResolvePromise(render_frame_id_, cdm_id_, promise_id_); |
-} |
- |
-template <> |
-void CdmPromiseInternal<std::string>::resolve(const std::string& session_id) { |
- MarkPromiseSettled(); |
- if (manager_) { |
- manager_->ResolvePromiseWithSession(render_frame_id_, cdm_id_, promise_id_, |
- session_id); |
- } |
-} |
- |
-typedef CdmPromiseInternal<> SimplePromise; |
-typedef CdmPromiseInternal<std::string> NewSessionPromise; |
- |
-// Render process ID to BrowserCdmManager map. |
-typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap; |
-base::LazyInstance<BrowserCdmManagerMap>::Leaky g_browser_cdm_manager_map = |
- LAZY_INSTANCE_INITIALIZER; |
- |
-// Keeps the BrowserCdmManager alive, and in the global map, for as long as the |
-// RenderProcessHost is connected to the child process. This class is a |
-// self-owned observer. |
-class BrowserCdmManagerProcessWatcher : public RenderProcessHostObserver { |
- public: |
- BrowserCdmManagerProcessWatcher( |
- int render_process_id, |
- const scoped_refptr<BrowserCdmManager>& manager) |
- : browser_cdm_manager_(manager) { |
- RenderProcessHost::FromID(render_process_id)->AddObserver(this); |
- CHECK(g_browser_cdm_manager_map.Get() |
- .insert(std::make_pair(render_process_id, manager.get())) |
- .second); |
- } |
- |
- // RenderProcessHostObserver: |
- void RenderProcessExited(RenderProcessHost* host, |
- base::TerminationStatus /* status */, |
- int /* exit_code */) override { |
- RemoveHostObserverAndDestroy(host); |
- } |
- |
- void RenderProcessHostDestroyed(RenderProcessHost* host) override { |
- RemoveHostObserverAndDestroy(host); |
- } |
- |
- private: |
- void RemoveHostObserverAndDestroy(RenderProcessHost* host) { |
- CHECK(g_browser_cdm_manager_map.Get().erase(host->GetID())); |
- host->RemoveObserver(this); |
- delete this; |
- } |
- |
- const scoped_refptr<BrowserCdmManager> browser_cdm_manager_; |
-}; |
- |
-} // namespace |
- |
-// static |
-BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) { |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- auto& map = g_browser_cdm_manager_map.Get(); |
- auto iterator = map.find(render_process_id); |
- return (iterator == map.end()) ? nullptr : iterator->second; |
-} |
- |
-BrowserCdmManager::BrowserCdmManager( |
- int render_process_id, |
- const scoped_refptr<base::TaskRunner>& task_runner) |
- : BrowserMessageFilter(CdmMsgStart), |
- render_process_id_(render_process_id), |
- task_runner_(task_runner), |
- weak_ptr_factory_(this) { |
- DVLOG(1) << __FUNCTION__ << ": " << render_process_id_; |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- |
- new BrowserCdmManagerProcessWatcher(render_process_id, this); |
- |
- if (!task_runner_.get()) { |
- task_runner_ = BrowserThread::GetTaskRunnerForThread(BrowserThread::UI); |
- } |
-} |
- |
-BrowserCdmManager::~BrowserCdmManager() { |
- DVLOG(1) << __FUNCTION__ << ": " << render_process_id_; |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
-} |
- |
-// Makes sure BrowserCdmManager is always deleted on the Browser UI thread. |
-void BrowserCdmManager::OnDestruct() const { |
- DVLOG(1) << __FUNCTION__ << ": " << render_process_id_; |
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
- delete this; |
- } else { |
- BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); |
- } |
-} |
- |
-base::TaskRunner* BrowserCdmManager::OverrideTaskRunnerForMessage( |
- const IPC::Message& message) { |
- // Only handles CDM messages. |
- if (IPC_MESSAGE_CLASS(message) != CdmMsgStart) |
- return NULL; |
- |
- return task_runner_.get(); |
-} |
- |
-bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- bool handled = true; |
- IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest, |
- OnCreateSessionAndGenerateRequest) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_LoadSession, OnLoadSession) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_RemoveSession, OnRemoveSession) |
- IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm) |
- IPC_MESSAGE_UNHANDLED(handled = false) |
- IPC_END_MESSAGE_MAP() |
- return handled; |
-} |
- |
-scoped_refptr<MediaKeys> BrowserCdmManager::GetCdm(int render_frame_id, |
- int cdm_id) const { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- const auto& iter = cdm_map_.find(GetId(render_frame_id, cdm_id)); |
- return iter == cdm_map_.end() ? nullptr : iter->second; |
-} |
- |
-void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) { |
- if (!task_runner_->RunsTasksOnCurrentThread()) { |
- task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame, |
- this, render_frame_id)); |
- return; |
- } |
- RemoveAllCdmForFrame(render_frame_id); |
-} |
- |
-void BrowserCdmManager::ResolvePromise(int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id) { |
- Send(new CdmMsg_ResolvePromise(render_frame_id, cdm_id, promise_id)); |
-} |
- |
-void BrowserCdmManager::ResolvePromiseWithSession( |
- int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- const std::string& session_id) { |
- if (session_id.length() > media::limits::kMaxSessionIdLength) { |
- RejectPromise(render_frame_id, cdm_id, promise_id, |
- MediaKeys::INVALID_ACCESS_ERROR, 0, |
- "Session ID is too long."); |
- return; |
- } |
- |
- Send(new CdmMsg_ResolvePromiseWithSession(render_frame_id, cdm_id, promise_id, |
- session_id)); |
-} |
- |
-void BrowserCdmManager::RejectPromise(int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- MediaKeys::Exception exception, |
- uint32_t system_code, |
- const std::string& error_message) { |
- Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception, |
- system_code, error_message)); |
-} |
- |
-media::CdmFactory* BrowserCdmManager::GetCdmFactory() { |
- if (!cdm_factory_) { |
- // Create a new CdmFactory. |
- cdm_factory_ = GetContentClient()->browser()->CreateCdmFactory(); |
- |
-#if defined(OS_ANDROID) |
- if (!cdm_factory_) { |
- // Obtain http request context for the current render process. |
- net::URLRequestContextGetter* context_getter = |
- BrowserContext::GetDefaultStoragePartition( |
- RenderProcessHost::FromID(render_process_id_)-> |
- GetBrowserContext())->GetURLRequestContext(); |
- DCHECK(context_getter); |
- |
- cdm_factory_.reset(new media::AndroidCdmFactory( |
- base::Bind(&CreateProvisionFetcher, context_getter))); |
- } |
-#endif |
- } |
- |
- return cdm_factory_.get(); |
-} |
- |
-void BrowserCdmManager::OnSessionMessage(int render_frame_id, |
- int cdm_id, |
- const std::string& session_id, |
- MediaKeys::MessageType message_type, |
- const std::vector<uint8_t>& message) { |
- Send(new CdmMsg_SessionMessage(render_frame_id, cdm_id, session_id, |
- message_type, message)); |
-} |
- |
-void BrowserCdmManager::OnSessionClosed(int render_frame_id, |
- int cdm_id, |
- const std::string& session_id) { |
- Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id)); |
-} |
- |
-void BrowserCdmManager::OnSessionKeysChange(int render_frame_id, |
- int cdm_id, |
- const std::string& session_id, |
- bool has_additional_usable_key, |
- media::CdmKeysInfo keys_info) { |
- std::vector<media::CdmKeyInformation> key_info_vector; |
- for (auto* key_info : keys_info) |
- key_info_vector.push_back(*key_info); |
- Send(new CdmMsg_SessionKeysChange(render_frame_id, cdm_id, session_id, |
- has_additional_usable_key, |
- key_info_vector)); |
-} |
- |
-void BrowserCdmManager::OnSessionExpirationUpdate( |
- int render_frame_id, |
- int cdm_id, |
- const std::string& session_id, |
- const base::Time& new_expiry_time) { |
- Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id, |
- new_expiry_time)); |
-} |
- |
-// Use a weak pointer here instead of |this| to avoid circular references. |
-#define BROWSER_CDM_MANAGER_CB(func, ...) \ |
- base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ |
- render_frame_id, cdm_id, ##__VA_ARGS__) |
- |
-void BrowserCdmManager::OnInitializeCdm( |
- int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- const CdmHostMsg_InitializeCdm_Params& params) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- DCHECK(!GetCdm(render_frame_id, cdm_id)); |
- |
- std::unique_ptr<SimplePromise> promise(new SimplePromise( |
- weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
- |
- if (params.key_system.size() > media::limits::kMaxKeySystemLength) { |
- NOTREACHED() << "Invalid key system: " << params.key_system; |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Invalid key system."); |
- return; |
- } |
- |
- if (!GetCdmFactory()) { |
- NOTREACHED() << "CDM not supported."; |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "CDM not supported."); |
- return; |
- } |
- |
- // The render process makes sure |allow_distinctive_identifier| and |
- // |allow_persistent_state| are true. See RenderCdmFactory::Create(). |
- // TODO(xhwang): Pass |allow_distinctive_identifier| and |
- // |allow_persistent_state| from the render process. |
- media::CdmConfig cdm_config; |
- cdm_config.allow_distinctive_identifier = true; |
- cdm_config.allow_persistent_state = true; |
- cdm_config.use_hw_secure_codecs = params.use_hw_secure_codecs; |
- |
- GetCdmFactory()->Create( |
- params.key_system, params.security_origin, cdm_config, |
- BROWSER_CDM_MANAGER_CB(OnSessionMessage), |
- BROWSER_CDM_MANAGER_CB(OnSessionClosed), |
- BROWSER_CDM_MANAGER_CB(OnSessionKeysChange), |
- BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate), |
- BROWSER_CDM_MANAGER_CB(OnCdmCreated, params.security_origin, |
- base::Passed(&promise))); |
-} |
- |
-void BrowserCdmManager::OnSetServerCertificate( |
- int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- const std::vector<uint8_t>& certificate) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- std::unique_ptr<SimplePromise> promise(new SimplePromise( |
- weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- if (certificate.empty()) { |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate."); |
- return; |
- } |
- |
- cdm->SetServerCertificate(certificate, std::move(promise)); |
-} |
- |
-void BrowserCdmManager::OnCreateSessionAndGenerateRequest( |
- const CdmHostMsg_CreateSessionAndGenerateRequest_Params& params) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- int render_frame_id = params.render_frame_id; |
- int cdm_id = params.cdm_id; |
- const std::vector<uint8_t>& init_data = params.init_data; |
- std::unique_ptr<NewSessionPromise> promise( |
- new NewSessionPromise(weak_ptr_factory_.GetWeakPtr(), render_frame_id, |
- cdm_id, params.promise_id)); |
- |
- if (init_data.size() > media::limits::kMaxInitDataLength) { |
- LOG(WARNING) << "InitData for ID: " << cdm_id |
- << " too long: " << init_data.size(); |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long."); |
- return; |
- } |
-#if defined(OS_ANDROID) |
- // 'webm' initData is a single key ID. On Android the length is restricted. |
- if (params.init_data_type == INIT_DATA_TYPE_WEBM && |
- init_data.size() != kAndroidKeyIdBytes) { |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, |
- "'webm' initData is not the correct length."); |
- return; |
- } |
-#endif |
- |
- media::EmeInitDataType eme_init_data_type; |
- switch (params.init_data_type) { |
- case INIT_DATA_TYPE_WEBM: |
- eme_init_data_type = media::EmeInitDataType::WEBM; |
- break; |
-#if defined(USE_PROPRIETARY_CODECS) |
- case INIT_DATA_TYPE_CENC: |
- eme_init_data_type = media::EmeInitDataType::CENC; |
- break; |
-#endif |
- default: |
- NOTREACHED(); |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, |
- "Invalid init data type."); |
- return; |
- } |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- CheckPermissionStatus( |
- render_frame_id, cdm_id, |
- base::Bind(&BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted, |
- this, render_frame_id, cdm_id, params.session_type, |
- eme_init_data_type, init_data, base::Passed(&promise))); |
-} |
- |
-void BrowserCdmManager::OnLoadSession( |
- int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- media::MediaKeys::SessionType session_type, |
- const std::string& session_id) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- std::unique_ptr<NewSessionPromise> promise(new NewSessionPromise( |
- weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- CheckPermissionStatus( |
- render_frame_id, cdm_id, |
- base::Bind(&BrowserCdmManager::LoadSessionIfPermitted, |
- this, render_frame_id, cdm_id, session_type, |
- session_id, base::Passed(&promise))); |
-} |
- |
-void BrowserCdmManager::OnUpdateSession(int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- const std::string& session_id, |
- const std::vector<uint8_t>& response) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- std::unique_ptr<SimplePromise> promise(new SimplePromise( |
- weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- if (response.size() > media::limits::kMaxSessionResponseLength) { |
- LOG(WARNING) << "Response for ID " << cdm_id |
- << " is too long: " << response.size(); |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long."); |
- return; |
- } |
- |
- if (response.empty()) { |
- promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty."); |
- return; |
- } |
- |
- cdm->UpdateSession(session_id, response, std::move(promise)); |
-} |
- |
-void BrowserCdmManager::OnCloseSession(int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- const std::string& session_id) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- std::unique_ptr<SimplePromise> promise(new SimplePromise( |
- weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- cdm->CloseSession(session_id, std::move(promise)); |
-} |
- |
-void BrowserCdmManager::OnRemoveSession(int render_frame_id, |
- int cdm_id, |
- uint32_t promise_id, |
- const std::string& session_id) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- std::unique_ptr<SimplePromise> promise(new SimplePromise( |
- weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id)); |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- cdm->RemoveSession(session_id, std::move(promise)); |
-} |
- |
-void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- RemoveCdm(GetId(render_frame_id, cdm_id)); |
-} |
- |
-void BrowserCdmManager::OnCdmCreated( |
- int render_frame_id, |
- int cdm_id, |
- const GURL& security_origin, |
- std::unique_ptr<media::SimpleCdmPromise> promise, |
- const scoped_refptr<media::MediaKeys>& cdm, |
- const std::string& error_message) { |
- if (!cdm) { |
- DVLOG(1) << "Failed to create CDM: " << error_message; |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, error_message); |
- return; |
- } |
- |
- uint64_t id = GetId(render_frame_id, cdm_id); |
- cdm_map_[id] = cdm; |
- cdm_security_origin_map_[id] = security_origin; |
- promise->resolve(); |
-} |
- |
-void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- std::vector<uint64_t> ids_to_remove; |
- for (const auto& entry : cdm_map_) { |
- if (IdBelongsToFrame(entry.first, render_frame_id)) |
- ids_to_remove.push_back(entry.first); |
- } |
- |
- for (const auto& id_to_remove : ids_to_remove) |
- RemoveCdm(id_to_remove); |
-} |
- |
-void BrowserCdmManager::RemoveCdm(uint64_t id) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- cdm_map_.erase(id); |
- cdm_security_origin_map_.erase(id); |
-} |
- |
-void BrowserCdmManager::CheckPermissionStatus( |
- int render_frame_id, |
- int cdm_id, |
- const PermissionStatusCB& permission_status_cb) { |
- // Always called on |task_runner_|, which may not be on the UI thread. |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- GURL security_origin; |
- std::map<uint64_t, GURL>::const_iterator iter = |
- cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); |
- DCHECK(iter != cdm_security_origin_map_.end()); |
- if (iter != cdm_security_origin_map_.end()) |
- security_origin = iter->second; |
- |
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&BrowserCdmManager::CheckPermissionStatusOnUIThread, this, |
- render_frame_id, security_origin, permission_status_cb)); |
- } else { |
- CheckPermissionStatusOnUIThread(render_frame_id, security_origin, |
- permission_status_cb); |
- } |
-} |
- |
-// Note: This function runs on the UI thread, which may be different from |
-// |task_runner_|. Be careful about thread safety! |
-void BrowserCdmManager::CheckPermissionStatusOnUIThread( |
- int render_frame_id, |
- const GURL& security_origin, |
- const base::Callback<void(bool)>& permission_status_cb) { |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- |
- RenderFrameHost* rfh = |
- RenderFrameHost::FromID(render_process_id_, render_frame_id); |
- WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); |
- PermissionManager* permission_manager = |
- web_contents->GetBrowserContext()->GetPermissionManager(); |
- if (!permission_manager) { |
- permission_status_cb.Run(false); |
- return; |
- } |
- |
- blink::mojom::PermissionStatus permission_status = |
- permission_manager->GetPermissionStatus( |
- PermissionType::PROTECTED_MEDIA_IDENTIFIER, security_origin, |
- web_contents->GetLastCommittedURL().GetOrigin()); |
- |
- bool allowed = (permission_status == blink::mojom::PermissionStatus::GRANTED); |
- if (!task_runner_->RunsTasksOnCurrentThread()) { |
- task_runner_->PostTask(FROM_HERE, |
- base::Bind(permission_status_cb, allowed)); |
- } else { |
- permission_status_cb.Run(allowed); |
- } |
-} |
- |
-void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted( |
- int render_frame_id, |
- int cdm_id, |
- media::MediaKeys::SessionType session_type, |
- media::EmeInitDataType init_data_type, |
- const std::vector<uint8_t>& init_data, |
- std::unique_ptr<media::NewSessionCdmPromise> promise, |
- bool permission_was_allowed) { |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- if (!permission_was_allowed) { |
- promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); |
- return; |
- } |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- cdm->CreateSessionAndGenerateRequest(session_type, init_data_type, init_data, |
- std::move(promise)); |
-} |
- |
-void BrowserCdmManager::LoadSessionIfPermitted( |
- int render_frame_id, |
- int cdm_id, |
- media::MediaKeys::SessionType session_type, |
- const std::string& session_id, |
- std::unique_ptr<media::NewSessionCdmPromise> promise, |
- bool permission_was_allowed) { |
- DCHECK_NE(media::MediaKeys::SessionType::TEMPORARY_SESSION, session_type); |
- DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
- |
- if (!permission_was_allowed) { |
- promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied."); |
- return; |
- } |
- |
- scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found."); |
- return; |
- } |
- |
- cdm->LoadSession(session_type, session_id, std::move(promise)); |
-} |
- |
-} // namespace content |