OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/crypto/renderer_cdm_manager.h" | 5 #include "content/renderer/media/crypto/renderer_cdm_manager.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "content/common/media/cdm_messages.h" | 8 #include "content/common/media/cdm_messages.h" |
9 #include "content/renderer/media/crypto/proxy_media_keys.h" | 9 #include "content/renderer/media/crypto/proxy_media_keys.h" |
10 #include "media/base/cdm_context.h" | 10 #include "media/base/cdm_context.h" |
| 11 #include "media/base/limits.h" |
11 | 12 |
12 namespace content { | 13 namespace content { |
13 | 14 |
| 15 using media::MediaKeys; |
| 16 |
14 // Maximum sizes for various EME API parameters. These are checks to prevent | 17 // Maximum sizes for various EME API parameters. These are checks to prevent |
15 // unnecessarily large messages from being passed around, and the sizes | 18 // unnecessarily large messages from being passed around, and the sizes |
16 // are somewhat arbitrary as the EME spec doesn't specify any limits. | 19 // are somewhat arbitrary as the EME spec doesn't specify any limits. |
17 const size_t kMaxWebSessionIdLength = 512; | |
18 const size_t kMaxSessionMessageLength = 10240; // 10 KB | 20 const size_t kMaxSessionMessageLength = 10240; // 10 KB |
19 | 21 |
20 RendererCdmManager::RendererCdmManager(RenderFrame* render_frame) | 22 RendererCdmManager::RendererCdmManager(RenderFrame* render_frame) |
21 : RenderFrameObserver(render_frame), | 23 : RenderFrameObserver(render_frame), |
22 next_cdm_id_(media::CdmContext::kInvalidCdmId + 1) { | 24 next_cdm_id_(media::CdmContext::kInvalidCdmId + 1) { |
23 } | 25 } |
24 | 26 |
25 RendererCdmManager::~RendererCdmManager() { | 27 RendererCdmManager::~RendererCdmManager() { |
26 DCHECK(proxy_media_keys_map_.empty()) | 28 DCHECK(proxy_media_keys_map_.empty()) |
27 << "RendererCdmManager is owned by RenderFrameImpl and is destroyed only " | 29 << "RendererCdmManager is owned by RenderFrameImpl and is destroyed only " |
28 "after all ProxyMediaKeys are destroyed and unregistered."; | 30 "after all ProxyMediaKeys are destroyed and unregistered."; |
29 } | 31 } |
30 | 32 |
31 bool RendererCdmManager::OnMessageReceived(const IPC::Message& msg) { | 33 bool RendererCdmManager::OnMessageReceived(const IPC::Message& msg) { |
32 bool handled = true; | 34 bool handled = true; |
33 IPC_BEGIN_MESSAGE_MAP(RendererCdmManager, msg) | 35 IPC_BEGIN_MESSAGE_MAP(RendererCdmManager, msg) |
34 IPC_MESSAGE_HANDLER(CdmMsg_SessionCreated, OnSessionCreated) | |
35 IPC_MESSAGE_HANDLER(CdmMsg_SessionMessage, OnSessionMessage) | 36 IPC_MESSAGE_HANDLER(CdmMsg_SessionMessage, OnSessionMessage) |
36 IPC_MESSAGE_HANDLER(CdmMsg_SessionReady, OnSessionReady) | |
37 IPC_MESSAGE_HANDLER(CdmMsg_SessionClosed, OnSessionClosed) | 37 IPC_MESSAGE_HANDLER(CdmMsg_SessionClosed, OnSessionClosed) |
38 IPC_MESSAGE_HANDLER(CdmMsg_SessionError, OnSessionError) | 38 IPC_MESSAGE_HANDLER(CdmMsg_LegacySessionError, OnLegacySessionError) |
| 39 IPC_MESSAGE_HANDLER(CdmMsg_SessionKeysChange, OnSessionKeysChange) |
| 40 IPC_MESSAGE_HANDLER(CdmMsg_SessionExpirationUpdate, |
| 41 OnSessionExpirationUpdate) |
| 42 IPC_MESSAGE_HANDLER(CdmMsg_ResolvePromise, OnPromiseResolved) |
| 43 IPC_MESSAGE_HANDLER(CdmMsg_ResolvePromiseWithSession, |
| 44 OnPromiseResolvedWithSession) |
| 45 IPC_MESSAGE_HANDLER(CdmMsg_RejectPromise, OnPromiseRejected) |
39 IPC_MESSAGE_UNHANDLED(handled = false) | 46 IPC_MESSAGE_UNHANDLED(handled = false) |
40 IPC_END_MESSAGE_MAP() | 47 IPC_END_MESSAGE_MAP() |
41 return handled; | 48 return handled; |
42 } | 49 } |
43 | 50 |
44 void RendererCdmManager::InitializeCdm(int cdm_id, | 51 void RendererCdmManager::InitializeCdm(int cdm_id, |
45 ProxyMediaKeys* media_keys, | 52 ProxyMediaKeys* media_keys, |
46 const std::string& key_system, | 53 const std::string& key_system, |
47 const GURL& security_origin) { | 54 const GURL& security_origin) { |
48 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; | 55 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; |
49 Send(new CdmHostMsg_InitializeCdm( | 56 Send(new CdmHostMsg_InitializeCdm( |
50 routing_id(), cdm_id, key_system, security_origin)); | 57 routing_id(), cdm_id, key_system, security_origin)); |
51 } | 58 } |
52 | 59 |
53 void RendererCdmManager::CreateSession( | 60 void RendererCdmManager::SetServerCertificate( |
54 int cdm_id, | 61 int cdm_id, |
55 uint32 session_id, | 62 uint32_t promise_id, |
56 CdmHostMsg_CreateSession_ContentType content_type, | 63 const std::vector<uint8_t>& certificate) { |
57 const std::vector<uint8>& init_data) { | |
58 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; | 64 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; |
59 Send(new CdmHostMsg_CreateSession( | 65 Send(new CdmHostMsg_SetServerCertificate(routing_id(), cdm_id, promise_id, |
60 routing_id(), cdm_id, session_id, content_type, init_data)); | 66 certificate)); |
| 67 } |
| 68 |
| 69 void RendererCdmManager::CreateSessionAndGenerateRequest( |
| 70 int cdm_id, |
| 71 uint32_t promise_id, |
| 72 CdmHostMsg_CreateSession_InitDataType init_data_type, |
| 73 const std::vector<uint8_t>& init_data) { |
| 74 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; |
| 75 Send(new CdmHostMsg_CreateSessionAndGenerateRequest( |
| 76 routing_id(), cdm_id, promise_id, init_data_type, init_data)); |
61 } | 77 } |
62 | 78 |
63 void RendererCdmManager::UpdateSession(int cdm_id, | 79 void RendererCdmManager::UpdateSession(int cdm_id, |
64 uint32 session_id, | 80 uint32_t promise_id, |
65 const std::vector<uint8>& response) { | 81 const std::string& session_id, |
| 82 const std::vector<uint8_t>& response) { |
66 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; | 83 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; |
67 Send( | 84 Send(new CdmHostMsg_UpdateSession(routing_id(), cdm_id, promise_id, |
68 new CdmHostMsg_UpdateSession(routing_id(), cdm_id, session_id, response)); | 85 session_id, response)); |
69 } | 86 } |
70 | 87 |
71 void RendererCdmManager::ReleaseSession(int cdm_id, uint32 session_id) { | 88 void RendererCdmManager::CloseSession(int cdm_id, |
| 89 uint32_t promise_id, |
| 90 const std::string& session_id) { |
72 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; | 91 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; |
73 Send(new CdmHostMsg_ReleaseSession(routing_id(), cdm_id, session_id)); | 92 Send(new CdmHostMsg_CloseSession(routing_id(), cdm_id, promise_id, |
| 93 session_id)); |
74 } | 94 } |
75 | 95 |
76 void RendererCdmManager::DestroyCdm(int cdm_id) { | 96 void RendererCdmManager::DestroyCdm(int cdm_id) { |
77 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; | 97 DCHECK(GetMediaKeys(cdm_id)) << "|cdm_id| not registered."; |
78 Send(new CdmHostMsg_DestroyCdm(routing_id(), cdm_id)); | 98 Send(new CdmHostMsg_DestroyCdm(routing_id(), cdm_id)); |
79 } | 99 } |
80 | 100 |
81 void RendererCdmManager::OnSessionCreated(int cdm_id, | 101 void RendererCdmManager::OnSessionMessage( |
82 uint32 session_id, | 102 int cdm_id, |
83 const std::string& web_session_id) { | 103 const std::string& session_id, |
84 if (web_session_id.length() > kMaxWebSessionIdLength) { | 104 media::MediaKeys::MessageType message_type, |
85 OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); | 105 const std::vector<uint8>& message, |
| 106 const GURL& legacy_destination_url) { |
| 107 if (message.size() > kMaxSessionMessageLength) { |
| 108 NOTREACHED(); |
| 109 LOG(ERROR) << "Message is too long and dropped."; |
86 return; | 110 return; |
87 } | 111 } |
88 | 112 |
89 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); | 113 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
90 if (media_keys) | 114 if (media_keys) |
91 media_keys->OnSessionCreated(session_id, web_session_id); | 115 media_keys->OnSessionMessage(session_id, message_type, message, |
| 116 legacy_destination_url); |
92 } | 117 } |
93 | 118 |
94 void RendererCdmManager::OnSessionMessage(int cdm_id, | 119 void RendererCdmManager::OnSessionClosed(int cdm_id, |
95 uint32 session_id, | 120 const std::string& session_id) { |
96 const std::vector<uint8>& message, | 121 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
97 const GURL& destination_url) { | 122 if (media_keys) |
98 if (message.size() > kMaxSessionMessageLength) { | 123 media_keys->OnSessionClosed(session_id); |
99 OnSessionError(cdm_id, session_id, media::MediaKeys::kUnknownError, 0); | 124 } |
| 125 |
| 126 void RendererCdmManager::OnLegacySessionError( |
| 127 int cdm_id, |
| 128 const std::string& session_id, |
| 129 MediaKeys::Exception exception, |
| 130 uint32 system_code, |
| 131 const std::string& error_message) { |
| 132 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
| 133 if (media_keys) |
| 134 media_keys->OnLegacySessionError(session_id, exception, system_code, |
| 135 error_message); |
| 136 } |
| 137 |
| 138 void RendererCdmManager::OnSessionKeysChange( |
| 139 int cdm_id, |
| 140 const std::string& session_id, |
| 141 bool has_additional_usable_key, |
| 142 const std::vector<media::CdmKeyInformation>& key_info_vector) { |
| 143 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
| 144 if (!media_keys) |
| 145 return; |
| 146 |
| 147 media::CdmKeysInfo keys_info; |
| 148 keys_info.reserve(key_info_vector.size()); |
| 149 for (const auto& key_info : key_info_vector) |
| 150 keys_info.push_back(new media::CdmKeyInformation(key_info)); |
| 151 |
| 152 media_keys->OnSessionKeysChange(session_id, has_additional_usable_key, |
| 153 keys_info.Pass()); |
| 154 } |
| 155 |
| 156 void RendererCdmManager::OnSessionExpirationUpdate( |
| 157 int cdm_id, |
| 158 const std::string& session_id, |
| 159 const base::Time& new_expiry_time) { |
| 160 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
| 161 if (media_keys) |
| 162 media_keys->OnSessionExpirationUpdate(session_id, new_expiry_time); |
| 163 } |
| 164 |
| 165 void RendererCdmManager::OnPromiseResolved(int cdm_id, uint32_t promise_id) { |
| 166 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
| 167 if (media_keys) |
| 168 media_keys->OnPromiseResolved(promise_id); |
| 169 } |
| 170 |
| 171 void RendererCdmManager::OnPromiseResolvedWithSession( |
| 172 int cdm_id, |
| 173 uint32_t promise_id, |
| 174 const std::string& session_id) { |
| 175 if (session_id.length() > media::limits::kMaxWebSessionIdLength) { |
| 176 NOTREACHED(); |
| 177 OnPromiseRejected(cdm_id, promise_id, MediaKeys::INVALID_ACCESS_ERROR, 0, |
| 178 "Session ID is too long"); |
100 return; | 179 return; |
101 } | 180 } |
102 | 181 |
103 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); | 182 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
104 if (media_keys) | 183 if (media_keys) |
105 media_keys->OnSessionMessage(session_id, message, destination_url); | 184 media_keys->OnPromiseResolvedWithSession(promise_id, session_id); |
106 } | 185 } |
107 | 186 |
108 void RendererCdmManager::OnSessionReady(int cdm_id, uint32 session_id) { | 187 void RendererCdmManager::OnPromiseRejected(int cdm_id, |
| 188 uint32_t promise_id, |
| 189 MediaKeys::Exception exception, |
| 190 uint32_t system_code, |
| 191 const std::string& error_message) { |
109 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); | 192 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); |
110 if (media_keys) | 193 if (media_keys) |
111 media_keys->OnSessionReady(session_id); | 194 media_keys->OnPromiseRejected(promise_id, exception, system_code, |
112 } | 195 error_message); |
113 | |
114 void RendererCdmManager::OnSessionClosed(int cdm_id, uint32 session_id) { | |
115 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); | |
116 if (media_keys) | |
117 media_keys->OnSessionClosed(session_id); | |
118 } | |
119 | |
120 void RendererCdmManager::OnSessionError(int cdm_id, | |
121 uint32 session_id, | |
122 media::MediaKeys::KeyError error_code, | |
123 uint32 system_code) { | |
124 ProxyMediaKeys* media_keys = GetMediaKeys(cdm_id); | |
125 if (media_keys) | |
126 media_keys->OnSessionError(session_id, error_code, system_code); | |
127 } | 196 } |
128 | 197 |
129 int RendererCdmManager::RegisterMediaKeys(ProxyMediaKeys* media_keys) { | 198 int RendererCdmManager::RegisterMediaKeys(ProxyMediaKeys* media_keys) { |
130 int cdm_id = next_cdm_id_++; | 199 int cdm_id = next_cdm_id_++; |
131 DCHECK_NE(cdm_id, media::CdmContext::kInvalidCdmId); | 200 DCHECK_NE(cdm_id, media::CdmContext::kInvalidCdmId); |
132 DCHECK(!ContainsKey(proxy_media_keys_map_, cdm_id)); | 201 DCHECK(!ContainsKey(proxy_media_keys_map_, cdm_id)); |
133 proxy_media_keys_map_[cdm_id] = media_keys; | 202 proxy_media_keys_map_[cdm_id] = media_keys; |
134 return cdm_id; | 203 return cdm_id; |
135 } | 204 } |
136 | 205 |
137 void RendererCdmManager::UnregisterMediaKeys(int cdm_id) { | 206 void RendererCdmManager::UnregisterMediaKeys(int cdm_id) { |
138 DCHECK(ContainsKey(proxy_media_keys_map_, cdm_id)); | 207 DCHECK(ContainsKey(proxy_media_keys_map_, cdm_id)); |
139 proxy_media_keys_map_.erase(cdm_id); | 208 proxy_media_keys_map_.erase(cdm_id); |
140 } | 209 } |
141 | 210 |
142 ProxyMediaKeys* RendererCdmManager::GetMediaKeys(int cdm_id) { | 211 ProxyMediaKeys* RendererCdmManager::GetMediaKeys(int cdm_id) { |
143 std::map<int, ProxyMediaKeys*>::iterator iter = | 212 std::map<int, ProxyMediaKeys*>::iterator iter = |
144 proxy_media_keys_map_.find(cdm_id); | 213 proxy_media_keys_map_.find(cdm_id); |
145 return (iter != proxy_media_keys_map_.end()) ? iter->second : NULL; | 214 return (iter != proxy_media_keys_map_.end()) ? iter->second : NULL; |
146 } | 215 } |
147 | 216 |
148 } // namespace content | 217 } // namespace content |
OLD | NEW |