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

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

Powered by Google App Engine
This is Rietveld 408576698