1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/media/cdm/browser_cdm_manager.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/command_line.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/lazy_instance.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/task_runner.h" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/common/media/cdm_messages.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/browser_thread.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/content_browser_client.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/render_frame_host.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/render_process_host.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/browser/web_contents.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/public/common/content_switches.h" 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "media/base/browser_cdm.h" 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "media/base/browser_cdm_factory.h" 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "media/base/media_switches.h" 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace content { 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using media::BrowserCdm; 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using media::MediaKeys; 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Maximum lengths for various EME API parameters. These are checks to 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// prevent unnecessarily large parameters from being passed around, and the 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// lengths are somewhat arbitrary as the EME spec doesn't specify any limits. 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const size_t kMaxInitDataLength = 64 * 1024; // 64 KB 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const size_t kMaxSessionResponseLength = 64 * 1024; // 64 KB 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const size_t kMaxKeySystemLength = 256; 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The ID used in this class is a concatenation of |render_frame_id| and 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |cdm_id|, i.e. (render_frame_id << 32) + cdm_id. 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic uint64 GetId(int render_frame_id, int cdm_id) { 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return (static_cast<uint64>(render_frame_id) << 32) + 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<uint64>(cdm_id); 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic bool IdBelongsToFrame(uint64 id, int render_frame_id) { 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return (id >> 32) == static_cast<uint64>(render_frame_id); 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Render process ID to BrowserCdmManager map. 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap; 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::LazyInstance<BrowserCdmManagerMap> g_browser_cdm_manager_map = 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LAZY_INSTANCE_INITIALIZER; 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) { 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_CURRENTLY_ON(BrowserThread::UI); 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!g_browser_cdm_manager_map.Get().count(render_process_id)) 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return g_browser_cdm_manager_map.Get()[render_process_id]; 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBrowserCdmManager::BrowserCdmManager( 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int render_process_id, 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<base::TaskRunner>& task_runner) 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : BrowserMessageFilter(CdmMsgStart), 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_process_id_(render_process_id), 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner_(task_runner) { 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_CURRENTLY_ON(BrowserThread::UI); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!task_runner_) { 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner_ = 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This may overwrite an existing entry of |render_process_id| if the 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // previous process crashed and didn't cleanup its child frames. For example, 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // see FrameTreeBrowserTest.FrameTreeAfterCrash test. 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_browser_cdm_manager_map.Get()[render_process_id] = this; 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)BrowserCdmManager::~BrowserCdmManager() { 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_CURRENTLY_ON(BrowserThread::UI); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(g_browser_cdm_manager_map.Get().count(render_process_id_)); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_browser_cdm_manager_map.Get().erase(render_process_id_); 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Makes sure BrowserCdmManager is always deleted on the Browser UI thread. 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnDestruct() const { 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delete this; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::TaskRunner* BrowserCdmManager::OverrideTaskRunnerForMessage( 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const IPC::Message& message) { 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Only handles CDM messages. 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (IPC_MESSAGE_CLASS(message) != CdmMsgStart) 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return task_runner_.get(); 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) { 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(task_runner_->RunsTasksOnCurrentThread()); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool handled = true; 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg) 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm) 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSession, OnCreateSession) 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession) 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(CdmHostMsg_ReleaseSession, OnReleaseSession) 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm) 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_UNHANDLED(handled = false) 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_END_MESSAGE_MAP() 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return handled; 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccimedia::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(task_runner_->RunsTasksOnCurrentThread()); 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return cdm_map_.get(GetId(render_frame_id, cdm_id)); 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::RenderFrameDeleted(int render_frame_id) { 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(task_runner_->RunsTasksOnCurrentThread()); 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint64> ids_to_remove; 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (CdmMap::iterator it = cdm_map_.begin(); it != cdm_map_.end(); ++it) { 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (IdBelongsToFrame(it->first, render_frame_id)) 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ids_to_remove.push_back(it->first); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < ids_to_remove.size(); ++i) 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RemoveCdm(ids_to_remove[i]); 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnSessionCreated(int render_frame_id, 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32 session_id, 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& web_session_id) { 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Send(new CdmMsg_SessionCreated( 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_id, cdm_id, session_id, web_session_id)); 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnSessionMessage(int render_frame_id, 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32 session_id, 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<uint8>& message, 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& destination_url) { 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GURL verified_gurl = destination_url; 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DLOG(WARNING) << "SessionMessage destination_url is invalid : " 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << destination_url.possibly_invalid_spec(); 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) verified_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Send(new CdmMsg_SessionMessage( 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_id, cdm_id, session_id, message, verified_gurl)); 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnSessionReady(int render_frame_id, 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32 session_id) { 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Send(new CdmMsg_SessionReady(render_frame_id, cdm_id, session_id)); 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnSessionClosed(int render_frame_id, 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32 session_id) { 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id)); 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnSessionError(int render_frame_id, 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32 session_id, 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MediaKeys::KeyError error_code, 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32 system_code) { 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Send(new CdmMsg_SessionError( 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_id, cdm_id, session_id, error_code, system_code)); 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnInitializeCdm(int render_frame_id, 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& key_system, 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& security_origin) { 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (key_system.size() > kMaxKeySystemLength) { 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This failure will be discovered and reported by OnCreateSession() 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // as GetCdm() will return null. 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED() << "Invalid key system: " << key_system; 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddCdm(render_frame_id, cdm_id, key_system, security_origin); 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BrowserCdmManager::OnCreateSession( 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int render_frame_id, 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int cdm_id, 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32 session_id, 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CdmHostMsg_CreateSession_ContentType content_type, 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<uint8>& init_data) { 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (init_data.size() > kMaxInitDataLength) { 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(WARNING) << "InitData for ID: " << cdm_id 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << " too long: " << init_data.size(); 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Convert the session content type into a MIME type. "audio" and "video" 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // don't matter, so using "video" for the MIME type. 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ref: 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-createsession 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string mime_type; 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (content_type) { 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case CREATE_SESSION_TYPE_WEBM: 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mime_type = "video/webm"; 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case CREATE_SESSION_TYPE_MP4: 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mime_type = "video/mp4"; 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_ANDROID) 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (CommandLine::ForCurrentProcess() 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) { 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CreateSessionIfPermitted( 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_id, cdm_id, session_id, mime_type, init_data, true); 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!cdm) { 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::map<uint64, GURL>::const_iterator iter = 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (iter == cdm_security_origin_map_.end()) { 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NOTREACHED(); 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL security_origin = iter->second; 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenderFrameHost* rfh = 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RenderFrameHost::FromID(render_process_id_, render_frame_id); 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(web_contents); 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Closure cancel_callback; 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetContentClient()->browser()->RequestProtectedMediaIdentifierPermission( 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_contents, 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci security_origin, 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Bind(&BrowserCdmManager::CreateSessionIfPermitted, 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_id, cdm_id, session_id, 2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mime_type, init_data), 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &cancel_callback); 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (cancel_callback.is_null()) 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_cancel_permission_map_[GetId(render_frame_id, cdm_id)] = cancel_callback; 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BrowserCdmManager::OnUpdateSession( 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int render_frame_id, 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int cdm_id, 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32 session_id, 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<uint8>& response) { 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!cdm) { 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (response.size() > kMaxSessionResponseLength) { 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG(WARNING) << "Response for ID " << cdm_id 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << " is too long: " << response.size(); 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cdm->UpdateSession(session_id, &response[0], response.size()); 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnReleaseSession(int render_frame_id, 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32 session_id) { 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!cdm) { 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cdm->ReleaseSession(session_id); 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RemoveCdm(GetId(render_frame_id, cdm_id)); 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::SendSessionError(int render_frame_id, 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint32 session_id) { 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnSessionError( 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_frame_id, cdm_id, session_id, MediaKeys::kUnknownError, 0); 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define BROWSER_CDM_MANAGER_CB(func) \ 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&BrowserCdmManager::func, this, render_frame_id, cdm_id) 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::AddCdm(int render_frame_id, 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int cdm_id, 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& key_system, 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const GURL& security_origin) { 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(task_runner_->RunsTasksOnCurrentThread()); 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!GetCdm(render_frame_id, cdm_id)); 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<BrowserCdm> cdm( 3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media::CreateBrowserCdm(key_system, 3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BROWSER_CDM_MANAGER_CB(OnSessionCreated), 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BROWSER_CDM_MANAGER_CB(OnSessionMessage), 3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BROWSER_CDM_MANAGER_CB(OnSessionReady), 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BROWSER_CDM_MANAGER_CB(OnSessionClosed), 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BROWSER_CDM_MANAGER_CB(OnSessionError))); 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!cdm) { 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This failure will be discovered and reported by OnCreateSession() 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // as GetCdm() will return null. 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DVLOG(1) << "failed to create CDM."; 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint64 id = GetId(render_frame_id, cdm_id); 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_map_.add(id, cdm.Pass()); 3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_security_origin_map_[id] = security_origin; 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserCdmManager::RemoveCdm(uint64 id) { 3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(task_runner_->RunsTasksOnCurrentThread()); 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_map_.erase(id); 3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_security_origin_map_.erase(id); 3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (cdm_cancel_permission_map_.count(id)) { 3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_cancel_permission_map_[id].Run(); 3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_cancel_permission_map_.erase(id); 3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BrowserCdmManager::CreateSessionIfPermitted( 3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int render_frame_id, 360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int cdm_id, 361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32 session_id, 362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& content_type, 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<uint8>& init_data, 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool permitted) { 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id)); 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!permitted) { 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!cdm) { 3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendSessionError(render_frame_id, cdm_id, session_id); 375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This could fail, in which case a SessionError will be fired. 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cdm->CreateSession(session_id, content_type, &init_data[0], init_data.size()); 380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace content 383