OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/webcontentdecryptionmodulesession_impl.h" | 5 #include "content/renderer/media/webcontentdecryptionmodulesession_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "content/renderer/media/cdm_session_adapter.h" | 12 #include "content/renderer/media/cdm_session_adapter.h" |
13 #include "media/base/cdm_promise.h" | 13 #include "media/base/cdm_promise.h" |
14 #include "third_party/WebKit/public/platform/WebURL.h" | 14 #include "third_party/WebKit/public/platform/WebURL.h" |
15 | 15 |
16 namespace content { | 16 namespace content { |
17 | 17 |
18 const char kCreateSessionUMAName[] = "CreateSession"; | 18 const char kCreateSessionUMAName[] = "CreateSession"; |
19 | 19 |
20 // For backwards compatibility with blink not using | 20 // For backwards compatibility with blink not using |
21 // WebContentDecryptionModuleResult, reserve an index for |outstanding_results_| | 21 // WebContentDecryptionModuleResult, reserve an index for |outstanding_results_| |
22 // that will not be used when adding a WebContentDecryptionModuleResult. | 22 // that will not be used when adding a WebContentDecryptionModuleResult. |
23 // TODO(jrummell): Remove once blink always uses | 23 // TODO(jrummell): Remove once blink always uses |
24 // WebContentDecryptionModuleResult. | 24 // WebContentDecryptionModuleResult. |
25 const uint32 kReservedIndex = 0; | 25 const uint32 kReservedIndex = 0; |
26 | 26 |
27 static blink::WebContentDecryptionModuleException ConvertException( | |
28 media::MediaKeys::Exception exception_code) { | |
29 switch (exception_code) { | |
30 case media::MediaKeys::NOT_SUPPORTED_ERROR: | |
31 return blink::WebContentDecryptionModuleExceptionNotSupportedError; | |
32 case media::MediaKeys::INVALID_STATE_ERROR: | |
33 return blink::WebContentDecryptionModuleExceptionInvalidStateError; | |
34 case media::MediaKeys::INVALID_ACCESS_ERROR: | |
35 return blink::WebContentDecryptionModuleExceptionInvalidAccessError; | |
36 case media::MediaKeys::QUOTA_EXCEEDED_ERROR: | |
37 return blink::WebContentDecryptionModuleExceptionQuotaExceededError; | |
38 case media::MediaKeys::UNKNOWN_ERROR: | |
39 return blink::WebContentDecryptionModuleExceptionUnknownError; | |
40 case media::MediaKeys::CLIENT_ERROR: | |
41 return blink::WebContentDecryptionModuleExceptionClientError; | |
42 case media::MediaKeys::OUTPUT_ERROR: | |
43 return blink::WebContentDecryptionModuleExceptionOutputError; | |
44 default: | |
45 NOTREACHED(); | |
46 return blink::WebContentDecryptionModuleExceptionUnknownError; | |
47 } | |
48 } | |
49 | |
50 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( | 27 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( |
51 const scoped_refptr<CdmSessionAdapter>& adapter) | 28 const scoped_refptr<CdmSessionAdapter>& adapter) |
52 : adapter_(adapter), | 29 : adapter_(adapter), |
53 is_closed_(false), | 30 is_closed_(false), |
54 next_available_result_index_(1), | |
55 weak_ptr_factory_(this) { | 31 weak_ptr_factory_(this) { |
56 } | 32 } |
57 | 33 |
58 WebContentDecryptionModuleSessionImpl:: | 34 WebContentDecryptionModuleSessionImpl:: |
59 ~WebContentDecryptionModuleSessionImpl() { | 35 ~WebContentDecryptionModuleSessionImpl() { |
60 if (!web_session_id_.empty()) | 36 if (!web_session_id_.empty()) |
61 adapter_->RemoveSession(web_session_id_); | 37 adapter_->UnregisterSession(web_session_id_); |
62 | |
63 // Release any WebContentDecryptionModuleResult objects that are left. Their | |
64 // index will have been passed down via a CdmPromise, but it uses a WeakPtr. | |
65 DLOG_IF(WARNING, outstanding_results_.size() > 0) | |
66 << "Clearing " << outstanding_results_.size() << " results"; | |
67 for (ResultMap::iterator it = outstanding_results_.begin(); | |
68 it != outstanding_results_.end(); | |
69 ++it) { | |
70 it->second.completeWithError( | |
71 blink::WebContentDecryptionModuleExceptionInvalidStateError, | |
72 0, | |
73 "Outstanding request being cancelled."); | |
74 } | |
75 outstanding_results_.clear(); | |
76 } | 38 } |
77 | 39 |
78 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) { | 40 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) { |
79 client_ = client; | 41 client_ = client; |
80 } | 42 } |
81 | 43 |
82 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { | 44 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { |
83 return blink::WebString::fromUTF8(web_session_id_); | 45 return blink::WebString::fromUTF8(web_session_id_); |
84 } | 46 } |
85 | 47 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 adapter_->UpdateSession( | 92 adapter_->UpdateSession( |
131 web_session_id_, response, response_length, promise.Pass()); | 93 web_session_id_, response, response_length, promise.Pass()); |
132 } | 94 } |
133 | 95 |
134 void WebContentDecryptionModuleSessionImpl::release() { | 96 void WebContentDecryptionModuleSessionImpl::release() { |
135 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( | 97 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( |
136 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionClosed, | 98 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionClosed, |
137 weak_ptr_factory_.GetWeakPtr()), | 99 weak_ptr_factory_.GetWeakPtr()), |
138 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError, | 100 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError, |
139 weak_ptr_factory_.GetWeakPtr()))); | 101 weak_ptr_factory_.GetWeakPtr()))); |
140 adapter_->ReleaseSession(web_session_id_, promise.Pass()); | 102 adapter_->RemoveSession(web_session_id_, promise.Pass()); |
ddorwin
2014/09/12 21:46:29
CloseSession() is probably more appropriate, thoug
jrummell
2014/09/15 18:22:39
Blink doesn't call this. So it doesn't matter. Cha
| |
141 } | 103 } |
142 | 104 |
143 void WebContentDecryptionModuleSessionImpl::initializeNewSession( | 105 void WebContentDecryptionModuleSessionImpl::initializeNewSession( |
144 const blink::WebString& init_data_type, | 106 const blink::WebString& init_data_type, |
145 const uint8* init_data, | 107 const uint8* init_data, |
146 size_t init_data_length, | 108 size_t init_data_length, |
147 const blink::WebString& session_type, | 109 const blink::WebString& session_type, |
148 blink::WebContentDecryptionModuleResult result) { | 110 blink::WebContentDecryptionModuleResult result) { |
149 uint32 result_index = AddResult(result); | 111 uint32 result_index = outstanding_results_.AddResult(result); |
150 | 112 |
151 // TODO(ddorwin): Guard against this in supported types check and remove this. | 113 // TODO(ddorwin): Guard against this in supported types check and remove this. |
152 // Chromium only supports ASCII MIME types. | 114 // Chromium only supports ASCII MIME types. |
153 if (!base::IsStringASCII(init_data_type)) { | 115 if (!base::IsStringASCII(init_data_type)) { |
154 NOTREACHED(); | 116 NOTREACHED(); |
155 SessionError(result_index, | 117 SessionError(result_index, |
ddorwin
2014/09/11 23:31:11
This is the first instance of the one with "On". I
ddorwin
2014/09/12 21:46:29
OnPromiseRejected
jrummell
2014/09/15 18:22:40
Done.
jrummell
2014/09/15 18:22:40
Done.
| |
156 media::MediaKeys::NOT_SUPPORTED_ERROR, | 118 media::MediaKeys::NOT_SUPPORTED_ERROR, |
157 0, | 119 0, |
158 "The initialization data type " + init_data_type.utf8() + | 120 "The initialization data type " + init_data_type.utf8() + |
159 " is not supported by the key system."); | 121 " is not supported by the key system."); |
160 return; | 122 return; |
161 } | 123 } |
162 | 124 |
163 std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type); | 125 std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type); |
164 DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos) | 126 DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos) |
165 << "init_data_type '" << init_data_type_as_ascii | 127 << "init_data_type '" << init_data_type_as_ascii |
(...skipping 13 matching lines...) Expand all Loading... | |
179 init_data_length, | 141 init_data_length, |
180 media::MediaKeys::TEMPORARY_SESSION, | 142 media::MediaKeys::TEMPORARY_SESSION, |
181 promise.Pass()); | 143 promise.Pass()); |
182 } | 144 } |
183 | 145 |
184 void WebContentDecryptionModuleSessionImpl::update( | 146 void WebContentDecryptionModuleSessionImpl::update( |
185 const uint8* response, | 147 const uint8* response, |
186 size_t response_length, | 148 size_t response_length, |
187 blink::WebContentDecryptionModuleResult result) { | 149 blink::WebContentDecryptionModuleResult result) { |
188 DCHECK(response); | 150 DCHECK(response); |
189 uint32 result_index = AddResult(result); | 151 uint32 result_index = outstanding_results_.AddResult(result); |
190 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( | 152 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( |
191 base::Bind( | 153 base::Bind( |
192 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased, | 154 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased, |
193 weak_ptr_factory_.GetWeakPtr(), | 155 weak_ptr_factory_.GetWeakPtr(), |
194 result_index), | 156 result_index), |
195 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, | 157 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, |
196 weak_ptr_factory_.GetWeakPtr(), | 158 weak_ptr_factory_.GetWeakPtr(), |
197 result_index))); | 159 result_index))); |
198 adapter_->UpdateSession( | 160 adapter_->UpdateSession( |
199 web_session_id_, response, response_length, promise.Pass()); | 161 web_session_id_, response, response_length, promise.Pass()); |
200 } | 162 } |
201 | 163 |
164 void WebContentDecryptionModuleSessionImpl::close( | |
165 blink::WebContentDecryptionModuleResult result) { | |
166 uint32 result_index = outstanding_results_.AddResult(result); | |
ddorwin
2014/09/12 21:46:30
This is a lot of boilerplate code. It'd be nice to
jrummell
2014/09/15 18:22:39
Would work well for most of these calls. However,
| |
167 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( | |
ddorwin
2014/09/12 21:46:29
Related to above, can we eliminate outstanding_res
jrummell
2014/09/15 18:22:40
(I assume you mean CdmPromise.) Have a separate CL
ddorwin
2014/09/17 23:54:33
Okay, I think we'll need to wait for that before c
| |
168 base::Bind( | |
169 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased, | |
170 weak_ptr_factory_.GetWeakPtr(), | |
171 result_index), | |
172 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, | |
173 weak_ptr_factory_.GetWeakPtr(), | |
174 result_index))); | |
175 adapter_->CloseSession(web_session_id_, promise.Pass()); | |
176 } | |
177 | |
178 void WebContentDecryptionModuleSessionImpl::remove( | |
179 blink::WebContentDecryptionModuleResult result) { | |
180 uint32 result_index = outstanding_results_.AddResult(result); | |
181 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( | |
182 base::Bind( | |
183 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased, | |
184 weak_ptr_factory_.GetWeakPtr(), | |
185 result_index), | |
186 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, | |
187 weak_ptr_factory_.GetWeakPtr(), | |
188 result_index))); | |
189 adapter_->RemoveSession(web_session_id_, promise.Pass()); | |
190 } | |
191 | |
192 void WebContentDecryptionModuleSessionImpl::getUsableKeyIds( | |
193 blink::WebContentDecryptionModuleResult result) { | |
194 uint32 result_index = outstanding_results_.AddResult(result); | |
195 scoped_ptr<media::KeyIdsPromise> promise(new media::KeyIdsPromise( | |
196 base::Bind(&WebContentDecryptionModuleSessionImpl::KeyIdsAvailable, | |
197 weak_ptr_factory_.GetWeakPtr(), | |
198 result_index), | |
199 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, | |
200 weak_ptr_factory_.GetWeakPtr(), | |
201 result_index))); | |
202 adapter_->GetUsableKeyIds(web_session_id_, promise.Pass()); | |
203 } | |
204 | |
202 void WebContentDecryptionModuleSessionImpl::release( | 205 void WebContentDecryptionModuleSessionImpl::release( |
203 blink::WebContentDecryptionModuleResult result) { | 206 blink::WebContentDecryptionModuleResult result) { |
204 uint32 result_index = AddResult(result); | 207 uint32 result_index = outstanding_results_.AddResult(result); |
205 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( | 208 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( |
206 base::Bind( | 209 base::Bind( |
207 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased, | 210 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased, |
208 weak_ptr_factory_.GetWeakPtr(), | 211 weak_ptr_factory_.GetWeakPtr(), |
209 result_index), | 212 result_index), |
210 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, | 213 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, |
211 weak_ptr_factory_.GetWeakPtr(), | 214 weak_ptr_factory_.GetWeakPtr(), |
212 result_index))); | 215 result_index))); |
213 adapter_->ReleaseSession(web_session_id_, promise.Pass()); | 216 adapter_->RemoveSession(web_session_id_, promise.Pass()); |
ddorwin
2014/09/12 21:46:30
ditto
jrummell
2014/09/15 18:22:40
This one is called. Changed to close().
| |
214 } | 217 } |
215 | 218 |
216 void WebContentDecryptionModuleSessionImpl::OnSessionMessage( | 219 void WebContentDecryptionModuleSessionImpl::OnSessionMessage( |
217 const std::vector<uint8>& message, | 220 const std::vector<uint8>& message, |
218 const GURL& destination_url) { | 221 const GURL& destination_url) { |
219 DCHECK(client_) << "Client not set before message event"; | 222 DCHECK(client_) << "Client not set before message event"; |
220 client_->message( | 223 client_->message( |
221 message.empty() ? NULL : &message[0], message.size(), destination_url); | 224 message.empty() ? NULL : &message[0], message.size(), destination_url); |
222 } | 225 } |
223 | 226 |
227 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange( | |
228 bool has_additional_usable_key) { | |
229 // TODO(jrummell): Update this once Blink client supports this. | |
230 } | |
231 | |
232 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationChange( | |
233 double new_expiry_time) { | |
234 // TODO(jrummell): Update this once Blink client supports this. | |
235 } | |
236 | |
224 void WebContentDecryptionModuleSessionImpl::OnSessionReady() { | 237 void WebContentDecryptionModuleSessionImpl::OnSessionReady() { |
225 client_->ready(); | 238 client_->ready(); |
226 } | 239 } |
227 | 240 |
228 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() { | 241 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() { |
229 if (!is_closed_) { | 242 if (!is_closed_) { |
230 is_closed_ = true; | 243 is_closed_ = true; |
231 client_->close(); | 244 client_->close(); |
232 } | 245 } |
233 } | 246 } |
(...skipping 10 matching lines...) Expand all Loading... | |
244 client_->error(Client::MediaKeyErrorCodeClient, system_code); | 257 client_->error(Client::MediaKeyErrorCodeClient, system_code); |
245 break; | 258 break; |
246 default: | 259 default: |
247 // This will include all other CDM4 errors and any error generated | 260 // This will include all other CDM4 errors and any error generated |
248 // by CDM5 or later. | 261 // by CDM5 or later. |
249 client_->error(Client::MediaKeyErrorCodeUnknown, system_code); | 262 client_->error(Client::MediaKeyErrorCodeUnknown, system_code); |
250 break; | 263 break; |
251 } | 264 } |
252 } | 265 } |
253 | 266 |
254 void WebContentDecryptionModuleSessionImpl::SessionCreated( | 267 void WebContentDecryptionModuleSessionImpl::SessionCreated( |
ddorwin
2014/09/12 21:46:29
This will need to be renamed. It's OnSessionInitia
jrummell
2014/09/15 18:22:40
Done.
| |
255 uint32 result_index, | 268 uint32 result_index, |
256 const std::string& web_session_id) { | 269 const std::string& web_session_id) { |
257 blink::WebContentDecryptionModuleResult::SessionStatus status; | 270 blink::WebContentDecryptionModuleResult::SessionStatus status; |
258 | 271 |
259 // CDM will return NULL if the session to be loaded can't be found. | 272 // CDM will return NULL if the session to be loaded can't be found. |
260 if (web_session_id.empty()) { | 273 if (web_session_id.empty()) { |
261 status = blink::WebContentDecryptionModuleResult::SessionNotFound; | 274 status = blink::WebContentDecryptionModuleResult::SessionNotFound; |
ddorwin
2014/09/12 21:46:30
We should know that we called load() and check tha
jrummell
2014/09/15 18:22:40
load() hasn't been implemented here yet -- coming
| |
262 } else { | 275 } else { |
263 DCHECK(web_session_id_.empty()) | 276 DCHECK(web_session_id_.empty()) |
264 << "Session ID may not be changed once set."; | 277 << "Session ID may not be changed once set."; |
265 web_session_id_ = web_session_id; | 278 web_session_id_ = web_session_id; |
266 status = | 279 status = |
267 adapter_->RegisterSession(web_session_id_, | 280 adapter_->RegisterSession(web_session_id_, |
268 weak_ptr_factory_.GetWeakPtr()) | 281 weak_ptr_factory_.GetWeakPtr()) |
269 ? blink::WebContentDecryptionModuleResult::NewSession | 282 ? blink::WebContentDecryptionModuleResult::NewSession |
270 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists; | 283 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists; |
271 } | 284 } |
272 | 285 |
273 ResultMap::iterator it = outstanding_results_.find(result_index); | 286 outstanding_results_.CompleteWithSession(result_index, status); |
274 if (it != outstanding_results_.end()) { | |
275 blink::WebContentDecryptionModuleResult& result = it->second; | |
276 result.completeWithSession(status); | |
277 outstanding_results_.erase(result_index); | |
278 } | |
279 } | 287 } |
280 | 288 |
281 void WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased( | 289 void WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased( |
ddorwin
2014/09/12 21:46:30
This function needs a new name. OnPromiseResolved?
jrummell
2014/09/15 18:22:39
Done.
| |
282 uint32 result_index) { | 290 uint32 result_index) { |
283 ResultMap::iterator it = outstanding_results_.find(result_index); | 291 outstanding_results_.Complete(result_index); |
284 DCHECK(it != outstanding_results_.end()); | 292 } |
285 blink::WebContentDecryptionModuleResult& result = it->second; | 293 |
286 result.complete(); | 294 void WebContentDecryptionModuleSessionImpl::KeyIdsAvailable( |
287 outstanding_results_.erase(it); | 295 uint32 result_index, |
296 const media::KeyIdsVector& key_ids) { | |
297 outstanding_results_.CompleteWithKeyIds(result_index, key_ids); | |
288 } | 298 } |
289 | 299 |
290 void WebContentDecryptionModuleSessionImpl::SessionError( | 300 void WebContentDecryptionModuleSessionImpl::SessionError( |
291 uint32 result_index, | 301 uint32 result_index, |
292 media::MediaKeys::Exception exception_code, | 302 media::MediaKeys::Exception exception_code, |
293 uint32 system_code, | 303 uint32 system_code, |
294 const std::string& error_message) { | 304 const std::string& error_message) { |
295 ResultMap::iterator it = outstanding_results_.find(result_index); | 305 outstanding_results_.CompleteWithError( |
296 DCHECK(it != outstanding_results_.end()); | 306 result_index, exception_code, system_code, error_message); |
297 blink::WebContentDecryptionModuleResult& result = it->second; | |
298 result.completeWithError(ConvertException(exception_code), | |
299 system_code, | |
300 blink::WebString::fromUTF8(error_message)); | |
301 outstanding_results_.erase(it); | |
302 } | |
303 | |
304 uint32 WebContentDecryptionModuleSessionImpl::AddResult( | |
305 blink::WebContentDecryptionModuleResult result) { | |
306 uint32 result_index = next_available_result_index_++; | |
307 DCHECK(result_index != kReservedIndex); | |
308 outstanding_results_.insert(std::make_pair(result_index, result)); | |
309 return result_index; | |
310 } | 307 } |
311 | 308 |
312 } // namespace content | 309 } // namespace content |
OLD | NEW |