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

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

Powered by Google App Engine
This is Rietveld 408576698