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

Side by Side Diff: components/cdm/browser/media_drm_storage_impl.cc

Issue 2791903004: media: Implement MediaDrmStorageImpl with tests (Closed)
Patch Set: fix rebase errors Created 3 years, 8 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 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "components/cdm/browser/media_drm_storage_impl.h" 5 #include "components/cdm/browser/media_drm_storage_impl.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "components/prefs/pref_registry_simple.h" 9 #include "components/prefs/pref_registry_simple.h"
10 #include "components/prefs/pref_service.h" 10 #include "components/prefs/pref_service.h"
11 #include "components/prefs/scoped_user_pref_update.h" 11 #include "components/prefs/scoped_user_pref_update.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/navigation_handle.h" 12 #include "content/public/browser/navigation_handle.h"
14 13
15 // The storage will be managed by PrefService. All data will be stored in a 14 // The storage will be managed by PrefService. All data will be stored in a
16 // dictionary under the key "media.media_drm_storage". The dictionary is 15 // dictionary under the key "media.media_drm_storage". The dictionary is
17 // structured as follows: 16 // structured as follows:
18 // 17 //
19 // { 18 // {
20 // $origin: { 19 // $origin: {
21 // "origin_id": $origin_id 20 // "origin_id": $origin_id
22 // "creation_time": $creation_time 21 // "creation_time": $creation_time
23 // "sessions" : { 22 // "sessions" : {
24 // $session_id: { 23 // $session_id: {
25 // "key_set_id": $key_set_id, 24 // "key_set_id": $key_set_id,
26 // "mime_type": $mime_type, 25 // "mime_type": $mime_type,
27 // "creation_time": $creation_time 26 // "creation_time": $creation_time
28 // }, 27 // },
29 // # more session_id map... 28 // # more session_id map...
30 // } 29 // }
31 // }, 30 // },
32 // # more origin map... 31 // # more origin map...
33 // } 32 // }
34 33
35 namespace cdm { 34 namespace cdm {
36 35
37 namespace { 36 namespace {
38 37
39 const char kMediaDrmStorage[] = "media.media_drm_storage"; 38 const char kMediaDrmStorage[] = "media.media_drm_storage";
39 const char kCreationTime[] = "creation_time";
40 const char kSessions[] = "sessions";
41 const char kKeySetId[] = "key_set_id";
42 const char kMimeType[] = "mime_type";
43
44 std::unique_ptr<base::DictionaryValue> CreateOriginDictionary() {
45 auto dict = base::MakeUnique<base::DictionaryValue>();
46 // TODO(xhwang): Create |origin_id|.
47 dict->SetDouble(kCreationTime, base::Time::Now().ToDoubleT());
48 return dict;
49 }
50
51 std::unique_ptr<base::DictionaryValue> CreateSessionDictionary(
52 const std::vector<uint8_t>& key_set_id,
53 const std::string& mime_type) {
54 auto dict = base::MakeUnique<base::DictionaryValue>();
55 dict->SetString(kKeySetId,
56 std::string(reinterpret_cast<const char*>(key_set_id.data()),
57 key_set_id.size()));
58 dict->SetString(kMimeType, mime_type);
59 dict->SetDouble(kCreationTime, base::Time::Now().ToDoubleT());
60 return dict;
61 }
62
63 bool GetSessionData(const base::DictionaryValue* sesssion_dict,
64 std::vector<uint8_t>* key_set_id,
65 std::string* mime_type) {
66 std::string key_set_id_string;
67 if (!sesssion_dict->GetString(kKeySetId, &key_set_id_string))
68 return false;
69
70 if (!sesssion_dict->GetString(kMimeType, mime_type))
71 return false;
72
73 key_set_id->assign(key_set_id_string.begin(), key_set_id_string.end());
74 return true;
75 }
40 76
41 } // namespace 77 } // namespace
42 78
43 // static 79 // static
44 void MediaDrmStorageImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) { 80 void MediaDrmStorageImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) {
45 registry->RegisterDictionaryPref(kMediaDrmStorage); 81 registry->RegisterDictionaryPref(kMediaDrmStorage);
46 } 82 }
47 83
48 MediaDrmStorageImpl::MediaDrmStorageImpl( 84 MediaDrmStorageImpl::MediaDrmStorageImpl(
49 content::RenderFrameHost* render_frame_host, 85 content::RenderFrameHost* render_frame_host,
50 PrefService* pref_service, 86 PrefService* pref_service,
51 const url::Origin& origin, 87 const url::Origin& origin,
52 media::mojom::MediaDrmStorageRequest request) 88 media::mojom::MediaDrmStorageRequest request)
53 : render_frame_host_(render_frame_host), 89 : render_frame_host_(render_frame_host),
54 pref_service_(pref_service), 90 pref_service_(pref_service),
55 origin_(origin), 91 origin_(origin),
92 origin_string_(origin.Serialize()),
56 binding_(this, std::move(request)) { 93 binding_(this, std::move(request)) {
57 DVLOG(1) << __func__ << ": origin = " << origin; 94 DVLOG(1) << __func__ << ": origin = " << origin;
58 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 95 DCHECK(thread_checker_.CalledOnValidThread());
59 DCHECK(pref_service_); 96 DCHECK(pref_service_);
97 DCHECK(!origin_string_.empty());
60 98
61 // |this| owns |binding_|, so unretained is safe. 99 // |this| owns |binding_|, so unretained is safe.
62 binding_.set_connection_error_handler( 100 binding_.set_connection_error_handler(
63 base::Bind(&MediaDrmStorageImpl::Close, base::Unretained(this))); 101 base::Bind(&MediaDrmStorageImpl::Close, base::Unretained(this)));
64 } 102 }
65 103
66 MediaDrmStorageImpl::~MediaDrmStorageImpl() { 104 MediaDrmStorageImpl::~MediaDrmStorageImpl() {
67 DVLOG(1) << __func__; 105 DVLOG(1) << __func__;
68 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 106 DCHECK(thread_checker_.CalledOnValidThread());
69 } 107 }
70 108
71 // TODO(xhwang): Update this function to return an origin ID. If the origin is 109 // TODO(xhwang): Update this function to return an origin ID. If the origin is
72 // not the same as |origin_|, return an empty origin ID. 110 // not the same as |origin_|, return an empty origin ID.
73 void MediaDrmStorageImpl::Initialize(const url::Origin& origin) { 111 void MediaDrmStorageImpl::Initialize(const url::Origin& origin) {
74 DVLOG(1) << __func__ << ": origin = " << origin; 112 DVLOG(1) << __func__ << ": origin = " << origin;
75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 113 DCHECK(thread_checker_.CalledOnValidThread());
76 DCHECK(!initialized_); 114 DCHECK(!initialized_);
77 115
78 initialized_ = true; 116 initialized_ = true;
79 } 117 }
80 118
81 void MediaDrmStorageImpl::OnProvisioned(const OnProvisionedCallback& callback) { 119 void MediaDrmStorageImpl::OnProvisioned(const OnProvisionedCallback& callback) {
82 DVLOG(1) << __func__; 120 DVLOG(1) << __func__;
83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 121 DCHECK(thread_checker_.CalledOnValidThread());
84 122
85 if (!initialized_) { 123 if (!initialized_) {
86 DVLOG(1) << __func__ << ": Not initialized."; 124 DVLOG(1) << __func__ << ": Not initialized.";
87 callback.Run(false); 125 callback.Run(false);
88 return; 126 return;
89 } 127 }
90 128
91 NOTIMPLEMENTED(); 129 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
92 callback.Run(false); 130 base::DictionaryValue* storage_dict = update.Get();
131 DCHECK(storage_dict);
132
133 // The origin string may contain dots. Do not use path expansion.
134 if (storage_dict->GetDictionaryWithoutPathExpansion(origin_string_,
135 nullptr)) {
136 DVLOG(1) << __func__
137 << ": Failed to save persistent session data; entry for origin "
138 << origin_string_ << " already exists.";
139 callback.Run(false);
yucliu1 2017/04/04 06:50:00 If this happens, all information associated with t
xhwang 2017/04/06 22:00:51 Updated the implementation to clear the old dictio
140 return;
141 }
142
143 storage_dict->SetWithoutPathExpansion(origin_string_,
144 CreateOriginDictionary());
145 callback.Run(true);
93 } 146 }
94 147
95 void MediaDrmStorageImpl::SavePersistentSession( 148 void MediaDrmStorageImpl::SavePersistentSession(
96 const std::string& session_id, 149 const std::string& session_id,
97 media::mojom::SessionDataPtr session_data, 150 media::mojom::SessionDataPtr session_data,
98 const SavePersistentSessionCallback& callback) { 151 const SavePersistentSessionCallback& callback) {
99 DVLOG(2) << __func__; 152 DVLOG(2) << __func__;
100 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 153 DCHECK(thread_checker_.CalledOnValidThread());
101 154
102 if (!initialized_) { 155 if (!initialized_) {
103 DVLOG(1) << __func__ << ": Not initialized."; 156 DVLOG(1) << __func__ << ": Not initialized.";
104 callback.Run(false); 157 callback.Run(false);
105 return; 158 return;
106 } 159 }
107 160
108 NOTIMPLEMENTED(); 161 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
109 callback.Run(false); 162 base::DictionaryValue* storage_dict = update.Get();
163 DCHECK(storage_dict);
164
165 base::DictionaryValue* origin_dict = nullptr;
166 // The origin string may contain dots. Do not use path expansion.
167 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
168 if (!origin_dict) {
169 DVLOG(1) << __func__
170 << ": Failed to save persistent session data; entry for origin "
171 << origin_string_ << " does not exist.";
172 callback.Run(false);
173 return;
174 }
175
176 base::DictionaryValue* sessions_dict = nullptr;
177 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
178 DVLOG(2) << __func__ << ": No session exists; creating a new dict.";
179 origin_dict->Set(kSessions, base::MakeUnique<base::DictionaryValue>());
180 DCHECK(origin_dict->GetDictionary(kSessions, &sessions_dict));
181 }
182
183 if (sessions_dict->GetDictionaryWithoutPathExpansion(session_id, nullptr)) {
184 DVLOG(1) << __func__ << ": Session ID already exists";
185 callback.Run(false);
yucliu1 2017/04/04 06:50:00 I think offline licenses can be updated, in which
xhwang 2017/04/06 22:00:51 Good point. Done.
186 return;
187 }
188
189 sessions_dict->SetWithoutPathExpansion(
190 session_id, CreateSessionDictionary(session_data->key_set_id,
191 session_data->mime_type));
192
193 callback.Run(true);
110 } 194 }
111 195
112 void MediaDrmStorageImpl::LoadPersistentSession( 196 void MediaDrmStorageImpl::LoadPersistentSession(
113 const std::string& session_id, 197 const std::string& session_id,
114 const LoadPersistentSessionCallback& callback) { 198 const LoadPersistentSessionCallback& callback) {
115 DVLOG(2) << __func__; 199 DVLOG(2) << __func__;
116 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 200 DCHECK(thread_checker_.CalledOnValidThread());
117 201
118 if (!initialized_) { 202 if (!initialized_) {
119 DVLOG(1) << __func__ << ": Not initialized."; 203 DVLOG(1) << __func__ << ": Not initialized.";
120 callback.Run(nullptr); 204 callback.Run(nullptr);
121 return; 205 return;
122 } 206 }
123 207
124 NOTIMPLEMENTED(); 208 const base::DictionaryValue* storage_dict =
125 callback.Run(nullptr); 209 pref_service_->GetDictionary(kMediaDrmStorage);
210
211 const base::DictionaryValue* origin_dict = nullptr;
212 // The origin string may contain dots. Do not use path expansion.
213 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
214 if (!origin_dict) {
215 DVLOG(1) << __func__
216 << ": Failed to save persistent session data; entry for origin "
217 << origin_ << " does not exist.";
218 callback.Run(nullptr);
219 return;
220 }
221
222 const base::DictionaryValue* sessions_dict = nullptr;
223 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
224 DVLOG(2) << __func__ << ": Sessions dictionary does not exist.";
225 callback.Run(nullptr);
226 return;
227 }
228
229 const base::DictionaryValue* session_dict = nullptr;
230 if (!sessions_dict->GetDictionaryWithoutPathExpansion(session_id,
231 &session_dict)) {
232 DVLOG(2) << __func__ << ": Session dictionary does not exist.";
233 callback.Run(nullptr);
234 return;
235 }
236
237 std::vector<uint8_t> key_set_id;
238 std::string mime_type;
239 if (!GetSessionData(session_dict, &key_set_id, &mime_type)) {
240 DVLOG(2) << __func__ << ": Failed to read session data.";
241 callback.Run(nullptr);
yucliu1 2017/04/04 06:50:00 MediaDrmBridge level has logic to clear storage wh
xhwang 2017/04/06 22:00:51 That should never happen unless user manually modi
242 return;
243 }
244
245 callback.Run(media::mojom::SessionData::New(key_set_id, mime_type));
126 } 246 }
127 247
128 void MediaDrmStorageImpl::RemovePersistentSession( 248 void MediaDrmStorageImpl::RemovePersistentSession(
129 const std::string& session_id, 249 const std::string& session_id,
130 const RemovePersistentSessionCallback& callback) { 250 const RemovePersistentSessionCallback& callback) {
131 DVLOG(2) << __func__; 251 DVLOG(2) << __func__;
132 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 252 DCHECK(thread_checker_.CalledOnValidThread());
133 253
134 if (!initialized_) { 254 if (!initialized_) {
135 DVLOG(1) << __func__ << ": Not initialized."; 255 DVLOG(1) << __func__ << ": Not initialized.";
136 callback.Run(false); 256 callback.Run(false);
137 return; 257 return;
138 } 258 }
139 259
140 NOTIMPLEMENTED(); 260 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
141 callback.Run(false); 261 base::DictionaryValue* storage_dict = update.Get();
262 DCHECK(storage_dict);
263
264 base::DictionaryValue* origin_dict = nullptr;
265 // The origin string may contain dots. Do not use path expansion.
266 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
267 if (!origin_dict) {
268 DVLOG(1) << __func__ << ": Entry for rigin " << origin_string_
269 << " does not exist.";
270 callback.Run(false);
271 return;
272 }
273
274 base::DictionaryValue* sessions_dict = nullptr;
275 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
276 DVLOG(2) << __func__ << ": Sessions dictionary does not exist.";
277 callback.Run(false);
278 return;
279 }
280
281 callback.Run(sessions_dict->RemoveWithoutPathExpansion(session_id, nullptr));
yucliu1 2017/04/04 06:50:00 If session_id doesn't exist, this should be treate
xhwang 2017/04/06 22:00:51 Done.
142 } 282 }
143 283
144 void MediaDrmStorageImpl::RenderFrameDeleted( 284 void MediaDrmStorageImpl::RenderFrameDeleted(
145 content::RenderFrameHost* render_frame_host) { 285 content::RenderFrameHost* render_frame_host) {
286 DCHECK(thread_checker_.CalledOnValidThread());
287
146 if (render_frame_host == render_frame_host_) { 288 if (render_frame_host == render_frame_host_) {
147 DVLOG(1) << __func__ << ": RenderFrame destroyed."; 289 DVLOG(1) << __func__ << ": RenderFrame destroyed.";
148 Close(); 290 Close();
149 } 291 }
150 } 292 }
151 293
152 void MediaDrmStorageImpl::DidFinishNavigation( 294 void MediaDrmStorageImpl::DidFinishNavigation(
153 content::NavigationHandle* navigation_handle) { 295 content::NavigationHandle* navigation_handle) {
296 DCHECK(thread_checker_.CalledOnValidThread());
297
154 if (navigation_handle->GetRenderFrameHost() == render_frame_host_) { 298 if (navigation_handle->GetRenderFrameHost() == render_frame_host_) {
155 DVLOG(1) << __func__ << ": Close connection on navigation."; 299 DVLOG(1) << __func__ << ": Close connection on navigation.";
156 Close(); 300 Close();
157 } 301 }
158 } 302 }
159 303
160 void MediaDrmStorageImpl::Close() { 304 void MediaDrmStorageImpl::Close() {
161 DVLOG(1) << __func__; 305 DVLOG(1) << __func__;
162 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 306 DCHECK(thread_checker_.CalledOnValidThread());
163 307
164 delete this; 308 delete this;
165 } 309 }
166 310
167 } // namespace cdm 311 } // namespace cdm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698