Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1203)

Side by Side Diff: content/browser/media/cdm/browser_cdm_manager.cc

Issue 850183002: media: Support unprefixed EME API on Android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comment addressed Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/media/cdm/browser_cdm_manager.h ('k') | content/common/media/cdm_messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/browser/media/cdm/browser_cdm_manager.h" 5 #include "content/browser/media/cdm/browser_cdm_manager.h"
6 6
7 #include <string>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/command_line.h" 10 #include "base/command_line.h"
9 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
10 #include "base/task_runner.h" 13 #include "base/task_runner.h"
11 #include "content/common/media/cdm_messages.h" 14 #include "content/common/media/cdm_messages.h"
12 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/content_browser_client.h" 16 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/browser/render_frame_host.h" 17 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/render_process_host.h" 18 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/render_view_host.h" 19 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/web_contents.h" 20 #include "content/public/browser/web_contents.h"
18 #include "content/public/common/content_switches.h" 21 #include "content/public/common/content_switches.h"
19 #include "media/base/browser_cdm.h" 22 #include "media/base/browser_cdm.h"
20 #include "media/base/browser_cdm_factory.h" 23 #include "media/base/browser_cdm_factory.h"
24 #include "media/base/cdm_promise.h"
25 #include "media/base/limits.h"
21 #include "media/base/media_switches.h" 26 #include "media/base/media_switches.h"
22 27
23 namespace content { 28 namespace content {
24 29
25 using media::BrowserCdm; 30 using media::BrowserCdm;
26 using media::MediaKeys; 31 using media::MediaKeys;
27 32
33 namespace {
34
28 // Maximum lengths for various EME API parameters. These are checks to 35 // Maximum lengths for various EME API parameters. These are checks to
29 // prevent unnecessarily large parameters from being passed around, and the 36 // prevent unnecessarily large parameters from being passed around, and the
30 // lengths are somewhat arbitrary as the EME spec doesn't specify any limits. 37 // lengths are somewhat arbitrary as the EME spec doesn't specify any limits.
31 const size_t kMaxInitDataLength = 64 * 1024; // 64 KB 38 const size_t kMaxInitDataLength = 64 * 1024; // 64 KB
32 const size_t kMaxSessionResponseLength = 64 * 1024; // 64 KB 39 const size_t kMaxSessionResponseLength = 64 * 1024; // 64 KB
33 const size_t kMaxKeySystemLength = 256; 40 const size_t kMaxKeySystemLength = 256;
34 41
35 // The ID used in this class is a concatenation of |render_frame_id| and 42 // The ID used in this class is a concatenation of |render_frame_id| and
36 // |cdm_id|, i.e. (render_frame_id << 32) + cdm_id. 43 // |cdm_id|, i.e. (render_frame_id << 32) + cdm_id.
37 44
38 static uint64 GetId(int render_frame_id, int cdm_id) { 45 uint64 GetId(int render_frame_id, int cdm_id) {
39 return (static_cast<uint64>(render_frame_id) << 32) + 46 return (static_cast<uint64>(render_frame_id) << 32) +
40 static_cast<uint64>(cdm_id); 47 static_cast<uint64>(cdm_id);
41 } 48 }
42 49
43 static bool IdBelongsToFrame(uint64 id, int render_frame_id) { 50 bool IdBelongsToFrame(uint64 id, int render_frame_id) {
44 return (id >> 32) == static_cast<uint64>(render_frame_id); 51 return (id >> 32) == static_cast<uint64>(render_frame_id);
45 } 52 }
46 53
54 // media::CdmPromiseTemplate implementation backed by a BrowserCdmManager.
55 template <typename... T>
56 class CdmPromiseInternal : public media::CdmPromiseTemplate<T...> {
57 public:
58 CdmPromiseInternal(BrowserCdmManager* manager,
59 int render_frame_id,
60 int cdm_id,
61 uint32_t promise_id)
62 : manager_(manager),
63 render_frame_id_(render_frame_id),
64 cdm_id_(cdm_id),
65 promise_id_(promise_id) {
66 DCHECK(manager_);
67 }
68
69 ~CdmPromiseInternal() final {}
70
71 // CdmPromiseTemplate<> implementation.
72 void resolve(const T&... result) final;
73
74 void reject(MediaKeys::Exception exception,
75 uint32_t system_code,
76 const std::string& error_message) final {
77 MarkPromiseSettled();
78 manager_->RejectPromise(render_frame_id_, cdm_id_, promise_id_, exception,
79 system_code, error_message);
80 }
81
82 private:
83 using media::CdmPromiseTemplate<T...>::MarkPromiseSettled;
84
85 BrowserCdmManager* const manager_;
86 const int render_frame_id_;
87 const int cdm_id_;
88 const uint32_t promise_id_;
89 };
90
91 template <>
92 void CdmPromiseInternal<>::resolve() {
dcheng 2015/01/21 00:12:05 I'm not going to push for it in this patchset, but
93 MarkPromiseSettled();
94 manager_->ResolvePromise(render_frame_id_, cdm_id_, promise_id_);
95 }
96
97 template <>
98 void CdmPromiseInternal<std::string>::resolve(const std::string& session_id) {
99 MarkPromiseSettled();
100 manager_->ResolvePromiseWithSession(render_frame_id_, cdm_id_, promise_id_,
101 session_id);
102 }
103
104 typedef CdmPromiseInternal<> SimplePromise;
105 typedef CdmPromiseInternal<std::string> NewSessionPromise;
106
107 } // namespace
108
47 // Render process ID to BrowserCdmManager map. 109 // Render process ID to BrowserCdmManager map.
48 typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap; 110 typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap;
49 base::LazyInstance<BrowserCdmManagerMap> g_browser_cdm_manager_map = 111 base::LazyInstance<BrowserCdmManagerMap> g_browser_cdm_manager_map =
50 LAZY_INSTANCE_INITIALIZER; 112 LAZY_INSTANCE_INITIALIZER;
51 113
52 BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) { 114 BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) {
53 DCHECK_CURRENTLY_ON(BrowserThread::UI); 115 DCHECK_CURRENTLY_ON(BrowserThread::UI);
54 116
55 if (!g_browser_cdm_manager_map.Get().count(render_process_id)) 117 if (!g_browser_cdm_manager_map.Get().count(render_process_id))
56 return NULL; 118 return NULL;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 return NULL; 162 return NULL;
101 163
102 return task_runner_.get(); 164 return task_runner_.get();
103 } 165 }
104 166
105 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) { 167 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) {
106 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 168 DCHECK(task_runner_->RunsTasksOnCurrentThread());
107 bool handled = true; 169 bool handled = true;
108 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg) 170 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg)
109 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm) 171 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm)
110 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSession, OnCreateSession) 172 IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate)
173 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest,
174 OnCreateSessionAndGenerateRequest)
111 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession) 175 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession)
112 IPC_MESSAGE_HANDLER(CdmHostMsg_ReleaseSession, OnReleaseSession) 176 IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession)
113 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm) 177 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm)
114 IPC_MESSAGE_UNHANDLED(handled = false) 178 IPC_MESSAGE_UNHANDLED(handled = false)
115 IPC_END_MESSAGE_MAP() 179 IPC_END_MESSAGE_MAP()
116 return handled; 180 return handled;
117 } 181 }
118 182
119 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) { 183 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) {
120 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 184 DCHECK(task_runner_->RunsTasksOnCurrentThread());
121 return cdm_map_.get(GetId(render_frame_id, cdm_id)); 185 return cdm_map_.get(GetId(render_frame_id, cdm_id));
122 } 186 }
123 187
124 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) { 188 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) {
125 if (!task_runner_->RunsTasksOnCurrentThread()) { 189 if (!task_runner_->RunsTasksOnCurrentThread()) {
126 task_runner_->PostTask( 190 task_runner_->PostTask(
127 FROM_HERE, 191 FROM_HERE,
128 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame, 192 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame,
129 this, render_frame_id)); 193 this, render_frame_id));
130 return; 194 return;
131 } 195 }
132 RemoveAllCdmForFrame(render_frame_id); 196 RemoveAllCdmForFrame(render_frame_id);
133 } 197 }
134 198
135 void BrowserCdmManager::OnSessionCreated(int render_frame_id, 199 void BrowserCdmManager::ResolvePromise(int render_frame_id,
136 int cdm_id, 200 int cdm_id,
137 uint32 session_id, 201 uint32_t promise_id) {
138 const std::string& web_session_id) { 202 Send(new CdmMsg_ResolvePromise(render_frame_id, cdm_id, promise_id));
139 Send(new CdmMsg_SessionCreated(
140 render_frame_id, cdm_id, session_id, web_session_id));
141 } 203 }
142 204
143 void BrowserCdmManager::OnSessionMessage(int render_frame_id, 205 void BrowserCdmManager::ResolvePromiseWithSession(
144 int cdm_id, 206 int render_frame_id,
145 uint32 session_id, 207 int cdm_id,
146 const std::vector<uint8>& message, 208 uint32_t promise_id,
147 const GURL& destination_url) { 209 const std::string& session_id) {
148 GURL verified_gurl = destination_url; 210 if (session_id.length() > media::limits::kMaxWebSessionIdLength) {
149 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { 211 RejectPromise(render_frame_id, cdm_id, promise_id,
150 DLOG(WARNING) << "SessionMessage destination_url is invalid : " 212 MediaKeys::INVALID_ACCESS_ERROR, 0,
151 << destination_url.possibly_invalid_spec(); 213 "Session ID is too long.");
152 verified_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. 214 return;
153 } 215 }
154 216
155 Send(new CdmMsg_SessionMessage( 217 Send(new CdmMsg_ResolvePromiseWithSession(render_frame_id, cdm_id, promise_id,
156 render_frame_id, cdm_id, session_id, message, verified_gurl)); 218 session_id));
157 } 219 }
158 220
159 void BrowserCdmManager::OnSessionReady(int render_frame_id, 221 void BrowserCdmManager::RejectPromise(int render_frame_id,
160 int cdm_id, 222 int cdm_id,
161 uint32 session_id) { 223 uint32_t promise_id,
162 Send(new CdmMsg_SessionReady(render_frame_id, cdm_id, session_id)); 224 media::MediaKeys::Exception exception,
225 uint32_t system_code,
226 const std::string& error_message) {
227 Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception,
228 system_code, error_message));
229 }
230
231 void BrowserCdmManager::OnSessionMessage(
232 int render_frame_id,
233 int cdm_id,
234 const std::string& session_id,
235 media::MediaKeys::MessageType message_type,
236 const std::vector<uint8>& message,
237 const GURL& legacy_destination_url) {
238 GURL verified_gurl = legacy_destination_url;
239 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
240 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : "
241 << legacy_destination_url.possibly_invalid_spec();
242 verified_gurl =
243 GURL::EmptyGURL(); // Replace invalid legacy_destination_url.
244 }
245
246 Send(new CdmMsg_SessionMessage(render_frame_id, cdm_id, session_id,
247 message_type, message, verified_gurl));
163 } 248 }
164 249
165 void BrowserCdmManager::OnSessionClosed(int render_frame_id, 250 void BrowserCdmManager::OnSessionClosed(int render_frame_id,
166 int cdm_id, 251 int cdm_id,
167 uint32 session_id) { 252 const std::string& session_id) {
168 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id)); 253 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id));
169 } 254 }
170 255
171 void BrowserCdmManager::OnSessionError(int render_frame_id, 256 void BrowserCdmManager::OnLegacySessionError(
172 int cdm_id, 257 int render_frame_id,
173 uint32 session_id, 258 int cdm_id,
174 MediaKeys::KeyError error_code, 259 const std::string& session_id,
175 uint32 system_code) { 260 MediaKeys::Exception exception_code,
176 Send(new CdmMsg_SessionError( 261 uint32 system_code,
177 render_frame_id, cdm_id, session_id, error_code, system_code)); 262 const std::string& error_message) {
263 Send(new CdmMsg_LegacySessionError(render_frame_id, cdm_id, session_id,
264 exception_code, system_code,
265 error_message));
266 }
267
268 void BrowserCdmManager::OnSessionKeysChange(int render_frame_id,
269 int cdm_id,
270 const std::string& session_id,
271 bool has_additional_usable_key,
272 media::CdmKeysInfo keys_info) {
273 std::vector<media::CdmKeyInformation> key_info_vector;
274 for (const auto& key_info : keys_info)
275 key_info_vector.push_back(*key_info);
276 Send(new CdmMsg_SessionKeysChange(render_frame_id, cdm_id, session_id,
277 has_additional_usable_key,
278 key_info_vector));
279 }
280
281 void BrowserCdmManager::OnSessionExpirationUpdate(
282 int render_frame_id,
283 int cdm_id,
284 const std::string& session_id,
285 const base::Time& new_expiry_time) {
286 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id,
287 new_expiry_time));
178 } 288 }
179 289
180 void BrowserCdmManager::OnInitializeCdm(int render_frame_id, 290 void BrowserCdmManager::OnInitializeCdm(int render_frame_id,
181 int cdm_id, 291 int cdm_id,
182 const std::string& key_system, 292 const std::string& key_system,
183 const GURL& security_origin) { 293 const GURL& security_origin) {
184 if (key_system.size() > kMaxKeySystemLength) { 294 if (key_system.size() > kMaxKeySystemLength) {
185 // This failure will be discovered and reported by OnCreateSession() 295 // This failure will be discovered and reported by OnCreateSession()
186 // as GetCdm() will return null. 296 // as GetCdm() will return null.
187 NOTREACHED() << "Invalid key system: " << key_system; 297 NOTREACHED() << "Invalid key system: " << key_system;
188 return; 298 return;
189 } 299 }
190 300
191 AddCdm(render_frame_id, cdm_id, key_system, security_origin); 301 AddCdm(render_frame_id, cdm_id, key_system, security_origin);
192 } 302 }
193 303
194 void BrowserCdmManager::OnCreateSession( 304 void BrowserCdmManager::OnSetServerCertificate(
195 int render_frame_id, 305 int render_frame_id,
196 int cdm_id, 306 int cdm_id,
197 uint32 session_id, 307 uint32_t promise_id,
198 CdmHostMsg_CreateSession_ContentType content_type, 308 const std::vector<uint8_t>& certificate) {
309 scoped_ptr<SimplePromise> promise(
310 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
311
312 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
313 if (!cdm) {
314 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
315 return;
316 }
317
318 if (certificate.empty()) {
319 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate.");
320 return;
321 }
322
323 cdm->SetServerCertificate(&certificate[0], certificate.size(),
324 promise.Pass());
325 }
326
327 void BrowserCdmManager::OnCreateSessionAndGenerateRequest(
328 int render_frame_id,
329 int cdm_id,
330 uint32_t promise_id,
331 CdmHostMsg_CreateSession_InitDataType init_data_type,
199 const std::vector<uint8>& init_data) { 332 const std::vector<uint8>& init_data) {
333 scoped_ptr<NewSessionPromise> promise(
334 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id));
335
200 if (init_data.size() > kMaxInitDataLength) { 336 if (init_data.size() > kMaxInitDataLength) {
201 LOG(WARNING) << "InitData for ID: " << cdm_id 337 LOG(WARNING) << "InitData for ID: " << cdm_id
202 << " too long: " << init_data.size(); 338 << " too long: " << init_data.size();
203 SendSessionError(render_frame_id, cdm_id, session_id); 339 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long.");
204 return; 340 return;
205 } 341 }
206 342
207 // Convert the session content type into a MIME type. "audio" and "video" 343 // Convert the session content type into a MIME type. "audio" and "video"
208 // don't matter, so using "video" for the MIME type. 344 // don't matter, so using "video" for the MIME type.
209 // Ref: 345 // Ref:
210 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte d-media.html#dom-createsession 346 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte d-media.html#dom-createsession
211 std::string mime_type; 347 std::string mime_type;
212 switch (content_type) { 348 switch (init_data_type) {
213 case CREATE_SESSION_TYPE_WEBM: 349 case CREATE_SESSION_TYPE_WEBM:
214 mime_type = "video/webm"; 350 mime_type = "video/webm";
215 break; 351 break;
216 case CREATE_SESSION_TYPE_MP4: 352 case CREATE_SESSION_TYPE_MP4:
217 mime_type = "video/mp4"; 353 mime_type = "video/mp4";
218 break; 354 break;
219 default: 355 default:
220 NOTREACHED(); 356 NOTREACHED();
357 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
358 "Invalid init data type.");
221 return; 359 return;
222 } 360 }
223 361
224 #if defined(OS_ANDROID) 362 #if defined(OS_ANDROID)
225 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 363 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
226 switches::kDisableInfobarForProtectedMediaIdentifier)) { 364 switches::kDisableInfobarForProtectedMediaIdentifier)) {
227 CreateSessionIfPermitted( 365 GenerateRequestIfPermitted(render_frame_id, cdm_id, mime_type, init_data,
228 render_frame_id, cdm_id, session_id, mime_type, init_data, true); 366 promise.Pass(), true);
229 return; 367 return;
230 } 368 }
231 #endif 369 #endif
232 370
233 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 371 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
234 if (!cdm) { 372 if (!cdm) {
235 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 373 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
236 SendSessionError(render_frame_id, cdm_id, session_id); 374 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
237 return; 375 return;
238 } 376 }
239 377
240 std::map<uint64, GURL>::const_iterator iter = 378 std::map<uint64, GURL>::const_iterator iter =
241 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); 379 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id));
242 if (iter == cdm_security_origin_map_.end()) { 380 if (iter == cdm_security_origin_map_.end()) {
243 NOTREACHED(); 381 NOTREACHED();
244 SendSessionError(render_frame_id, cdm_id, session_id); 382 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
245 return; 383 return;
246 } 384 }
247 GURL security_origin = iter->second; 385 GURL security_origin = iter->second;
248 386
249 RequestSessionPermission(render_frame_id, 387 RequestSessionPermission(render_frame_id, security_origin, cdm_id, mime_type,
250 security_origin, 388 init_data, promise.Pass());
251 cdm_id,
252 session_id,
253 mime_type,
254 init_data);
255 } 389 }
256 390
257 void BrowserCdmManager::OnUpdateSession( 391 void BrowserCdmManager::OnUpdateSession(int render_frame_id,
258 int render_frame_id, 392 int cdm_id,
259 int cdm_id, 393 uint32_t promise_id,
260 uint32 session_id, 394 const std::string& session_id,
261 const std::vector<uint8>& response) { 395 const std::vector<uint8>& response) {
396 scoped_ptr<SimplePromise> promise(
397 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
398
262 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 399 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
263 if (!cdm) { 400 if (!cdm) {
264 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 401 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
265 SendSessionError(render_frame_id, cdm_id, session_id);
266 return; 402 return;
267 } 403 }
268 404
269 if (response.size() > kMaxSessionResponseLength) { 405 if (response.size() > kMaxSessionResponseLength) {
270 LOG(WARNING) << "Response for ID " << cdm_id 406 LOG(WARNING) << "Response for ID " << cdm_id
271 << " is too long: " << response.size(); 407 << " is too long: " << response.size();
272 SendSessionError(render_frame_id, cdm_id, session_id); 408 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long.");
273 return; 409 return;
274 } 410 }
275 411
276 cdm->UpdateSession(session_id, &response[0], response.size()); 412 if (response.empty()) {
277 } 413 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty.");
278
279 void BrowserCdmManager::OnReleaseSession(int render_frame_id,
280 int cdm_id,
281 uint32 session_id) {
282 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
283 if (!cdm) {
284 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
285 SendSessionError(render_frame_id, cdm_id, session_id);
286 return; 414 return;
287 } 415 }
288 416
289 cdm->ReleaseSession(session_id); 417 cdm->UpdateSession(session_id, &response[0], response.size(), promise.Pass());
418 }
419
420 void BrowserCdmManager::OnCloseSession(int render_frame_id,
421 int cdm_id,
422 uint32_t promise_id,
423 const std::string& session_id) {
424 scoped_ptr<SimplePromise> promise(
425 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
426
427 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
428 if (!cdm) {
429 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
430 return;
431 }
432
433 cdm->CloseSession(session_id, promise.Pass());
290 } 434 }
291 435
292 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { 436 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) {
293 RemoveCdm(GetId(render_frame_id, cdm_id)); 437 RemoveCdm(GetId(render_frame_id, cdm_id));
294 } 438 }
295 439
296 void BrowserCdmManager::SendSessionError(int render_frame_id,
297 int cdm_id,
298 uint32 session_id) {
299 OnSessionError(
300 render_frame_id, cdm_id, session_id, MediaKeys::kUnknownError, 0);
301 }
302
303 #define BROWSER_CDM_MANAGER_CB(func) \ 440 #define BROWSER_CDM_MANAGER_CB(func) \
304 base::Bind(&BrowserCdmManager::func, this, render_frame_id, cdm_id) 441 base::Bind(&BrowserCdmManager::func, this, render_frame_id, cdm_id)
305 442
306 void BrowserCdmManager::AddCdm(int render_frame_id, 443 void BrowserCdmManager::AddCdm(int render_frame_id,
307 int cdm_id, 444 int cdm_id,
308 const std::string& key_system, 445 const std::string& key_system,
309 const GURL& security_origin) { 446 const GURL& security_origin) {
310 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 447 DCHECK(task_runner_->RunsTasksOnCurrentThread());
311 DCHECK(!GetCdm(render_frame_id, cdm_id)); 448 DCHECK(!GetCdm(render_frame_id, cdm_id));
312 449
313 scoped_ptr<BrowserCdm> cdm( 450 scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
314 media::CreateBrowserCdm(key_system, 451 key_system, BROWSER_CDM_MANAGER_CB(OnSessionMessage),
315 BROWSER_CDM_MANAGER_CB(OnSessionCreated), 452 BROWSER_CDM_MANAGER_CB(OnSessionClosed),
316 BROWSER_CDM_MANAGER_CB(OnSessionMessage), 453 BROWSER_CDM_MANAGER_CB(OnLegacySessionError),
317 BROWSER_CDM_MANAGER_CB(OnSessionReady), 454 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange),
318 BROWSER_CDM_MANAGER_CB(OnSessionClosed), 455 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate)));
319 BROWSER_CDM_MANAGER_CB(OnSessionError)));
320 456
321 if (!cdm) { 457 if (!cdm) {
322 // This failure will be discovered and reported by OnCreateSession() 458 // This failure will be discovered and reported by
323 // as GetCdm() will return null. 459 // OnCreateSessionAndGenerateRequest() as GetCdm() will return null.
324 DVLOG(1) << "failed to create CDM."; 460 DVLOG(1) << "failed to create CDM.";
325 return; 461 return;
326 } 462 }
327 463
328 uint64 id = GetId(render_frame_id, cdm_id); 464 uint64 id = GetId(render_frame_id, cdm_id);
329 cdm_map_.add(id, cdm.Pass()); 465 cdm_map_.add(id, cdm.Pass());
330 cdm_security_origin_map_[id] = security_origin; 466 cdm_security_origin_map_[id] = security_origin;
331 } 467 }
332 468
333 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) { 469 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) {
(...skipping 17 matching lines...) Expand all
351 if (cdm_cancel_permission_map_.count(id)) { 487 if (cdm_cancel_permission_map_.count(id)) {
352 cdm_cancel_permission_map_[id].Run(); 488 cdm_cancel_permission_map_[id].Run();
353 cdm_cancel_permission_map_.erase(id); 489 cdm_cancel_permission_map_.erase(id);
354 } 490 }
355 } 491 }
356 492
357 void BrowserCdmManager::RequestSessionPermission( 493 void BrowserCdmManager::RequestSessionPermission(
358 int render_frame_id, 494 int render_frame_id,
359 const GURL& security_origin, 495 const GURL& security_origin,
360 int cdm_id, 496 int cdm_id,
361 uint32 session_id, 497 const std::string& init_data_type,
362 const std::string& content_type, 498 const std::vector<uint8>& init_data,
363 const std::vector<uint8>& init_data) { 499 scoped_ptr<media::NewSessionCdmPromise> promise) {
364 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 500 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
365 BrowserThread::PostTask( 501 BrowserThread::PostTask(
366 BrowserThread::UI, 502 BrowserThread::UI, FROM_HERE,
367 FROM_HERE, 503 base::Bind(&BrowserCdmManager::RequestSessionPermission, this,
368 base::Bind(&BrowserCdmManager::RequestSessionPermission, 504 render_frame_id, security_origin, cdm_id, init_data_type,
369 this, 505 init_data, base::Passed(&promise)));
370 render_frame_id,
371 security_origin,
372 cdm_id,
373 session_id,
374 content_type,
375 init_data));
376 return; 506 return;
377 } 507 }
378 508
379 RenderFrameHost* rfh = 509 RenderFrameHost* rfh =
380 RenderFrameHost::FromID(render_process_id_, render_frame_id); 510 RenderFrameHost::FromID(render_process_id_, render_frame_id);
381 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); 511 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
382 DCHECK(web_contents); 512 DCHECK(web_contents);
383 GetContentClient()->browser()->RequestPermission( 513 GetContentClient()->browser()->RequestPermission(
384 content::PERMISSION_PROTECTED_MEDIA, 514 content::PERMISSION_PROTECTED_MEDIA, web_contents,
385 web_contents,
386 0, // bridge id 515 0, // bridge id
387 security_origin, 516 security_origin,
388 // Only implemented for Android infobars which do not support 517 // Only implemented for Android infobars which do not support
389 // user gestures. 518 // user gestures.
390 true, 519 true, base::Bind(&BrowserCdmManager::GenerateRequestIfPermitted, this,
391 base::Bind(&BrowserCdmManager::CreateSessionIfPermitted, 520 render_frame_id, cdm_id, init_data_type, init_data,
392 this, 521 base::Passed(&promise)));
393 render_frame_id,
394 cdm_id,
395 session_id,
396 content_type,
397 init_data));
398 } 522 }
399 523
400 void BrowserCdmManager::CreateSessionIfPermitted( 524 void BrowserCdmManager::GenerateRequestIfPermitted(
401 int render_frame_id, 525 int render_frame_id,
402 int cdm_id, 526 int cdm_id,
403 uint32 session_id, 527 const std::string& init_data_type,
404 const std::string& content_type,
405 const std::vector<uint8>& init_data, 528 const std::vector<uint8>& init_data,
529 scoped_ptr<media::NewSessionCdmPromise> promise,
406 bool permitted) { 530 bool permitted) {
407 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id)); 531 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id));
408 if (!permitted) { 532 if (!permitted) {
409 SendSessionError(render_frame_id, cdm_id, session_id); 533 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
410 return; 534 return;
411 } 535 }
412 536
413 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 537 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
414 if (!cdm) { 538 if (!cdm) {
415 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 539 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
416 SendSessionError(render_frame_id, cdm_id, session_id);
417 return; 540 return;
418 } 541 }
419 542
420 // This could fail, in which case a SessionError will be fired. 543 // Only the temporary session type is supported in browser CDM path.
421 cdm->CreateSession(session_id, content_type, &init_data[0], init_data.size()); 544 // TODO(xhwang): Add SessionType support if needed.
545 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION,
546 init_data_type, &init_data[0],
547 init_data.size(), promise.Pass());
422 } 548 }
423 549
424 } // namespace content 550 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/cdm/browser_cdm_manager.h ('k') | content/common/media/cdm_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698