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

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 #if DCHECK_IS_ON()
78 // Returns whether |dict| has a value assocaited with the |key|.
79 bool HasEntry(const base::DictionaryValue& dict, const std::string& key) {
80 return dict.GetDictionaryWithoutPathExpansion(key, nullptr);
81 }
82 #endif
40 83
41 } // namespace 84 } // namespace
42 85
43 // static 86 // static
44 void MediaDrmStorageImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) { 87 void MediaDrmStorageImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) {
45 registry->RegisterDictionaryPref(kMediaDrmStorage); 88 registry->RegisterDictionaryPref(kMediaDrmStorage);
46 } 89 }
47 90
48 MediaDrmStorageImpl::MediaDrmStorageImpl( 91 MediaDrmStorageImpl::MediaDrmStorageImpl(
49 content::RenderFrameHost* render_frame_host, 92 content::RenderFrameHost* render_frame_host,
50 PrefService* pref_service, 93 PrefService* pref_service,
51 const url::Origin& origin, 94 const url::Origin& origin,
52 media::mojom::MediaDrmStorageRequest request) 95 media::mojom::MediaDrmStorageRequest request)
53 : render_frame_host_(render_frame_host), 96 : render_frame_host_(render_frame_host),
54 pref_service_(pref_service), 97 pref_service_(pref_service),
55 origin_(origin), 98 origin_(origin),
99 origin_string_(origin.Serialize()),
56 binding_(this, std::move(request)) { 100 binding_(this, std::move(request)) {
57 DVLOG(1) << __func__ << ": origin = " << origin; 101 DVLOG(1) << __func__ << ": origin = " << origin;
58 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 102 DCHECK(thread_checker_.CalledOnValidThread());
59 DCHECK(pref_service_); 103 DCHECK(pref_service_);
104 DCHECK(!origin_string_.empty());
60 105
61 // |this| owns |binding_|, so unretained is safe. 106 // |this| owns |binding_|, so unretained is safe.
62 binding_.set_connection_error_handler( 107 binding_.set_connection_error_handler(
63 base::Bind(&MediaDrmStorageImpl::Close, base::Unretained(this))); 108 base::Bind(&MediaDrmStorageImpl::Close, base::Unretained(this)));
64 } 109 }
65 110
66 MediaDrmStorageImpl::~MediaDrmStorageImpl() { 111 MediaDrmStorageImpl::~MediaDrmStorageImpl() {
67 DVLOG(1) << __func__; 112 DVLOG(1) << __func__;
68 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 113 DCHECK(thread_checker_.CalledOnValidThread());
69 } 114 }
70 115
71 // TODO(xhwang): Update this function to return an origin ID. If the origin is 116 // 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. 117 // not the same as |origin_|, return an empty origin ID.
73 void MediaDrmStorageImpl::Initialize(const url::Origin& origin) { 118 void MediaDrmStorageImpl::Initialize(const url::Origin& origin) {
74 DVLOG(1) << __func__ << ": origin = " << origin; 119 DVLOG(1) << __func__ << ": origin = " << origin;
75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 120 DCHECK(thread_checker_.CalledOnValidThread());
76 DCHECK(!initialized_); 121 DCHECK(!initialized_);
77 122
78 initialized_ = true; 123 initialized_ = true;
79 } 124 }
80 125
81 void MediaDrmStorageImpl::OnProvisioned(const OnProvisionedCallback& callback) { 126 void MediaDrmStorageImpl::OnProvisioned(const OnProvisionedCallback& callback) {
82 DVLOG(1) << __func__; 127 DVLOG(1) << __func__;
83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 128 DCHECK(thread_checker_.CalledOnValidThread());
84 129
85 if (!initialized_) { 130 if (!initialized_) {
86 DVLOG(1) << __func__ << ": Not initialized."; 131 DVLOG(1) << __func__ << ": Not initialized.";
87 callback.Run(false); 132 callback.Run(false);
88 return; 133 return;
89 } 134 }
90 135
91 NOTIMPLEMENTED(); 136 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
92 callback.Run(false); 137 base::DictionaryValue* storage_dict = update.Get();
138 DCHECK(storage_dict);
139
140 // The origin string may contain dots. Do not use path expansion.
141 DVLOG_IF(1, HasEntry(*storage_dict, origin_string_))
142 << __func__ << ": Entry for origin " << origin_string_
143 << " already exists and will be cleared";
144
145 storage_dict->SetWithoutPathExpansion(origin_string_,
146 CreateOriginDictionary());
147 callback.Run(true);
93 } 148 }
94 149
95 void MediaDrmStorageImpl::SavePersistentSession( 150 void MediaDrmStorageImpl::SavePersistentSession(
96 const std::string& session_id, 151 const std::string& session_id,
97 media::mojom::SessionDataPtr session_data, 152 media::mojom::SessionDataPtr session_data,
98 const SavePersistentSessionCallback& callback) { 153 const SavePersistentSessionCallback& callback) {
99 DVLOG(2) << __func__; 154 DVLOG(2) << __func__;
100 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 155 DCHECK(thread_checker_.CalledOnValidThread());
101 156
102 if (!initialized_) { 157 if (!initialized_) {
103 DVLOG(1) << __func__ << ": Not initialized."; 158 DVLOG(1) << __func__ << ": Not initialized.";
104 callback.Run(false); 159 callback.Run(false);
105 return; 160 return;
106 } 161 }
107 162
108 NOTIMPLEMENTED(); 163 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
109 callback.Run(false); 164 base::DictionaryValue* storage_dict = update.Get();
165 DCHECK(storage_dict);
166
167 base::DictionaryValue* origin_dict = nullptr;
168 // The origin string may contain dots. Do not use path expansion.
169 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
170 if (!origin_dict) {
171 DVLOG(1) << __func__
172 << ": Failed to save persistent session data; entry for origin "
173 << origin_string_ << " does not exist.";
174 callback.Run(false);
175 return;
176 }
177
178 base::DictionaryValue* sessions_dict = nullptr;
179 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
180 DVLOG(2) << __func__ << ": No session exists; creating a new dict.";
181 origin_dict->Set(kSessions, base::MakeUnique<base::DictionaryValue>());
182 DCHECK(origin_dict->GetDictionary(kSessions, &sessions_dict));
183 }
184
185 DVLOG_IF(1, HasEntry(*sessions_dict, session_id))
186 << __func__ << ": Session ID already exists and will be replaced.";
187
188 sessions_dict->SetWithoutPathExpansion(
189 session_id, CreateSessionDictionary(session_data->key_set_id,
190 session_data->mime_type));
191
192 callback.Run(true);
110 } 193 }
111 194
112 void MediaDrmStorageImpl::LoadPersistentSession( 195 void MediaDrmStorageImpl::LoadPersistentSession(
113 const std::string& session_id, 196 const std::string& session_id,
114 const LoadPersistentSessionCallback& callback) { 197 const LoadPersistentSessionCallback& callback) {
115 DVLOG(2) << __func__; 198 DVLOG(2) << __func__;
116 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 199 DCHECK(thread_checker_.CalledOnValidThread());
117 200
118 if (!initialized_) { 201 if (!initialized_) {
119 DVLOG(1) << __func__ << ": Not initialized."; 202 DVLOG(1) << __func__ << ": Not initialized.";
120 callback.Run(nullptr); 203 callback.Run(nullptr);
121 return; 204 return;
122 } 205 }
123 206
124 NOTIMPLEMENTED(); 207 const base::DictionaryValue* storage_dict =
125 callback.Run(nullptr); 208 pref_service_->GetDictionary(kMediaDrmStorage);
209
210 const base::DictionaryValue* origin_dict = nullptr;
211 // The origin string may contain dots. Do not use path expansion.
212 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
213 if (!origin_dict) {
214 DVLOG(1) << __func__
215 << ": Failed to save persistent session data; entry for origin "
216 << origin_ << " does not exist.";
217 callback.Run(nullptr);
218 return;
219 }
220
221 const base::DictionaryValue* sessions_dict = nullptr;
222 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
223 DVLOG(2) << __func__ << ": Sessions dictionary does not exist.";
224 callback.Run(nullptr);
225 return;
226 }
227
228 const base::DictionaryValue* session_dict = nullptr;
229 if (!sessions_dict->GetDictionaryWithoutPathExpansion(session_id,
230 &session_dict)) {
231 DVLOG(2) << __func__ << ": Session dictionary does not exist.";
232 callback.Run(nullptr);
233 return;
234 }
235
236 std::vector<uint8_t> key_set_id;
237 std::string mime_type;
238 if (!GetSessionData(session_dict, &key_set_id, &mime_type)) {
239 DVLOG(2) << __func__ << ": Failed to read session data.";
240 callback.Run(nullptr);
241 return;
242 }
243
244 callback.Run(media::mojom::SessionData::New(key_set_id, mime_type));
126 } 245 }
127 246
128 void MediaDrmStorageImpl::RemovePersistentSession( 247 void MediaDrmStorageImpl::RemovePersistentSession(
129 const std::string& session_id, 248 const std::string& session_id,
130 const RemovePersistentSessionCallback& callback) { 249 const RemovePersistentSessionCallback& callback) {
131 DVLOG(2) << __func__; 250 DVLOG(2) << __func__;
132 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 251 DCHECK(thread_checker_.CalledOnValidThread());
133 252
134 if (!initialized_) { 253 if (!initialized_) {
135 DVLOG(1) << __func__ << ": Not initialized."; 254 DVLOG(1) << __func__ << ": Not initialized.";
136 callback.Run(false); 255 callback.Run(false);
137 return; 256 return;
138 } 257 }
139 258
140 NOTIMPLEMENTED(); 259 DictionaryPrefUpdate update(pref_service_, kMediaDrmStorage);
141 callback.Run(false); 260 base::DictionaryValue* storage_dict = update.Get();
261 DCHECK(storage_dict);
262
263 base::DictionaryValue* origin_dict = nullptr;
264 // The origin string may contain dots. Do not use path expansion.
265 storage_dict->GetDictionaryWithoutPathExpansion(origin_string_, &origin_dict);
266 if (!origin_dict) {
267 DVLOG(1) << __func__ << ": Entry for rigin " << origin_string_
268 << " does not exist.";
269 callback.Run(true);
270 return;
271 }
272
273 base::DictionaryValue* sessions_dict = nullptr;
274 if (!origin_dict->GetDictionary(kSessions, &sessions_dict)) {
275 DVLOG(2) << __func__ << ": Sessions dictionary does not exist.";
276 callback.Run(true);
277 return;
278 }
279
280 sessions_dict->RemoveWithoutPathExpansion(session_id, nullptr);
281 callback.Run(true);
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
« 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