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

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

Issue 2791903004: media: Implement MediaDrmStorageImpl with tests (Closed)
Patch Set: comments 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 }
76
77 // Returns whether |dict| has a value assocaited with the |key|.
78 bool HasEntry(const base::DictionaryValue& dict, const std::string& key) {
yucliu1 2017/04/06 22:13:03 The function is only called in DVLOG_IF, will this
xhwang 2017/04/06 22:38:44 Good point. Done.
79 return dict.GetDictionaryWithoutPathExpansion(key, nullptr);
80 }
40 81
41 } // namespace 82 } // namespace
42 83
43 // static 84 // static
44 void MediaDrmStorageImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) { 85 void MediaDrmStorageImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) {
45 registry->RegisterDictionaryPref(kMediaDrmStorage); 86 registry->RegisterDictionaryPref(kMediaDrmStorage);
46 } 87 }
47 88
48 MediaDrmStorageImpl::MediaDrmStorageImpl( 89 MediaDrmStorageImpl::MediaDrmStorageImpl(
49 content::RenderFrameHost* render_frame_host, 90 content::RenderFrameHost* render_frame_host,
50 PrefService* pref_service, 91 PrefService* pref_service,
51 const url::Origin& origin, 92 const url::Origin& origin,
52 media::mojom::MediaDrmStorageRequest request) 93 media::mojom::MediaDrmStorageRequest request)
53 : render_frame_host_(render_frame_host), 94 : render_frame_host_(render_frame_host),
54 pref_service_(pref_service), 95 pref_service_(pref_service),
55 origin_(origin), 96 origin_(origin),
97 origin_string_(origin.Serialize()),
56 binding_(this, std::move(request)) { 98 binding_(this, std::move(request)) {
57 DVLOG(1) << __func__ << ": origin = " << origin; 99 DVLOG(1) << __func__ << ": origin = " << origin;
58 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 100 DCHECK(thread_checker_.CalledOnValidThread());
59 DCHECK(pref_service_); 101 DCHECK(pref_service_);
102 DCHECK(!origin_string_.empty());
60 103
61 // |this| owns |binding_|, so unretained is safe. 104 // |this| owns |binding_|, so unretained is safe.
62 binding_.set_connection_error_handler( 105 binding_.set_connection_error_handler(
63 base::Bind(&MediaDrmStorageImpl::Close, base::Unretained(this))); 106 base::Bind(&MediaDrmStorageImpl::Close, base::Unretained(this)));
64 } 107 }
65 108
66 MediaDrmStorageImpl::~MediaDrmStorageImpl() { 109 MediaDrmStorageImpl::~MediaDrmStorageImpl() {
67 DVLOG(1) << __func__; 110 DVLOG(1) << __func__;
68 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 111 DCHECK(thread_checker_.CalledOnValidThread());
69 } 112 }
70 113
71 // TODO(xhwang): Update this function to return an origin ID. If the origin is 114 // 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. 115 // not the same as |origin_|, return an empty origin ID.
73 void MediaDrmStorageImpl::Initialize(const url::Origin& origin) { 116 void MediaDrmStorageImpl::Initialize(const url::Origin& origin) {
74 DVLOG(1) << __func__ << ": origin = " << origin; 117 DVLOG(1) << __func__ << ": origin = " << origin;
75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 118 DCHECK(thread_checker_.CalledOnValidThread());
76 DCHECK(!initialized_); 119 DCHECK(!initialized_);
77 120
78 initialized_ = true; 121 initialized_ = true;
79 } 122 }
80 123
81 void MediaDrmStorageImpl::OnProvisioned(const OnProvisionedCallback& callback) { 124 void MediaDrmStorageImpl::OnProvisioned(const OnProvisionedCallback& callback) {
82 DVLOG(1) << __func__; 125 DVLOG(1) << __func__;
83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 126 DCHECK(thread_checker_.CalledOnValidThread());
84 127
85 if (!initialized_) { 128 if (!initialized_) {
86 DVLOG(1) << __func__ << ": Not initialized."; 129 DVLOG(1) << __func__ << ": Not initialized.";
87 callback.Run(false); 130 callback.Run(false);
88 return; 131 return;
89 } 132 }
90 133
91 NOTIMPLEMENTED(); 134 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
92 callback.Run(false); 135 base::DictionaryValue* storage_dict = update.Get();
136 DCHECK(storage_dict);
137
138 // The origin string may contain dots. Do not use path expansion.
139 DVLOG_IF(1, HasEntry(*storage_dict, origin_string_))
140 << __func__ << ": Entry for origin " << origin_string_
141 << " already exists and will be cleared";
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 DVLOG_IF(1, HasEntry(*sessions_dict, session_id))
184 << __func__ << ": Session ID already exists and will be replaced.";
185
186 sessions_dict->SetWithoutPathExpansion(
187 session_id, CreateSessionDictionary(session_data->key_set_id,
188 session_data->mime_type));
189
190 callback.Run(true);
110 } 191 }
111 192
112 void MediaDrmStorageImpl::LoadPersistentSession( 193 void MediaDrmStorageImpl::LoadPersistentSession(
113 const std::string& session_id, 194 const std::string& session_id,
114 const LoadPersistentSessionCallback& callback) { 195 const LoadPersistentSessionCallback& callback) {
115 DVLOG(2) << __func__; 196 DVLOG(2) << __func__;
116 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 197 DCHECK(thread_checker_.CalledOnValidThread());
117 198
118 if (!initialized_) { 199 if (!initialized_) {
119 DVLOG(1) << __func__ << ": Not initialized."; 200 DVLOG(1) << __func__ << ": Not initialized.";
120 callback.Run(nullptr); 201 callback.Run(nullptr);
121 return; 202 return;
122 } 203 }
123 204
124 NOTIMPLEMENTED(); 205 const base::DictionaryValue* storage_dict =
125 callback.Run(nullptr); 206 pref_service_->GetDictionary(kMediaDrmStorage);
207
208 const base::DictionaryValue* origin_dict = nullptr;
209 // The origin string may contain dots. Do not use path expansion.
210 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
211 if (!origin_dict) {
212 DVLOG(1) << __func__
213 << ": Failed to save persistent session data; entry for origin "
214 << origin_ << " does not exist.";
215 callback.Run(nullptr);
216 return;
217 }
218
219 const base::DictionaryValue* sessions_dict = nullptr;
220 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
221 DVLOG(2) << __func__ << ": Sessions dictionary does not exist.";
222 callback.Run(nullptr);
223 return;
224 }
225
226 const base::DictionaryValue* session_dict = nullptr;
227 if (!sessions_dict->GetDictionaryWithoutPathExpansion(session_id,
228 &session_dict)) {
229 DVLOG(2) << __func__ << ": Session dictionary does not exist.";
230 callback.Run(nullptr);
231 return;
232 }
233
234 std::vector<uint8_t> key_set_id;
235 std::string mime_type;
236 if (!GetSessionData(session_dict, &key_set_id, &mime_type)) {
237 DVLOG(2) << __func__ << ": Failed to read session data.";
238 callback.Run(nullptr);
239 return;
240 }
241
242 callback.Run(media::mojom::SessionData::New(key_set_id, mime_type));
126 } 243 }
127 244
128 void MediaDrmStorageImpl::RemovePersistentSession( 245 void MediaDrmStorageImpl::RemovePersistentSession(
129 const std::string& session_id, 246 const std::string& session_id,
130 const RemovePersistentSessionCallback& callback) { 247 const RemovePersistentSessionCallback& callback) {
131 DVLOG(2) << __func__; 248 DVLOG(2) << __func__;
132 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 249 DCHECK(thread_checker_.CalledOnValidThread());
133 250
134 if (!initialized_) { 251 if (!initialized_) {
135 DVLOG(1) << __func__ << ": Not initialized."; 252 DVLOG(1) << __func__ << ": Not initialized.";
136 callback.Run(false); 253 callback.Run(false);
137 return; 254 return;
138 } 255 }
139 256
140 NOTIMPLEMENTED(); 257 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
141 callback.Run(false); 258 base::DictionaryValue* storage_dict = update.Get();
259 DCHECK(storage_dict);
260
261 base::DictionaryValue* origin_dict = nullptr;
262 // The origin string may contain dots. Do not use path expansion.
263 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
264 if (!origin_dict) {
265 DVLOG(1) << __func__ << ": Entry for rigin " << origin_string_
266 << " does not exist.";
267 callback.Run(true);
268 return;
269 }
270
271 base::DictionaryValue* sessions_dict = nullptr;
272 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
273 DVLOG(2) << __func__ << ": Sessions dictionary does not exist.";
274 callback.Run(true);
275 return;
276 }
277
278 sessions_dict->RemoveWithoutPathExpansion(session_id, nullptr);
279 callback.Run(true);
142 } 280 }
143 281
144 void MediaDrmStorageImpl::RenderFrameDeleted( 282 void MediaDrmStorageImpl::RenderFrameDeleted(
145 content::RenderFrameHost* render_frame_host) { 283 content::RenderFrameHost* render_frame_host) {
284 DCHECK(thread_checker_.CalledOnValidThread());
285
146 if (render_frame_host == render_frame_host_) { 286 if (render_frame_host == render_frame_host_) {
147 DVLOG(1) << __func__ << ": RenderFrame destroyed."; 287 DVLOG(1) << __func__ << ": RenderFrame destroyed.";
148 Close(); 288 Close();
149 } 289 }
150 } 290 }
151 291
152 void MediaDrmStorageImpl::DidFinishNavigation( 292 void MediaDrmStorageImpl::DidFinishNavigation(
153 content::NavigationHandle* navigation_handle) { 293 content::NavigationHandle* navigation_handle) {
294 DCHECK(thread_checker_.CalledOnValidThread());
295
154 if (navigation_handle->GetRenderFrameHost() == render_frame_host_) { 296 if (navigation_handle->GetRenderFrameHost() == render_frame_host_) {
155 DVLOG(1) << __func__ << ": Close connection on navigation."; 297 DVLOG(1) << __func__ << ": Close connection on navigation.";
156 Close(); 298 Close();
157 } 299 }
158 } 300 }
159 301
160 void MediaDrmStorageImpl::Close() { 302 void MediaDrmStorageImpl::Close() {
161 DVLOG(1) << __func__; 303 DVLOG(1) << __func__;
162 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 304 DCHECK(thread_checker_.CalledOnValidThread());
163 305
164 delete this; 306 delete this;
165 } 307 }
166 308
167 } // namespace cdm 309 } // namespace cdm
OLDNEW
« no previous file with comments | « components/cdm/browser/media_drm_storage_impl.h ('k') | components/cdm/browser/media_drm_storage_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698