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/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_); |
xhwang
2014/05/05 20:46:42
We should check session_id_to_promise_map_, reject
jrummell
2014/05/08 23:37:45
Done.
| |
42 } | 40 } |
43 | 41 |
44 bool ProxyMediaKeys::CreateSession(uint32 session_id, | 42 void ProxyMediaKeys::CreateSession( |
prabhur
2014/05/05 17:57:29
Do we need a bool return value as before to indica
jrummell
2014/05/08 23:37:45
Nope. The promise will be resolved or rejected, po
| |
45 const std::string& content_type, | 43 const std::string& init_data_type, |
46 const uint8* init_data, | 44 const uint8* init_data, |
47 int init_data_length) { | 45 int init_data_length, |
46 SessionType session_type, | |
47 scoped_ptr<media::MediaKeysSessionPromise> promise) { | |
48 // TODO(xhwang): Move these checks up to blink and DCHECK here. | 48 // TODO(xhwang): Move these checks up to blink and DCHECK here. |
49 // See http://crbug.com/342510 | 49 // See http://crbug.com/342510 |
50 CdmHostMsg_CreateSession_ContentType session_type; | 50 CdmHostMsg_CreateSession_ContentType session_content_type; |
51 if (content_type == "audio/mp4" || content_type == "video/mp4") { | 51 if (init_data_type == "audio/mp4" || init_data_type == "video/mp4") { |
prabhur
2014/05/05 17:57:29
Is the value expected to be always lower case? i.e
jrummell
2014/05/08 23:37:45
The spec states "Initialization data type strings
| |
52 session_type = CREATE_SESSION_TYPE_MP4; | 52 session_content_type = CREATE_SESSION_TYPE_MP4; |
xhwang
2014/05/05 20:46:42
I don't feel "session_content_type" is an improvem
jrummell
2014/05/08 23:37:45
Done.
| |
53 } else if (content_type == "audio/webm" || content_type == "video/webm") { | 53 } else if (init_data_type == "audio/webm" || init_data_type == "video/webm") { |
54 session_type = CREATE_SESSION_TYPE_WEBM; | 54 session_content_type = CREATE_SESSION_TYPE_WEBM; |
55 } else { | 55 } else { |
56 DLOG(ERROR) << "Unsupported EME CreateSession content type of " | 56 DLOG(ERROR) << "Unsupported EME CreateSession content type of " |
57 << content_type; | 57 << init_data_type; |
58 return false; | 58 promise->reject( |
59 "NotSupportedError", | |
60 0, | |
61 "Unsupported EME CreateSession content type of " + init_data_type); | |
xhwang
2014/05/05 20:46:42
s/content/init data/?
jrummell
2014/05/08 23:37:45
Done.
| |
62 promise.reset(); | |
xhwang
2014/05/05 20:46:42
No need to reset because it'll go out of scope?
jrummell
2014/05/08 23:37:45
Done.
| |
63 return; | |
59 } | 64 } |
60 | 65 |
66 uint32 session_id = CreateSessionId(); | |
67 AddPromise(session_id, promise.Pass()); | |
61 manager_->CreateSession( | 68 manager_->CreateSession( |
62 cdm_id_, | 69 cdm_id_, |
63 session_id, | 70 session_id, |
64 session_type, | 71 session_content_type, |
65 std::vector<uint8>(init_data, init_data + init_data_length)); | 72 std::vector<uint8>(init_data, init_data + init_data_length)); |
66 return true; | |
67 } | 73 } |
68 | 74 |
69 void ProxyMediaKeys::LoadSession(uint32 session_id, | 75 void ProxyMediaKeys::LoadSession( |
70 const std::string& web_session_id) { | 76 const std::string& web_session_id, |
77 scoped_ptr<media::MediaKeysSessionPromise> promise) { | |
71 // TODO(xhwang): Check key system and platform support for LoadSession in | 78 // TODO(xhwang): Check key system and platform support for LoadSession in |
72 // blink and add NOTREACHED() here. | 79 // blink and add NOTREACHED() here. |
73 DLOG(ERROR) << "ProxyMediaKeys doesn't support session loading."; | 80 DLOG(ERROR) << "ProxyMediaKeys doesn't support session loading."; |
74 OnSessionError(session_id, media::MediaKeys::kUnknownError, 0); | 81 promise->reject("NotSupportedError", 0, "LoadSession() is not implemented."); |
xhwang
2014/05/05 20:46:42
Hmm, I feel we are exposing Blink details to chrom
| |
82 promise.reset(); | |
xhwang
2014/05/05 20:46:42
ditto about reset.
jrummell
2014/05/08 23:37:45
Done.
| |
75 } | 83 } |
76 | 84 |
77 void ProxyMediaKeys::UpdateSession(uint32 session_id, | 85 void ProxyMediaKeys::UpdateSession( |
78 const uint8* response, | 86 const std::string& web_session_id, |
79 int response_length) { | 87 const uint8* response, |
88 int response_length, | |
89 scoped_ptr<media::MediaKeysSessionPromise> promise) { | |
90 uint32 session_id = LookupSessionId(web_session_id); | |
91 AddPromise(session_id, promise.Pass()); | |
80 manager_->UpdateSession( | 92 manager_->UpdateSession( |
81 cdm_id_, | 93 cdm_id_, |
82 session_id, | 94 session_id, |
83 std::vector<uint8>(response, response + response_length)); | 95 std::vector<uint8>(response, response + response_length)); |
84 } | 96 } |
85 | 97 |
86 void ProxyMediaKeys::ReleaseSession(uint32 session_id) { | 98 void ProxyMediaKeys::ReleaseSession( |
99 const std::string& web_session_id, | |
100 scoped_ptr<media::MediaKeysSessionPromise> promise) { | |
101 uint32 session_id = LookupSessionId(web_session_id); | |
102 AddPromise(session_id, promise.Pass()); | |
87 manager_->ReleaseSession(cdm_id_, session_id); | 103 manager_->ReleaseSession(cdm_id_, session_id); |
88 } | 104 } |
89 | 105 |
90 void ProxyMediaKeys::OnSessionCreated(uint32 session_id, | 106 void ProxyMediaKeys::OnSessionCreated(uint32 session_id, |
91 const std::string& web_session_id) { | 107 const std::string& web_session_id) { |
92 session_created_cb_.Run(session_id, web_session_id); | 108 AssignWebSessionId(session_id, web_session_id); |
109 scoped_ptr<media::MediaKeysSessionPromise> promise = | |
110 LookupPromise(session_id); | |
111 promise->resolve(web_session_id); | |
112 promise.reset(); | |
93 } | 113 } |
94 | 114 |
95 void ProxyMediaKeys::OnSessionMessage(uint32 session_id, | 115 void ProxyMediaKeys::OnSessionMessage(uint32 session_id, |
96 const std::vector<uint8>& message, | 116 const std::vector<uint8>& message, |
97 const std::string& destination_url) { | 117 const std::string& destination_url) { |
98 session_message_cb_.Run(session_id, message, destination_url); | 118 session_message_cb_.Run( |
119 LookupWebSessionId(session_id), message, destination_url); | |
99 } | 120 } |
100 | 121 |
101 void ProxyMediaKeys::OnSessionReady(uint32 session_id) { | 122 void ProxyMediaKeys::OnSessionReady(uint32 session_id) { |
102 session_ready_cb_.Run(session_id); | 123 std::string web_session_id = LookupWebSessionId(session_id); |
124 scoped_ptr<media::MediaKeysSessionPromise> promise = | |
125 LookupPromise(session_id); | |
126 if (promise) { | |
127 promise->resolve(); | |
128 promise.reset(); | |
129 } else { | |
130 session_ready_cb_.Run(web_session_id); | |
xhwang
2014/05/05 20:46:42
OnSessionReady() should always be the result of an
jrummell
2014/05/08 23:37:45
Added comment.
| |
131 } | |
103 } | 132 } |
104 | 133 |
105 void ProxyMediaKeys::OnSessionClosed(uint32 session_id) { | 134 void ProxyMediaKeys::OnSessionClosed(uint32 session_id) { |
106 session_closed_cb_.Run(session_id); | 135 std::string web_session_id = LookupWebSessionId(session_id); |
136 DropWebSessionId(web_session_id); | |
137 scoped_ptr<media::MediaKeysSessionPromise> promise = | |
138 LookupPromise(session_id); | |
139 if (promise) { | |
140 promise->resolve(); | |
141 promise.reset(); | |
142 } else { | |
143 session_closed_cb_.Run(web_session_id); | |
144 } | |
xhwang
2014/05/05 20:46:42
We need to comment why the "else" is a legit case
jrummell
2014/05/08 23:37:45
Done.
| |
107 } | 145 } |
108 | 146 |
109 void ProxyMediaKeys::OnSessionError(uint32 session_id, | 147 void ProxyMediaKeys::OnSessionError(uint32 session_id, |
110 media::MediaKeys::KeyError error_code, | 148 media::MediaKeys::KeyError error_code, |
111 uint32 system_code) { | 149 uint32 system_code) { |
112 session_error_cb_.Run(session_id, error_code, system_code); | 150 std::string web_session_id = LookupWebSessionId(session_id); |
151 scoped_ptr<media::MediaKeysSessionPromise> promise = | |
152 LookupPromise(session_id); | |
153 if (promise) { | |
154 promise->reject("InvalidStateError", 0, std::string()); | |
155 promise.reset(); | |
156 } else { | |
157 session_error_cb_.Run( | |
158 web_session_id, "InvalidStateError", system_code, std::string()); | |
159 } | |
xhwang
2014/05/05 20:46:42
ditto about adding a comment, that the sessionErro
jrummell
2014/05/08 23:37:45
Done.
| |
113 } | 160 } |
114 | 161 |
115 int ProxyMediaKeys::GetCdmId() const { | 162 int ProxyMediaKeys::GetCdmId() const { |
116 return cdm_id_; | 163 return cdm_id_; |
117 } | 164 } |
118 | 165 |
119 ProxyMediaKeys::ProxyMediaKeys( | 166 ProxyMediaKeys::ProxyMediaKeys( |
120 RendererMediaPlayerManager* manager, | 167 RendererMediaPlayerManager* manager, |
121 const media::SessionCreatedCB& session_created_cb, | |
122 const media::SessionMessageCB& session_message_cb, | 168 const media::SessionMessageCB& session_message_cb, |
123 const media::SessionReadyCB& session_ready_cb, | 169 const media::SessionReadyCB& session_ready_cb, |
124 const media::SessionClosedCB& session_closed_cb, | 170 const media::SessionClosedCB& session_closed_cb, |
125 const media::SessionErrorCB& session_error_cb) | 171 const media::SessionErrorCB& session_error_cb) |
126 : manager_(manager), | 172 : manager_(manager), |
127 cdm_id_(next_cdm_id_++), | 173 cdm_id_(next_cdm_id_++), |
128 session_created_cb_(session_created_cb), | |
129 session_message_cb_(session_message_cb), | 174 session_message_cb_(session_message_cb), |
130 session_ready_cb_(session_ready_cb), | 175 session_ready_cb_(session_ready_cb), |
131 session_closed_cb_(session_closed_cb), | 176 session_closed_cb_(session_closed_cb), |
132 session_error_cb_(session_error_cb) { | 177 session_error_cb_(session_error_cb), |
178 next_session_id_(1) { | |
133 } | 179 } |
134 | 180 |
135 void ProxyMediaKeys::InitializeCdm(const std::string& key_system, | 181 void ProxyMediaKeys::InitializeCdm(const std::string& key_system, |
136 const GURL& security_origin) { | 182 const GURL& security_origin) { |
137 manager_->InitializeCdm(cdm_id_, this, key_system, security_origin); | 183 manager_->InitializeCdm(cdm_id_, this, key_system, security_origin); |
138 } | 184 } |
139 | 185 |
186 uint32_t ProxyMediaKeys::CreateSessionId() { | |
187 return next_session_id_++; | |
188 } | |
189 | |
190 void ProxyMediaKeys::AssignWebSessionId(uint32_t session_id, | |
191 const std::string& web_session_id) { | |
192 web_session_to_session_id_map_.insert( | |
193 std::make_pair(web_session_id, session_id)); | |
194 } | |
195 | |
196 uint32_t ProxyMediaKeys::LookupSessionId(const std::string& web_session_id) { | |
197 return web_session_to_session_id_map_.find(web_session_id)->second; | |
198 } | |
199 | |
200 std::string ProxyMediaKeys::LookupWebSessionId(uint32_t session_id) { | |
201 std::map<std::string, uint32_t>::iterator it; | |
202 for (it = web_session_to_session_id_map_.begin(); | |
203 it != web_session_to_session_id_map_.end(); | |
204 ++it) { | |
205 if (it->second == session_id) | |
206 return it->first; | |
207 } | |
208 // Possible to get an error creating a session, so no |web_session_id| | |
209 // available. | |
210 return std::string(); | |
211 } | |
212 | |
213 void ProxyMediaKeys::DropWebSessionId(std::string web_session_id) { | |
214 web_session_to_session_id_map_.erase(web_session_id); | |
215 } | |
216 | |
217 void ProxyMediaKeys::AddPromise( | |
218 uint32_t session_id, | |
219 scoped_ptr<media::MediaKeysSessionPromise> promise) { | |
220 // Should only be one promise outstanding for any |session_id|. | |
221 DCHECK(session_id_to_promise_map_.find(session_id) == | |
222 session_id_to_promise_map_.end()); | |
223 session_id_to_promise_map_.insert( | |
224 std::make_pair(session_id, promise.release())); | |
225 } | |
226 | |
227 scoped_ptr<media::MediaKeysSessionPromise> ProxyMediaKeys::LookupPromise( | |
228 uint32_t session_id) { | |
229 std::map<uint32_t, media::MediaKeysSessionPromise*>::iterator it = | |
230 session_id_to_promise_map_.find(session_id); | |
231 // May not be a promise associated with this session for asynchronous events. | |
232 if (it == session_id_to_promise_map_.end()) | |
233 return scoped_ptr<media::MediaKeysSessionPromise>(); | |
234 scoped_ptr<media::MediaKeysSessionPromise> result(it->second); | |
235 session_id_to_promise_map_.erase(it); | |
236 return result.Pass(); | |
237 } | |
238 | |
140 } // namespace content | 239 } // namespace content |
OLD | NEW |