1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/media/crypto/renderer_cdm_manager.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/stl_util.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/common/media/cdm_messages.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/renderer/media/crypto/proxy_media_keys.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace content {
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Maximum sizes for various EME API parameters. These are checks to prevent
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// unnecessarily large messages from being passed around, and the sizes
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// are somewhat arbitrary as the EME spec doesn't specify any limits.
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kMaxWebSessionIdLength = 512;
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kMaxSessionMessageLength = 10240;  // 10 KB
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RendererCdmManager::RendererCdmManager(RenderFrame* render_frame)
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : RenderFrameObserver(render_frame),
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      next_cdm_id_(kInvalidCdmId + 1) {
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)RendererCdmManager::~RendererCdmManager() {
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(proxy_media_keys_map_.empty())
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "RendererCdmManager is owned by RenderFrameImpl and is destroyed only "
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         "after all ProxyMediaKeys are destroyed and unregistered.";
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RendererCdmManager::OnMessageReceived(const IPC::Message& msg) {
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool handled = true;
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(RendererCdmManager, msg)
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IPC_MESSAGE_HANDLER(CdmMsg_SessionCreated, OnSessionCreated)
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IPC_MESSAGE_HANDLER(CdmMsg_SessionMessage, OnSessionMessage)
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IPC_MESSAGE_HANDLER(CdmMsg_SessionReady, OnSessionReady)
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IPC_MESSAGE_HANDLER(CdmMsg_SessionClosed, OnSessionClosed)
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IPC_MESSAGE_HANDLER(CdmMsg_SessionError, OnSessionError)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_MESSAGE_UNHANDLED(handled = false)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return handled;
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::InitializeCdm(int cdm_id,
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       ProxyMediaKeys* media_keys,
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       const std::string& key_system,
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       const GURL& security_origin) {
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Send(new CdmHostMsg_InitializeCdm(
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      routing_id(), cdm_id, key_system, security_origin));
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::CreateSession(
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int cdm_id,
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    uint32 session_id,
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CdmHostMsg_CreateSession_ContentType content_type,
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<uint8>& init_data) {
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Send(new CdmHostMsg_CreateSession(
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      routing_id(), cdm_id, session_id, content_type, init_data));
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::UpdateSession(int cdm_id,
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       uint32 session_id,
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       const std::vector<uint8>& response) {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Send(
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new CdmHostMsg_UpdateSession(routing_id(), cdm_id, session_id, response));
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::ReleaseSession(int cdm_id, uint32 session_id) {
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Send(new CdmHostMsg_ReleaseSession(routing_id(), cdm_id, session_id));
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::DestroyCdm(int cdm_id) {
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered.";
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Send(new CdmHostMsg_DestroyCdm(routing_id(), cdm_id));
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::OnSessionCreated(int cdm_id,
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          uint32 session_id,
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          const std::string& web_session_id) {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (web_session_id.length() > kMaxWebSessionIdLength) {
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id);
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (media_keys)
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media_keys->OnSessionCreated(session_id, web_session_id);
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::OnSessionMessage(int cdm_id,
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          uint32 session_id,
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          const std::vector<uint8>& message,
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          const GURL& destination_url) {
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (message.size() > kMaxSessionMessageLength) {
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0);
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id);
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (media_keys)
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media_keys->OnSessionMessage(session_id, message, destination_url);
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::OnSessionReady(int cdm_id, uint32 session_id) {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id);
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (media_keys)
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media_keys->OnSessionReady(session_id);
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::OnSessionClosed(int cdm_id, uint32 session_id) {
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id);
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (media_keys)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media_keys->OnSessionClosed(session_id);
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::OnSessionError(int cdm_id,
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        uint32 session_id,
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        media::MediaKeys::KeyError error_code,
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        uint32 system_code) {
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id);
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (media_keys)
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media_keys->OnSessionError(session_id, error_code, system_code);
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int RendererCdmManager::RegisterMediaKeys(ProxyMediaKeys* media_keys) {
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int cdm_id = next_cdm_id_++;
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_NE(cdm_id, kInvalidCdmId);
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!ContainsKey(proxy_media_keys_map_, cdm_id));
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  proxy_media_keys_map_[cdm_id] = media_keys;
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return cdm_id;
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RendererCdmManager::UnregisterMediaKeys(int cdm_id) {
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(ContainsKey(proxy_media_keys_map_, cdm_id));
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  proxy_media_keys_map_.erase(cdm_id);
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ProxyMediaKeys* RendererCdmManager::GetMediaKeys(int cdm_id) {
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::map<int, ProxyMediaKeys*>::iterator iter =
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      proxy_media_keys_map_.find(cdm_id);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (iter != proxy_media_keys_map_.end()) ? iter->second : NULL;
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace content
148