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