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

Side by Side Diff: content/renderer/media/android/proxy_media_keys.cc

Issue 265993002: Add Promises for EME (Chromium side) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cdm_promise template Created 6 years, 7 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/android/proxy_media_keys.h" 5 #include "content/renderer/media/android/proxy_media_keys.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "content/renderer/media/android/renderer_media_player_manager.h" 11 #include "content/renderer/media/android/renderer_media_player_manager.h"
12 #include "content/renderer/media/crypto/key_systems.h" 12 #include "content/renderer/media/crypto/key_systems.h"
13 13
14 namespace content { 14 namespace content {
15 15
16 int ProxyMediaKeys::next_cdm_id_ = 16 int ProxyMediaKeys::next_cdm_id_ =
17 RendererMediaPlayerManager::kInvalidCdmId + 1; 17 RendererMediaPlayerManager::kInvalidCdmId + 1;
18 18
19 scoped_ptr<ProxyMediaKeys> ProxyMediaKeys::Create( 19 scoped_ptr<ProxyMediaKeys> ProxyMediaKeys::Create(
20 const std::string& key_system, 20 const std::string& key_system,
21 const GURL& security_origin, 21 const GURL& security_origin,
22 RendererMediaPlayerManager* manager, 22 RendererMediaPlayerManager* manager,
23 const media::SessionCreatedCB& session_created_cb,
24 const media::SessionMessageCB& session_message_cb, 23 const media::SessionMessageCB& session_message_cb,
25 const media::SessionReadyCB& session_ready_cb, 24 const media::SessionReadyCB& session_ready_cb,
26 const media::SessionClosedCB& session_closed_cb, 25 const media::SessionClosedCB& session_closed_cb,
27 const media::SessionErrorCB& session_error_cb) { 26 const media::SessionErrorCB& session_error_cb) {
28 DCHECK(manager); 27 DCHECK(manager);
29 scoped_ptr<ProxyMediaKeys> proxy_media_keys( 28 scoped_ptr<ProxyMediaKeys> proxy_media_keys(
30 new ProxyMediaKeys(manager, 29 new ProxyMediaKeys(manager,
31 session_created_cb,
32 session_message_cb, 30 session_message_cb,
33 session_ready_cb, 31 session_ready_cb,
34 session_closed_cb, 32 session_closed_cb,
35 session_error_cb)); 33 session_error_cb));
36 proxy_media_keys->InitializeCdm(key_system, security_origin); 34 proxy_media_keys->InitializeCdm(key_system, security_origin);
37 return proxy_media_keys.Pass(); 35 return proxy_media_keys.Pass();
38 } 36 }
39 37
40 ProxyMediaKeys::~ProxyMediaKeys() { 38 ProxyMediaKeys::~ProxyMediaKeys() {
41 manager_->DestroyCdm(cdm_id_); 39 manager_->DestroyCdm(cdm_id_);
40
41 // Reject any outstanding promises.
42 for (PromiseMap::iterator it = session_id_to_promise_map_.begin();
43 it != session_id_to_promise_map_.end();
44 ++it) {
45 it->second->reject("AbortError", 0, "The operation was aborted.");
46 }
jrummell 2014/05/08 23:37:46 Need to do the second list of promises as well.
jrummell 2014/05/09 00:55:23 Done.
42 } 47 }
43 48
44 bool ProxyMediaKeys::CreateSession(uint32 session_id, 49 void ProxyMediaKeys::CreateSession(
45 const std::string& content_type, 50 const std::string& init_data_type,
46 const uint8* init_data, 51 const uint8* init_data,
47 int init_data_length) { 52 int init_data_length,
53 SessionType session_type,
54 scoped_ptr<media::CdmPromise<std::string> > promise) {
48 // TODO(xhwang): Move these checks up to blink and DCHECK here. 55 // TODO(xhwang): Move these checks up to blink and DCHECK here.
49 // See http://crbug.com/342510 56 // See http://crbug.com/342510
50 CdmHostMsg_CreateSession_ContentType session_type; 57 CdmHostMsg_CreateSession_ContentType create_session_content_type;
51 if (content_type == "audio/mp4" || content_type == "video/mp4") { 58 if (init_data_type == "audio/mp4" || init_data_type == "video/mp4") {
52 session_type = CREATE_SESSION_TYPE_MP4; 59 create_session_content_type = CREATE_SESSION_TYPE_MP4;
53 } else if (content_type == "audio/webm" || content_type == "video/webm") { 60 } else if (init_data_type == "audio/webm" || init_data_type == "video/webm") {
54 session_type = CREATE_SESSION_TYPE_WEBM; 61 create_session_content_type = CREATE_SESSION_TYPE_WEBM;
55 } else { 62 } else {
56 DLOG(ERROR) << "Unsupported EME CreateSession content type of " 63 DLOG(ERROR) << "Unsupported EME CreateSession content type of "
57 << content_type; 64 << init_data_type;
58 return false; 65 promise->reject(
66 MEDIA_KEYS_EXCEPTION_NOT_SUPPORTED_ERROR,
67 0,
68 "Unsupported EME CreateSession init data type of " + init_data_type);
69 return;
59 } 70 }
60 71
72 uint32 session_id = CreateSessionId();
73 RegisterSessionPromise(session_id, promise.Pass());
61 manager_->CreateSession( 74 manager_->CreateSession(
62 cdm_id_, 75 cdm_id_,
63 session_id, 76 session_id,
64 session_type, 77 create_session_content_type,
65 std::vector<uint8>(init_data, init_data + init_data_length)); 78 std::vector<uint8>(init_data, init_data + init_data_length));
66 return true;
67 } 79 }
68 80
69 void ProxyMediaKeys::LoadSession(uint32 session_id, 81 void ProxyMediaKeys::LoadSession(
70 const std::string& web_session_id) { 82 const std::string& web_session_id,
83 scoped_ptr<media::CdmPromise<std::string> > promise) {
71 // TODO(xhwang): Check key system and platform support for LoadSession in 84 // TODO(xhwang): Check key system and platform support for LoadSession in
72 // blink and add NOTREACHED() here. 85 // blink and add NOTREACHED() here.
73 DLOG(ERROR) << "ProxyMediaKeys doesn't support session loading."; 86 DLOG(ERROR) << "ProxyMediaKeys doesn't support session loading.";
74 OnSessionError(session_id, media::MediaKeys::kUnknownError, 0); 87 promise->reject(MEDIA_KEYS_EXCEPTION_NOT_SUPPORTED_ERROR,
88 0,
89 "LoadSession() is not implemented.");
75 } 90 }
76 91
77 void ProxyMediaKeys::UpdateSession(uint32 session_id, 92 void ProxyMediaKeys::UpdateSession(
78 const uint8* response, 93 const std::string& web_session_id,
79 int response_length) { 94 const uint8* response,
95 int response_length,
96 scoped_ptr<media::CdmPromise<void> > promise) {
97 uint32 session_id = LookupSessionId(web_session_id);
98 RegisterVoidPromise(session_id, promise.Pass());
80 manager_->UpdateSession( 99 manager_->UpdateSession(
81 cdm_id_, 100 cdm_id_,
82 session_id, 101 session_id,
83 std::vector<uint8>(response, response + response_length)); 102 std::vector<uint8>(response, response + response_length));
84 } 103 }
85 104
86 void ProxyMediaKeys::ReleaseSession(uint32 session_id) { 105 void ProxyMediaKeys::ReleaseSession(
106 const std::string& web_session_id,
107 scoped_ptr<media::CdmPromise<void> > promise) {
108 uint32 session_id = LookupSessionId(web_session_id);
109 RegisterVoidPromise(session_id, promise.Pass());
87 manager_->ReleaseSession(cdm_id_, session_id); 110 manager_->ReleaseSession(cdm_id_, session_id);
88 } 111 }
89 112
90 void ProxyMediaKeys::OnSessionCreated(uint32 session_id, 113 void ProxyMediaKeys::OnSessionCreated(uint32 session_id,
91 const std::string& web_session_id) { 114 const std::string& web_session_id) {
92 session_created_cb_.Run(session_id, web_session_id); 115 AssignWebSessionId(session_id, web_session_id);
116 scoped_ptr<media::CdmPromise<std::string> > promise =
117 RetrieveSessionPromise(session_id);
118 promise->resolve(web_session_id);
93 } 119 }
94 120
95 void ProxyMediaKeys::OnSessionMessage(uint32 session_id, 121 void ProxyMediaKeys::OnSessionMessage(uint32 session_id,
96 const std::vector<uint8>& message, 122 const std::vector<uint8>& message,
97 const std::string& destination_url) { 123 const std::string& destination_url) {
98 session_message_cb_.Run(session_id, message, destination_url); 124 session_message_cb_.Run(
125 LookupWebSessionId(session_id), message, destination_url);
99 } 126 }
100 127
101 void ProxyMediaKeys::OnSessionReady(uint32 session_id) { 128 void ProxyMediaKeys::OnSessionReady(uint32 session_id) {
102 session_ready_cb_.Run(session_id); 129 std::string web_session_id = LookupWebSessionId(session_id);
130 scoped_ptr<media::CdmPromise<void> > promise =
131 RetrieveVoidPromise(session_id);
132 if (promise) {
133 promise->resolve();
134 } else {
135 // Still needed for keyadded.
136 session_ready_cb_.Run(web_session_id);
137 }
103 } 138 }
104 139
105 void ProxyMediaKeys::OnSessionClosed(uint32 session_id) { 140 void ProxyMediaKeys::OnSessionClosed(uint32 session_id) {
106 session_closed_cb_.Run(session_id); 141 std::string web_session_id = LookupWebSessionId(session_id);
142 DropWebSessionId(web_session_id);
143 scoped_ptr<media::CdmPromise<void> > promise =
144 RetrieveVoidPromise(session_id);
145 if (promise) {
146 promise->resolve();
147 } else {
148 // It is possible for the CDM to close a session independent of a
149 // Release() request.
150 session_closed_cb_.Run(web_session_id);
151 }
107 } 152 }
108 153
109 void ProxyMediaKeys::OnSessionError(uint32 session_id, 154 void ProxyMediaKeys::OnSessionError(uint32 session_id,
110 media::MediaKeys::KeyError error_code, 155 media::MediaKeys::KeyError error_code,
111 uint32 system_code) { 156 uint32 system_code) {
112 session_error_cb_.Run(session_id, error_code, system_code); 157 std::string web_session_id = LookupWebSessionId(session_id);
158 scoped_ptr<media::CdmPromise<std::string> > promise =
159 RetrieveSessionPromise(session_id);
160 if (promise) {
161 promise->reject("InvalidStateError", 0, std::string());
162 } else {
163 // Maybe an error for other set of promises.
164 scoped_ptr<media::CdmPromise<void> > promise2 =
165 RetrieveVoidPromise(session_id);
166 if (promise2) {
167 promise2->reject("InvalidStateError", 0, std::string());
168 } else {
169 // Errors generally happen in response to a request, but it is possible
170 // for something bad to happen in the CDM and it needs to tell the client.
171 session_error_cb_.Run(
172 web_session_id, "InvalidStateError", system_code, std::string());
173 }
174 }
113 } 175 }
114 176
115 int ProxyMediaKeys::GetCdmId() const { 177 int ProxyMediaKeys::GetCdmId() const {
116 return cdm_id_; 178 return cdm_id_;
117 } 179 }
118 180
119 ProxyMediaKeys::ProxyMediaKeys( 181 ProxyMediaKeys::ProxyMediaKeys(
120 RendererMediaPlayerManager* manager, 182 RendererMediaPlayerManager* manager,
121 const media::SessionCreatedCB& session_created_cb,
122 const media::SessionMessageCB& session_message_cb, 183 const media::SessionMessageCB& session_message_cb,
123 const media::SessionReadyCB& session_ready_cb, 184 const media::SessionReadyCB& session_ready_cb,
124 const media::SessionClosedCB& session_closed_cb, 185 const media::SessionClosedCB& session_closed_cb,
125 const media::SessionErrorCB& session_error_cb) 186 const media::SessionErrorCB& session_error_cb)
126 : manager_(manager), 187 : manager_(manager),
127 cdm_id_(next_cdm_id_++), 188 cdm_id_(next_cdm_id_++),
128 session_created_cb_(session_created_cb),
129 session_message_cb_(session_message_cb), 189 session_message_cb_(session_message_cb),
130 session_ready_cb_(session_ready_cb), 190 session_ready_cb_(session_ready_cb),
131 session_closed_cb_(session_closed_cb), 191 session_closed_cb_(session_closed_cb),
132 session_error_cb_(session_error_cb) { 192 session_error_cb_(session_error_cb),
193 next_session_id_(1) {
133 } 194 }
134 195
135 void ProxyMediaKeys::InitializeCdm(const std::string& key_system, 196 void ProxyMediaKeys::InitializeCdm(const std::string& key_system,
136 const GURL& security_origin) { 197 const GURL& security_origin) {
137 manager_->InitializeCdm(cdm_id_, this, key_system, security_origin); 198 manager_->InitializeCdm(cdm_id_, this, key_system, security_origin);
138 } 199 }
139 200
201 uint32_t ProxyMediaKeys::CreateSessionId() {
202 return next_session_id_++;
203 }
204
205 void ProxyMediaKeys::AssignWebSessionId(uint32_t session_id,
206 const std::string& web_session_id) {
207 web_session_to_session_id_map_.insert(
208 std::make_pair(web_session_id, session_id));
209 }
210
211 uint32_t ProxyMediaKeys::LookupSessionId(const std::string& web_session_id) {
212 return web_session_to_session_id_map_.find(web_session_id)->second;
213 }
214
215 std::string ProxyMediaKeys::LookupWebSessionId(uint32_t session_id) {
216 for (SessionMap::iterator it = web_session_to_session_id_map_.begin();
217 it != web_session_to_session_id_map_.end();
218 ++it) {
219 if (it->second == session_id)
220 return it->first;
221 }
222 // Possible to get an error creating a session, so no |web_session_id|
223 // available.
224 return std::string();
225 }
226
227 void ProxyMediaKeys::DropWebSessionId(std::string web_session_id) {
228 web_session_to_session_id_map_.erase(web_session_id);
229 }
230
231 void ProxyMediaKeys::RegisterVoidPromise(
232 uint32_t session_id,
233 scoped_ptr<media::CdmPromise<void> > promise) {
234 // Should only be one promise outstanding for any |session_id|.
235 DCHECK(session_id_to_promise_map_.find(session_id) ==
236 session_id_to_promise_map_.end());
237 session_id_to_promise_map_.insert(
238 std::make_pair(session_id, promise.release()));
239 }
240
241 scoped_ptr<media::CdmPromise<void> > ProxyMediaKeys::RetrieveVoidPromise(
242 uint32_t session_id) {
243 PromiseMap::iterator it = session_id_to_promise_map_.find(session_id);
244 // May not be a promise associated with this session for asynchronous events.
245 if (it == session_id_to_promise_map_.end())
246 return scoped_ptr<media::CdmPromise<void> >();
247 scoped_ptr<media::CdmPromise<void> > result(it->second);
248 session_id_to_promise_map_.erase(it);
249 return result.Pass();
250 }
251
252 void ProxyMediaKeys::RegisterSessionPromise(
253 uint32_t session_id,
254 scoped_ptr<media::CdmPromise<std::string> > promise) {
255 // Should only be one promise outstanding for any |session_id|.
256 DCHECK(session_id_to_new_session_promise_map_.find(session_id) ==
257 session_id_to_new_session_promise_map_.end());
258 session_id_to_new_session_promise_map_.insert(
259 std::make_pair(session_id, promise.release()));
260 }
261
262 scoped_ptr<media::CdmPromise<std::string> >
263 ProxyMediaKeys::RetrieveSessionPromise(uint32_t session_id) {
264 PromiseMap::iterator it =
265 session_id_to_new_session_promise_map_.find(session_id);
266 // May not be a promise associated with this session for asynchronous events.
267 if (it == session_id_to_new_session_promise_map_.end())
268 return scoped_ptr<media::CdmPromise<std::string> >();
269 scoped_ptr<media::CdmPromise<std::string> > result(it->second);
270 session_id_to_new_session_promise_map_.erase(it);
271 return result.Pass();
272 }
273
140 } // namespace content 274 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698