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

Side by Side Diff: content/renderer/media/webcontentdecryptionmodulesession_impl.cc

Issue 555223004: Update MediaKeys interface for EME (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: BlinkCdmPromiseTemplate Created 6 years, 2 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 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 "content/renderer/media/webcontentdecryptionmoduleresult_helper.h"
13 #include "media/base/cdm_promise.h" 14 #include "media/base/cdm_promise.h"
14 #include "third_party/WebKit/public/platform/WebURL.h" 15 #include "third_party/WebKit/public/platform/WebURL.h"
15 16
16 namespace content { 17 namespace content {
17 18
18 const char kCreateSessionUMAName[] = "CreateSession"; 19 const char kCreateSessionUMAName[] = "CreateSession";
19 20
20 // For backwards compatibility with blink not using 21 typedef base::Callback<blink::WebContentDecryptionModuleResult::SessionStatus(
21 // WebContentDecryptionModuleResult, reserve an index for |outstanding_results_| 22 const std::string& web_session_id)> SessionInitializedCB;
22 // that will not be used when adding a WebContentDecryptionModuleResult.
23 // TODO(jrummell): Remove once blink always uses
24 // WebContentDecryptionModuleResult.
25 const uint32 kReservedIndex = 0;
26 23
27 static blink::WebContentDecryptionModuleException ConvertException( 24 class WebNewSessionCdmPromise : public BlinkCdmPromiseTemplate<std::string> {
28 media::MediaKeys::Exception exception_code) { 25 public:
29 switch (exception_code) { 26 WebNewSessionCdmPromise(blink::WebContentDecryptionModuleResult result,
30 case media::MediaKeys::NOT_SUPPORTED_ERROR: 27 std::string uma_name,
31 return blink::WebContentDecryptionModuleExceptionNotSupportedError; 28 const SessionInitializedCB& new_session_created_cb)
32 case media::MediaKeys::INVALID_STATE_ERROR: 29 : BlinkCdmPromiseTemplate<std::string>(result, uma_name),
33 return blink::WebContentDecryptionModuleExceptionInvalidStateError; 30 new_session_created_cb_(new_session_created_cb) {}
34 case media::MediaKeys::INVALID_ACCESS_ERROR: 31
35 return blink::WebContentDecryptionModuleExceptionInvalidAccessError; 32 protected:
36 case media::MediaKeys::QUOTA_EXCEEDED_ERROR: 33 virtual void OnResolve(const std::string& web_session_id) OVERRIDE {
37 return blink::WebContentDecryptionModuleExceptionQuotaExceededError; 34 blink::WebContentDecryptionModuleResult::SessionStatus status =
38 case media::MediaKeys::UNKNOWN_ERROR: 35 new_session_created_cb_.Run(web_session_id);
39 return blink::WebContentDecryptionModuleExceptionUnknownError; 36 webCDMResult_.completeWithSession(status);
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 } 37 }
48 } 38
39 private:
40 SessionInitializedCB new_session_created_cb_;
41 };
49 42
50 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( 43 WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
51 const scoped_refptr<CdmSessionAdapter>& adapter) 44 const scoped_refptr<CdmSessionAdapter>& adapter)
52 : adapter_(adapter), 45 : adapter_(adapter),
53 is_closed_(false), 46 is_closed_(false),
54 next_available_result_index_(1),
55 weak_ptr_factory_(this) { 47 weak_ptr_factory_(this) {
56 } 48 }
57 49
58 WebContentDecryptionModuleSessionImpl:: 50 WebContentDecryptionModuleSessionImpl::
59 ~WebContentDecryptionModuleSessionImpl() { 51 ~WebContentDecryptionModuleSessionImpl() {
60 if (!web_session_id_.empty()) 52 if (!web_session_id_.empty())
61 adapter_->RemoveSession(web_session_id_); 53 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 } 54 }
77 55
78 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) { 56 void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) {
79 client_ = client; 57 client_ = client;
80 } 58 }
81 59
82 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { 60 blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
83 return blink::WebString::fromUTF8(web_session_id_); 61 return blink::WebString::fromUTF8(web_session_id_);
84 } 62 }
85 63
86 void WebContentDecryptionModuleSessionImpl::initializeNewSession( 64 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
87 const blink::WebString& init_data_type, 65 const blink::WebString& init_data_type,
88 const uint8* init_data, 66 const uint8* init_data,
89 size_t init_data_length) { 67 size_t init_data_length) {
90 DCHECK(base::IsStringASCII(init_data_type)); 68 NOTREACHED();
91
92 std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type);
93 DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos)
94 << "init_data_type '" << init_data_type_as_ascii
95 << "' may be a MIME type";
96
97 // Attempt to translate content types.
98 // TODO(sandersd): Remove once tests stop using content types.
99 // http://crbug.com/385874
100 std::string content_type = base::StringToLowerASCII(init_data_type_as_ascii);
101 if (content_type == "audio/mp4" || content_type == "video/mp4") {
102 init_data_type_as_ascii = "cenc";
103 } else if (content_type == "audio/webm" || content_type == "video/webm") {
104 init_data_type_as_ascii = "webm";
105 }
106
107 scoped_ptr<media::NewSessionCdmPromise> promise(
108 new media::NewSessionCdmPromise(
109 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionCreated,
110 weak_ptr_factory_.GetWeakPtr(),
111 kReservedIndex),
112 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
113 weak_ptr_factory_.GetWeakPtr()),
114 adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName));
115 adapter_->InitializeNewSession(init_data_type_as_ascii,
116 init_data,
117 init_data_length,
118 media::MediaKeys::TEMPORARY_SESSION,
119 promise.Pass());
120 } 69 }
121 70
122 void WebContentDecryptionModuleSessionImpl::update(const uint8* response, 71 void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
123 size_t response_length) { 72 size_t response_length) {
124 DCHECK(response); 73 NOTREACHED();
125 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
126 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionReady,
127 weak_ptr_factory_.GetWeakPtr()),
128 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
129 weak_ptr_factory_.GetWeakPtr())));
130 adapter_->UpdateSession(
131 web_session_id_, response, response_length, promise.Pass());
132 } 74 }
133 75
134 void WebContentDecryptionModuleSessionImpl::release() { 76 void WebContentDecryptionModuleSessionImpl::release() {
135 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( 77 NOTREACHED();
136 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionClosed,
137 weak_ptr_factory_.GetWeakPtr()),
138 base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
139 weak_ptr_factory_.GetWeakPtr())));
140 adapter_->ReleaseSession(web_session_id_, promise.Pass());
141 } 78 }
142 79
143 void WebContentDecryptionModuleSessionImpl::initializeNewSession( 80 void WebContentDecryptionModuleSessionImpl::initializeNewSession(
144 const blink::WebString& init_data_type, 81 const blink::WebString& init_data_type,
145 const uint8* init_data, 82 const uint8* init_data,
146 size_t init_data_length, 83 size_t init_data_length,
147 const blink::WebString& session_type, 84 const blink::WebString& session_type,
148 blink::WebContentDecryptionModuleResult result) { 85 blink::WebContentDecryptionModuleResult result) {
149 uint32 result_index = AddResult(result);
150 86
151 // TODO(ddorwin): Guard against this in supported types check and remove this. 87 // TODO(ddorwin): Guard against this in supported types check and remove this.
152 // Chromium only supports ASCII MIME types. 88 // Chromium only supports ASCII MIME types.
153 if (!base::IsStringASCII(init_data_type)) { 89 if (!base::IsStringASCII(init_data_type)) {
154 NOTREACHED(); 90 NOTREACHED();
155 SessionError(result_index, 91 std::string message = "The initialization data type " +
156 media::MediaKeys::NOT_SUPPORTED_ERROR, 92 init_data_type.utf8() +
157 0, 93 " is not supported by the key system.";
158 "The initialization data type " + init_data_type.utf8() + 94 result.completeWithError(
159 " is not supported by the key system."); 95 blink::WebContentDecryptionModuleExceptionNotSupportedError,
96 0,
97 blink::WebString::fromUTF8(message));
160 return; 98 return;
161 } 99 }
162 100
163 std::string init_data_type_as_ascii = base::UTF16ToASCII(init_data_type); 101 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) 102 DLOG_IF(WARNING, init_data_type_as_ascii.find('/') != std::string::npos)
165 << "init_data_type '" << init_data_type_as_ascii 103 << "init_data_type '" << init_data_type_as_ascii
166 << "' may be a MIME type"; 104 << "' may be a MIME type";
167 105
168 scoped_ptr<media::NewSessionCdmPromise> promise( 106 scoped_ptr<media::NewSessionCdmPromise> promise =
169 new media::NewSessionCdmPromise( 107 make_scoped_ptr<media::NewSessionCdmPromise>(new WebNewSessionCdmPromise(
ddorwin 2014/09/23 23:14:21 ditto. here and below. WDYT?
jrummell 2014/09/24 00:49:32 Done.
170 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionCreated, 108 result,
171 weak_ptr_factory_.GetWeakPtr(), 109 adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName,
172 result_index), 110 base::Bind(
173 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError, 111 &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
174 weak_ptr_factory_.GetWeakPtr(), 112 base::Unretained(this))));
175 result_index),
176 adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName));
177 adapter_->InitializeNewSession(init_data_type_as_ascii, 113 adapter_->InitializeNewSession(init_data_type_as_ascii,
178 init_data, 114 init_data,
179 init_data_length, 115 init_data_length,
180 media::MediaKeys::TEMPORARY_SESSION, 116 media::MediaKeys::TEMPORARY_SESSION,
181 promise.Pass()); 117 promise.Pass());
182 } 118 }
183 119
184 void WebContentDecryptionModuleSessionImpl::update( 120 void WebContentDecryptionModuleSessionImpl::update(
185 const uint8* response, 121 const uint8* response,
186 size_t response_length, 122 size_t response_length,
187 blink::WebContentDecryptionModuleResult result) { 123 blink::WebContentDecryptionModuleResult result) {
188 DCHECK(response); 124 DCHECK(response);
189 uint32 result_index = AddResult(result); 125 DCHECK(!web_session_id_.empty());
190 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise( 126 scoped_ptr<media::SimpleCdmPromise> promise =
191 base::Bind( 127 make_scoped_ptr<media::SimpleCdmPromise>(
192 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased, 128 new BlinkCdmPromiseTemplate<void>(result));
ddorwin 2014/09/23 23:14:21 Feel free to typedef this one. :)
jrummell 2014/09/24 00:49:32 Not sure there is much benefit now that it is inli
ddorwin 2014/09/24 17:37:46 Agreed - it was mainly for readability.
193 weak_ptr_factory_.GetWeakPtr(),
194 result_index),
195 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError,
196 weak_ptr_factory_.GetWeakPtr(),
197 result_index)));
198 adapter_->UpdateSession( 129 adapter_->UpdateSession(
199 web_session_id_, response, response_length, promise.Pass()); 130 web_session_id_, response, response_length, promise.Pass());
200 } 131 }
201 132
133 void WebContentDecryptionModuleSessionImpl::close(
134 blink::WebContentDecryptionModuleResult result) {
135 DCHECK(!web_session_id_.empty());
136 scoped_ptr<media::SimpleCdmPromise> promise =
137 make_scoped_ptr<media::SimpleCdmPromise>(
138 new BlinkCdmPromiseTemplate<void>(result));
139 adapter_->CloseSession(web_session_id_, promise.Pass());
140 }
141
142 void WebContentDecryptionModuleSessionImpl::remove(
143 blink::WebContentDecryptionModuleResult result) {
144 DCHECK(!web_session_id_.empty());
145 scoped_ptr<media::SimpleCdmPromise> promise =
146 make_scoped_ptr<media::SimpleCdmPromise>(
147 new BlinkCdmPromiseTemplate<void>(result));
148 adapter_->RemoveSession(web_session_id_, promise.Pass());
149 }
150
151 void WebContentDecryptionModuleSessionImpl::getUsableKeyIds(
152 blink::WebContentDecryptionModuleResult result) {
153 DCHECK(!web_session_id_.empty());
154 scoped_ptr<media::KeyIdsPromise> promise =
155 make_scoped_ptr<media::KeyIdsPromise>(
156 new BlinkCdmPromiseTemplate<media::KeyIdsVector>(result));
157 adapter_->GetUsableKeyIds(web_session_id_, promise.Pass());
158 }
159
202 void WebContentDecryptionModuleSessionImpl::release( 160 void WebContentDecryptionModuleSessionImpl::release(
203 blink::WebContentDecryptionModuleResult result) { 161 blink::WebContentDecryptionModuleResult result) {
204 uint32 result_index = AddResult(result); 162 close(result);
205 scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
206 base::Bind(
207 &WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased,
208 weak_ptr_factory_.GetWeakPtr(),
209 result_index),
210 base::Bind(&WebContentDecryptionModuleSessionImpl::SessionError,
211 weak_ptr_factory_.GetWeakPtr(),
212 result_index)));
213 adapter_->ReleaseSession(web_session_id_, promise.Pass());
214 } 163 }
215 164
216 void WebContentDecryptionModuleSessionImpl::OnSessionMessage( 165 void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
217 const std::vector<uint8>& message, 166 const std::vector<uint8>& message,
218 const GURL& destination_url) { 167 const GURL& destination_url) {
219 DCHECK(client_) << "Client not set before message event"; 168 DCHECK(client_) << "Client not set before message event";
220 client_->message( 169 client_->message(
221 message.empty() ? NULL : &message[0], message.size(), destination_url); 170 message.empty() ? NULL : &message[0], message.size(), destination_url);
222 } 171 }
223 172
173 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
174 bool has_additional_usable_key) {
175 // TODO(jrummell): Update this once Blink client supports this.
176 }
177
178 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationChange(
179 double new_expiry_time) {
180 // TODO(jrummell): Update this once Blink client supports this.
181 }
182
224 void WebContentDecryptionModuleSessionImpl::OnSessionReady() { 183 void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
225 client_->ready(); 184 client_->ready();
226 } 185 }
227 186
228 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() { 187 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
229 if (!is_closed_) { 188 if (!is_closed_) {
230 is_closed_ = true; 189 is_closed_ = true;
231 client_->close(); 190 client_->close();
232 } 191 }
233 } 192 }
(...skipping 10 matching lines...) Expand all
244 client_->error(Client::MediaKeyErrorCodeClient, system_code); 203 client_->error(Client::MediaKeyErrorCodeClient, system_code);
245 break; 204 break;
246 default: 205 default:
247 // This will include all other CDM4 errors and any error generated 206 // This will include all other CDM4 errors and any error generated
248 // by CDM5 or later. 207 // by CDM5 or later.
249 client_->error(Client::MediaKeyErrorCodeUnknown, system_code); 208 client_->error(Client::MediaKeyErrorCodeUnknown, system_code);
250 break; 209 break;
251 } 210 }
252 } 211 }
253 212
254 void WebContentDecryptionModuleSessionImpl::SessionCreated( 213 blink::WebContentDecryptionModuleResult::SessionStatus
255 uint32 result_index, 214 WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
256 const std::string& web_session_id) { 215 const std::string& web_session_id) {
257 blink::WebContentDecryptionModuleResult::SessionStatus status; 216 // CDM will return NULL if the session to be loaded can't be found.
217 if (web_session_id.empty())
218 return blink::WebContentDecryptionModuleResult::SessionNotFound;
258 219
259 // CDM will return NULL if the session to be loaded can't be found. 220 DCHECK(web_session_id_.empty()) << "Session ID may not be changed once set.";
260 if (web_session_id.empty()) { 221 web_session_id_ = web_session_id;
261 status = blink::WebContentDecryptionModuleResult::SessionNotFound; 222 return adapter_->RegisterSession(web_session_id_,
262 } else { 223 weak_ptr_factory_.GetWeakPtr())
263 DCHECK(web_session_id_.empty()) 224 ? blink::WebContentDecryptionModuleResult::NewSession
264 << "Session ID may not be changed once set."; 225 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
265 web_session_id_ = web_session_id;
266 status =
267 adapter_->RegisterSession(web_session_id_,
268 weak_ptr_factory_.GetWeakPtr())
269 ? blink::WebContentDecryptionModuleResult::NewSession
270 : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
271 }
272
273 ResultMap::iterator it = outstanding_results_.find(result_index);
274 if (it != outstanding_results_.end()) {
275 blink::WebContentDecryptionModuleResult& result = it->second;
276 result.completeWithSession(status);
277 outstanding_results_.erase(result_index);
278 }
279 }
280
281 void WebContentDecryptionModuleSessionImpl::SessionUpdatedOrReleased(
282 uint32 result_index) {
283 ResultMap::iterator it = outstanding_results_.find(result_index);
284 DCHECK(it != outstanding_results_.end());
285 blink::WebContentDecryptionModuleResult& result = it->second;
286 result.complete();
287 outstanding_results_.erase(it);
288 }
289
290 void WebContentDecryptionModuleSessionImpl::SessionError(
291 uint32 result_index,
292 media::MediaKeys::Exception exception_code,
293 uint32 system_code,
294 const std::string& error_message) {
295 ResultMap::iterator it = outstanding_results_.find(result_index);
296 DCHECK(it != outstanding_results_.end());
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 } 226 }
311 227
312 } // namespace content 228 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698