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

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: rebase only 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
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() {
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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 return NULL; 166 return NULL;
105 167
106 return task_runner_.get(); 168 return task_runner_.get();
107 } 169 }
108 170
109 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) { 171 bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) {
110 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 172 DCHECK(task_runner_->RunsTasksOnCurrentThread());
111 bool handled = true; 173 bool handled = true;
112 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg) 174 IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg)
113 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm) 175 IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm)
114 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSession, OnCreateSession) 176 IPC_MESSAGE_HANDLER(CdmHostMsg_SetServerCertificate, OnSetServerCertificate)
177 IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSessionAndGenerateRequest,
178 OnCreateSessionAndGenerateRequest)
115 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession) 179 IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession)
116 IPC_MESSAGE_HANDLER(CdmHostMsg_ReleaseSession, OnReleaseSession) 180 IPC_MESSAGE_HANDLER(CdmHostMsg_CloseSession, OnCloseSession)
117 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm) 181 IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm)
118 IPC_MESSAGE_UNHANDLED(handled = false) 182 IPC_MESSAGE_UNHANDLED(handled = false)
119 IPC_END_MESSAGE_MAP() 183 IPC_END_MESSAGE_MAP()
120 return handled; 184 return handled;
121 } 185 }
122 186
123 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) { 187 media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) {
124 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 188 DCHECK(task_runner_->RunsTasksOnCurrentThread());
125 return cdm_map_.get(GetId(render_frame_id, cdm_id)); 189 return cdm_map_.get(GetId(render_frame_id, cdm_id));
126 } 190 }
127 191
128 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) { 192 void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) {
129 if (!task_runner_->RunsTasksOnCurrentThread()) { 193 if (!task_runner_->RunsTasksOnCurrentThread()) {
130 task_runner_->PostTask( 194 task_runner_->PostTask(
131 FROM_HERE, 195 FROM_HERE,
132 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame, 196 base::Bind(&BrowserCdmManager::RemoveAllCdmForFrame,
133 this, render_frame_id)); 197 this, render_frame_id));
134 return; 198 return;
135 } 199 }
136 RemoveAllCdmForFrame(render_frame_id); 200 RemoveAllCdmForFrame(render_frame_id);
137 } 201 }
138 202
139 void BrowserCdmManager::OnSessionCreated(int render_frame_id, 203 void BrowserCdmManager::ResolvePromise(int render_frame_id,
140 int cdm_id, 204 int cdm_id,
141 uint32 session_id, 205 uint32_t promise_id) {
142 const std::string& web_session_id) { 206 Send(new CdmMsg_ResolvePromise(render_frame_id, cdm_id, promise_id));
143 Send(new CdmMsg_SessionCreated(
144 render_frame_id, cdm_id, session_id, web_session_id));
145 } 207 }
146 208
147 void BrowserCdmManager::OnSessionMessage(int render_frame_id, 209 void BrowserCdmManager::ResolvePromiseWithSession(
148 int cdm_id, 210 int render_frame_id,
149 uint32 session_id, 211 int cdm_id,
150 const std::vector<uint8>& message, 212 uint32_t promise_id,
151 const GURL& destination_url) { 213 const std::string& session_id) {
152 GURL verified_gurl = destination_url; 214 if (session_id.length() > media::limits::kMaxWebSessionIdLength) {
153 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) { 215 RejectPromise(render_frame_id, cdm_id, promise_id,
154 DLOG(WARNING) << "SessionMessage destination_url is invalid : " 216 MediaKeys::INVALID_ACCESS_ERROR, 0,
155 << destination_url.possibly_invalid_spec(); 217 "Session ID is too long.");
156 verified_gurl = GURL::EmptyGURL(); // Replace invalid destination_url. 218 return;
157 } 219 }
158 220
159 Send(new CdmMsg_SessionMessage( 221 Send(new CdmMsg_ResolvePromiseWithSession(render_frame_id, cdm_id, promise_id,
160 render_frame_id, cdm_id, session_id, message, verified_gurl)); 222 session_id));
161 } 223 }
162 224
163 void BrowserCdmManager::OnSessionReady(int render_frame_id, 225 void BrowserCdmManager::RejectPromise(int render_frame_id,
164 int cdm_id, 226 int cdm_id,
165 uint32 session_id) { 227 uint32_t promise_id,
166 Send(new CdmMsg_SessionReady(render_frame_id, cdm_id, session_id)); 228 media::MediaKeys::Exception exception,
229 uint32_t system_code,
230 const std::string& error_message) {
231 Send(new CdmMsg_RejectPromise(render_frame_id, cdm_id, promise_id, exception,
232 system_code, error_message));
233 }
234
235 void BrowserCdmManager::OnSessionMessage(
236 int render_frame_id,
237 int cdm_id,
238 const std::string& session_id,
239 media::MediaKeys::MessageType message_type,
240 const std::vector<uint8>& message,
241 const GURL& legacy_destination_url) {
242 GURL verified_gurl = legacy_destination_url;
243 if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
244 DLOG(WARNING) << "SessionMessage legacy_destination_url is invalid : "
245 << legacy_destination_url.possibly_invalid_spec();
246 verified_gurl =
247 GURL::EmptyGURL(); // Replace invalid legacy_destination_url.
248 }
249
250 Send(new CdmMsg_SessionMessage(render_frame_id, cdm_id, session_id,
251 message_type, message, verified_gurl));
167 } 252 }
168 253
169 void BrowserCdmManager::OnSessionClosed(int render_frame_id, 254 void BrowserCdmManager::OnSessionClosed(int render_frame_id,
170 int cdm_id, 255 int cdm_id,
171 uint32 session_id) { 256 const std::string& session_id) {
172 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id)); 257 Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id));
173 } 258 }
174 259
175 void BrowserCdmManager::OnSessionError(int render_frame_id, 260 void BrowserCdmManager::OnLegacySessionError(
176 int cdm_id, 261 int render_frame_id,
177 uint32 session_id, 262 int cdm_id,
178 MediaKeys::KeyError error_code, 263 const std::string& session_id,
179 uint32 system_code) { 264 MediaKeys::Exception exception_code,
180 Send(new CdmMsg_SessionError( 265 uint32 system_code,
181 render_frame_id, cdm_id, session_id, error_code, system_code)); 266 const std::string& error_message) {
267 Send(new CdmMsg_LegacySessionError(render_frame_id, cdm_id, session_id,
268 exception_code, system_code,
269 error_message));
270 }
271
272 void BrowserCdmManager::OnSessionKeysChange(int render_frame_id,
273 int cdm_id,
274 const std::string& session_id,
275 bool has_additional_usable_key,
276 media::CdmKeysInfo keys_info) {
277 std::vector<media::CdmKeyInformation> key_info_vector;
278 for (const auto& key_info : keys_info)
279 key_info_vector.push_back(*key_info);
280 Send(new CdmMsg_SessionKeysChange(render_frame_id, cdm_id, session_id,
281 has_additional_usable_key,
282 key_info_vector));
283 }
284
285 void BrowserCdmManager::OnSessionExpirationUpdate(
286 int render_frame_id,
287 int cdm_id,
288 const std::string& session_id,
289 const base::Time& new_expiry_time) {
290 Send(new CdmMsg_SessionExpirationUpdate(render_frame_id, cdm_id, session_id,
291 new_expiry_time));
182 } 292 }
183 293
184 void BrowserCdmManager::OnInitializeCdm(int render_frame_id, 294 void BrowserCdmManager::OnInitializeCdm(int render_frame_id,
185 int cdm_id, 295 int cdm_id,
186 const std::string& key_system, 296 const std::string& key_system,
187 const GURL& security_origin) { 297 const GURL& security_origin) {
188 if (key_system.size() > kMaxKeySystemLength) { 298 if (key_system.size() > kMaxKeySystemLength) {
189 // This failure will be discovered and reported by OnCreateSession() 299 // This failure will be discovered and reported by OnCreateSession()
190 // as GetCdm() will return null. 300 // as GetCdm() will return null.
191 NOTREACHED() << "Invalid key system: " << key_system; 301 NOTREACHED() << "Invalid key system: " << key_system;
192 return; 302 return;
193 } 303 }
194 304
195 AddCdm(render_frame_id, cdm_id, key_system, security_origin); 305 AddCdm(render_frame_id, cdm_id, key_system, security_origin);
196 } 306 }
197 307
198 void BrowserCdmManager::OnCreateSession( 308 void BrowserCdmManager::OnSetServerCertificate(
199 int render_frame_id, 309 int render_frame_id,
200 int cdm_id, 310 int cdm_id,
201 uint32 session_id, 311 uint32_t promise_id,
202 CdmHostMsg_CreateSession_ContentType content_type, 312 const std::vector<uint8_t>& certificate) {
313 scoped_ptr<SimplePromise> promise(
314 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
315
316 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
317 if (!cdm) {
318 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
319 return;
320 }
321
322 if (certificate.empty()) {
323 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Empty certificate.");
324 return;
325 }
326
327 cdm->SetServerCertificate(&certificate[0], certificate.size(),
328 promise.Pass());
329 }
330
331 void BrowserCdmManager::OnCreateSessionAndGenerateRequest(
332 int render_frame_id,
333 int cdm_id,
334 uint32_t promise_id,
335 CdmHostMsg_CreateSession_InitDataType init_data_type,
203 const std::vector<uint8>& init_data) { 336 const std::vector<uint8>& init_data) {
337 scoped_ptr<NewSessionPromise> promise(
338 new NewSessionPromise(this, render_frame_id, cdm_id, promise_id));
339
204 if (init_data.size() > kMaxInitDataLength) { 340 if (init_data.size() > kMaxInitDataLength) {
205 LOG(WARNING) << "InitData for ID: " << cdm_id 341 LOG(WARNING) << "InitData for ID: " << cdm_id
206 << " too long: " << init_data.size(); 342 << " too long: " << init_data.size();
207 SendSessionError(render_frame_id, cdm_id, session_id); 343 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Init data too long.");
208 return; 344 return;
209 } 345 }
210 346
211 // Convert the session content type into a MIME type. "audio" and "video" 347 // Convert the session content type into a MIME type. "audio" and "video"
212 // don't matter, so using "video" for the MIME type. 348 // don't matter, so using "video" for the MIME type.
213 // Ref: 349 // Ref:
214 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte d-media.html#dom-createsession 350 // https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypte d-media.html#dom-createsession
215 std::string mime_type; 351 std::string mime_type;
216 switch (content_type) { 352 switch (init_data_type) {
217 case CREATE_SESSION_TYPE_WEBM: 353 case CREATE_SESSION_TYPE_WEBM:
218 mime_type = "video/webm"; 354 mime_type = "video/webm";
219 break; 355 break;
220 case CREATE_SESSION_TYPE_MP4: 356 case CREATE_SESSION_TYPE_MP4:
221 mime_type = "video/mp4"; 357 mime_type = "video/mp4";
222 break; 358 break;
223 default: 359 default:
224 NOTREACHED(); 360 NOTREACHED();
361 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0,
362 "Invalid init data type.");
225 return; 363 return;
226 } 364 }
227 365
228 #if defined(OS_ANDROID) 366 #if defined(OS_ANDROID)
229 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 367 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
230 switches::kDisableInfobarForProtectedMediaIdentifier)) { 368 switches::kDisableInfobarForProtectedMediaIdentifier)) {
231 CreateSessionIfPermitted( 369 GenerateRequestIfPermitted(render_frame_id, cdm_id, mime_type, init_data,
232 render_frame_id, cdm_id, session_id, mime_type, init_data, true); 370 promise.Pass(), true);
233 return; 371 return;
234 } 372 }
235 #endif 373 #endif
236 374
237 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 375 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
238 if (!cdm) { 376 if (!cdm) {
239 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 377 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
240 SendSessionError(render_frame_id, cdm_id, session_id); 378 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
241 return; 379 return;
242 } 380 }
243 381
244 std::map<uint64, GURL>::const_iterator iter = 382 std::map<uint64, GURL>::const_iterator iter =
245 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id)); 383 cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id));
246 if (iter == cdm_security_origin_map_.end()) { 384 if (iter == cdm_security_origin_map_.end()) {
247 NOTREACHED(); 385 NOTREACHED();
248 SendSessionError(render_frame_id, cdm_id, session_id); 386 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
249 return; 387 return;
250 } 388 }
251 GURL security_origin = iter->second; 389 GURL security_origin = iter->second;
252 390
253 RequestSessionPermission(render_frame_id, 391 RequestSessionPermission(render_frame_id, security_origin, cdm_id, mime_type,
254 security_origin, 392 init_data, promise.Pass());
255 cdm_id,
256 session_id,
257 mime_type,
258 init_data);
259 } 393 }
260 394
261 void BrowserCdmManager::OnUpdateSession( 395 void BrowserCdmManager::OnUpdateSession(int render_frame_id,
262 int render_frame_id, 396 int cdm_id,
263 int cdm_id, 397 uint32_t promise_id,
264 uint32 session_id, 398 const std::string& session_id,
265 const std::vector<uint8>& response) { 399 const std::vector<uint8>& response) {
400 scoped_ptr<SimplePromise> promise(
401 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
402
266 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 403 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
267 if (!cdm) { 404 if (!cdm) {
268 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 405 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
269 SendSessionError(render_frame_id, cdm_id, session_id);
270 return; 406 return;
271 } 407 }
272 408
273 if (response.size() > kMaxSessionResponseLength) { 409 if (response.size() > kMaxSessionResponseLength) {
274 LOG(WARNING) << "Response for ID " << cdm_id 410 LOG(WARNING) << "Response for ID " << cdm_id
275 << " is too long: " << response.size(); 411 << " is too long: " << response.size();
276 SendSessionError(render_frame_id, cdm_id, session_id); 412 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response too long.");
277 return; 413 return;
278 } 414 }
279 415
280 cdm->UpdateSession(session_id, &response[0], response.size()); 416 if (response.empty()) {
281 } 417 promise->reject(MediaKeys::INVALID_ACCESS_ERROR, 0, "Response is empty.");
282
283 void BrowserCdmManager::OnReleaseSession(int render_frame_id,
284 int cdm_id,
285 uint32 session_id) {
286 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
287 if (!cdm) {
288 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
289 SendSessionError(render_frame_id, cdm_id, session_id);
290 return; 418 return;
291 } 419 }
292 420
293 cdm->ReleaseSession(session_id); 421 cdm->UpdateSession(session_id, &response[0], response.size(), promise.Pass());
422 }
423
424 void BrowserCdmManager::OnCloseSession(int render_frame_id,
425 int cdm_id,
426 uint32_t promise_id,
427 const std::string& session_id) {
428 scoped_ptr<SimplePromise> promise(
429 new SimplePromise(this, render_frame_id, cdm_id, promise_id));
430
431 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
432 if (!cdm) {
433 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
434 return;
435 }
436
437 cdm->CloseSession(session_id, promise.Pass());
294 } 438 }
295 439
296 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) { 440 void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) {
297 RemoveCdm(GetId(render_frame_id, cdm_id)); 441 RemoveCdm(GetId(render_frame_id, cdm_id));
298 } 442 }
299 443
300 void BrowserCdmManager::SendSessionError(int render_frame_id,
301 int cdm_id,
302 uint32 session_id) {
303 OnSessionError(
304 render_frame_id, cdm_id, session_id, MediaKeys::kUnknownError, 0);
305 }
306
307 // Use a weak pointer here instead of |this| to avoid circular references. 444 // Use a weak pointer here instead of |this| to avoid circular references.
308 #define BROWSER_CDM_MANAGER_CB(func) \ 445 #define BROWSER_CDM_MANAGER_CB(func) \
309 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \ 446 base::Bind(&BrowserCdmManager::func, weak_ptr_factory_.GetWeakPtr(), \
310 render_frame_id, cdm_id) 447 render_frame_id, cdm_id)
311 448
312 void BrowserCdmManager::AddCdm(int render_frame_id, 449 void BrowserCdmManager::AddCdm(int render_frame_id,
313 int cdm_id, 450 int cdm_id,
314 const std::string& key_system, 451 const std::string& key_system,
315 const GURL& security_origin) { 452 const GURL& security_origin) {
316 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 453 DCHECK(task_runner_->RunsTasksOnCurrentThread());
317 DCHECK(!GetCdm(render_frame_id, cdm_id)); 454 DCHECK(!GetCdm(render_frame_id, cdm_id));
318 455
319 scoped_ptr<BrowserCdm> cdm( 456 scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
320 media::CreateBrowserCdm(key_system, 457 key_system, BROWSER_CDM_MANAGER_CB(OnSessionMessage),
321 BROWSER_CDM_MANAGER_CB(OnSessionCreated), 458 BROWSER_CDM_MANAGER_CB(OnSessionClosed),
322 BROWSER_CDM_MANAGER_CB(OnSessionMessage), 459 BROWSER_CDM_MANAGER_CB(OnLegacySessionError),
323 BROWSER_CDM_MANAGER_CB(OnSessionReady), 460 BROWSER_CDM_MANAGER_CB(OnSessionKeysChange),
324 BROWSER_CDM_MANAGER_CB(OnSessionClosed), 461 BROWSER_CDM_MANAGER_CB(OnSessionExpirationUpdate)));
325 BROWSER_CDM_MANAGER_CB(OnSessionError)));
326 462
327 if (!cdm) { 463 if (!cdm) {
328 // This failure will be discovered and reported by OnCreateSession() 464 // This failure will be discovered and reported by
329 // as GetCdm() will return null. 465 // OnCreateSessionAndGenerateRequest() as GetCdm() will return null.
330 DVLOG(1) << "failed to create CDM."; 466 DVLOG(1) << "failed to create CDM.";
331 return; 467 return;
332 } 468 }
333 469
334 uint64 id = GetId(render_frame_id, cdm_id); 470 uint64 id = GetId(render_frame_id, cdm_id);
335 cdm_map_.add(id, cdm.Pass()); 471 cdm_map_.add(id, cdm.Pass());
336 cdm_security_origin_map_[id] = security_origin; 472 cdm_security_origin_map_[id] = security_origin;
337 } 473 }
338 474
339 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) { 475 void BrowserCdmManager::RemoveAllCdmForFrame(int render_frame_id) {
(...skipping 17 matching lines...) Expand all
357 if (cdm_cancel_permission_map_.count(id)) { 493 if (cdm_cancel_permission_map_.count(id)) {
358 cdm_cancel_permission_map_[id].Run(); 494 cdm_cancel_permission_map_[id].Run();
359 cdm_cancel_permission_map_.erase(id); 495 cdm_cancel_permission_map_.erase(id);
360 } 496 }
361 } 497 }
362 498
363 void BrowserCdmManager::RequestSessionPermission( 499 void BrowserCdmManager::RequestSessionPermission(
364 int render_frame_id, 500 int render_frame_id,
365 const GURL& security_origin, 501 const GURL& security_origin,
366 int cdm_id, 502 int cdm_id,
367 uint32 session_id, 503 const std::string& init_data_type,
368 const std::string& content_type, 504 const std::vector<uint8>& init_data,
369 const std::vector<uint8>& init_data) { 505 scoped_ptr<media::NewSessionCdmPromise> promise) {
370 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 506 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
371 BrowserThread::PostTask( 507 BrowserThread::PostTask(
372 BrowserThread::UI, 508 BrowserThread::UI, FROM_HERE,
373 FROM_HERE, 509 base::Bind(&BrowserCdmManager::RequestSessionPermission, this,
374 base::Bind(&BrowserCdmManager::RequestSessionPermission, 510 render_frame_id, security_origin, cdm_id, init_data_type,
375 this, 511 init_data, base::Passed(&promise)));
376 render_frame_id,
377 security_origin,
378 cdm_id,
379 session_id,
380 content_type,
381 init_data));
382 return; 512 return;
383 } 513 }
384 514
385 RenderFrameHost* rfh = 515 RenderFrameHost* rfh =
386 RenderFrameHost::FromID(render_process_id_, render_frame_id); 516 RenderFrameHost::FromID(render_process_id_, render_frame_id);
387 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); 517 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
388 DCHECK(web_contents); 518 DCHECK(web_contents);
389 GetContentClient()->browser()->RequestPermission( 519 GetContentClient()->browser()->RequestPermission(
390 content::PERMISSION_PROTECTED_MEDIA, 520 content::PERMISSION_PROTECTED_MEDIA, web_contents,
391 web_contents,
392 0, // bridge id 521 0, // bridge id
393 security_origin, 522 security_origin,
394 // Only implemented for Android infobars which do not support 523 // Only implemented for Android infobars which do not support
395 // user gestures. 524 // user gestures.
396 true, 525 true, base::Bind(&BrowserCdmManager::GenerateRequestIfPermitted, this,
397 base::Bind(&BrowserCdmManager::CreateSessionIfPermitted, 526 render_frame_id, cdm_id, init_data_type, init_data,
398 this, 527 base::Passed(&promise)));
399 render_frame_id,
400 cdm_id,
401 session_id,
402 content_type,
403 init_data));
404 } 528 }
405 529
406 void BrowserCdmManager::CreateSessionIfPermitted( 530 void BrowserCdmManager::GenerateRequestIfPermitted(
407 int render_frame_id, 531 int render_frame_id,
408 int cdm_id, 532 int cdm_id,
409 uint32 session_id, 533 const std::string& init_data_type,
410 const std::string& content_type,
411 const std::vector<uint8>& init_data, 534 const std::vector<uint8>& init_data,
535 scoped_ptr<media::NewSessionCdmPromise> promise,
412 bool permitted) { 536 bool permitted) {
413 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id)); 537 cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id));
414 if (!permitted) { 538 if (!permitted) {
415 SendSessionError(render_frame_id, cdm_id, session_id); 539 promise->reject(MediaKeys::NOT_SUPPORTED_ERROR, 0, "Permission denied.");
416 return; 540 return;
417 } 541 }
418 542
419 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id); 543 BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
420 if (!cdm) { 544 if (!cdm) {
421 DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id; 545 promise->reject(MediaKeys::INVALID_STATE_ERROR, 0, "CDM not found.");
422 SendSessionError(render_frame_id, cdm_id, session_id);
423 return; 546 return;
424 } 547 }
425 548
426 // This could fail, in which case a SessionError will be fired. 549 // Only the temporary session type is supported in browser CDM path.
427 cdm->CreateSession(session_id, content_type, &init_data[0], init_data.size()); 550 // TODO(xhwang): Add SessionType support if needed.
551 cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION,
552 init_data_type, &init_data[0],
553 init_data.size(), promise.Pass());
428 } 554 }
429 555
430 } // namespace content 556 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698