OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/browser/storage_partition_impl.h" | 5 #include "content/browser/storage_partition_impl.h" |
6 | 6 |
7 #include "base/sequenced_task_runner.h" | 7 #include "base/sequenced_task_runner.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "content/browser/browser_main_loop.h" | 9 #include "content/browser/browser_main_loop.h" |
10 #include "content/browser/fileapi/browser_file_system_helper.h" | 10 #include "content/browser/fileapi/browser_file_system_helper.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 void CheckQuotaManagedDataDeletionStatus(size_t* deletion_task_count, | 65 void CheckQuotaManagedDataDeletionStatus(size_t* deletion_task_count, |
66 const base::Closure& callback) { | 66 const base::Closure& callback) { |
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
68 if (*deletion_task_count == 0) { | 68 if (*deletion_task_count == 0) { |
69 delete deletion_task_count; | 69 delete deletion_task_count; |
70 callback.Run(); | 70 callback.Run(); |
71 } | 71 } |
72 } | 72 } |
73 | 73 |
74 void OnQuotaManagedOriginDeleted(const GURL& origin, | 74 void OnQuotaManagedOriginDeleted(const GURL& origin, |
75 quota::StorageType type, | 75 storage::StorageType type, |
76 size_t* deletion_task_count, | 76 size_t* deletion_task_count, |
77 const base::Closure& callback, | 77 const base::Closure& callback, |
78 quota::QuotaStatusCode status) { | 78 storage::QuotaStatusCode status) { |
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
80 DCHECK_GT(*deletion_task_count, 0u); | 80 DCHECK_GT(*deletion_task_count, 0u); |
81 if (status != quota::kQuotaStatusOk) { | 81 if (status != storage::kQuotaStatusOk) { |
82 DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin " | 82 DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin " |
83 << origin << ". Status: " << status; | 83 << origin << ". Status: " << status; |
84 } | 84 } |
85 | 85 |
86 (*deletion_task_count)--; | 86 (*deletion_task_count)--; |
87 CheckQuotaManagedDataDeletionStatus(deletion_task_count, callback); | 87 CheckQuotaManagedDataDeletionStatus(deletion_task_count, callback); |
88 } | 88 } |
89 | 89 |
90 void ClearedShaderCache(const base::Closure& callback) { | 90 void ClearedShaderCache(const base::Closure& callback) { |
91 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 91 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
92 BrowserThread::PostTask( | 92 BrowserThread::PostTask( |
93 BrowserThread::UI, FROM_HERE, | 93 BrowserThread::UI, FROM_HERE, |
94 base::Bind(&ClearedShaderCache, callback)); | 94 base::Bind(&ClearedShaderCache, callback)); |
95 return; | 95 return; |
96 } | 96 } |
97 callback.Run(); | 97 callback.Run(); |
98 } | 98 } |
99 | 99 |
100 void ClearShaderCacheOnIOThread(const base::FilePath& path, | 100 void ClearShaderCacheOnIOThread(const base::FilePath& path, |
101 const base::Time begin, | 101 const base::Time begin, |
102 const base::Time end, | 102 const base::Time end, |
103 const base::Closure& callback) { | 103 const base::Closure& callback) { |
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
105 ShaderCacheFactory::GetInstance()->ClearByPath( | 105 ShaderCacheFactory::GetInstance()->ClearByPath( |
106 path, begin, end, base::Bind(&ClearedShaderCache, callback)); | 106 path, begin, end, base::Bind(&ClearedShaderCache, callback)); |
107 } | 107 } |
108 | 108 |
109 void OnLocalStorageUsageInfo( | 109 void OnLocalStorageUsageInfo( |
110 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, | 110 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
111 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 111 const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, |
112 const StoragePartition::OriginMatcherFunction& origin_matcher, | 112 const StoragePartition::OriginMatcherFunction& origin_matcher, |
113 const base::Time delete_begin, | 113 const base::Time delete_begin, |
114 const base::Time delete_end, | 114 const base::Time delete_end, |
115 const base::Closure& callback, | 115 const base::Closure& callback, |
116 const std::vector<LocalStorageUsageInfo>& infos) { | 116 const std::vector<LocalStorageUsageInfo>& infos) { |
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
118 | 118 |
119 for (size_t i = 0; i < infos.size(); ++i) { | 119 for (size_t i = 0; i < infos.size(); ++i) { |
120 if (!origin_matcher.is_null() && | 120 if (!origin_matcher.is_null() && |
121 !origin_matcher.Run(infos[i].origin, special_storage_policy.get())) { | 121 !origin_matcher.Run(infos[i].origin, special_storage_policy.get())) { |
122 continue; | 122 continue; |
123 } | 123 } |
124 | 124 |
125 if (infos[i].last_modified >= delete_begin && | 125 if (infos[i].last_modified >= delete_begin && |
126 infos[i].last_modified <= delete_end) { | 126 infos[i].last_modified <= delete_end) { |
127 dom_storage_context->DeleteLocalStorage(infos[i].origin); | 127 dom_storage_context->DeleteLocalStorage(infos[i].origin); |
128 } | 128 } |
129 } | 129 } |
130 callback.Run(); | 130 callback.Run(); |
131 } | 131 } |
132 | 132 |
133 void OnSessionStorageUsageInfo( | 133 void OnSessionStorageUsageInfo( |
134 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, | 134 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
135 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 135 const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, |
136 const StoragePartition::OriginMatcherFunction& origin_matcher, | 136 const StoragePartition::OriginMatcherFunction& origin_matcher, |
137 const base::Closure& callback, | 137 const base::Closure& callback, |
138 const std::vector<SessionStorageUsageInfo>& infos) { | 138 const std::vector<SessionStorageUsageInfo>& infos) { |
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
140 | 140 |
141 for (size_t i = 0; i < infos.size(); ++i) { | 141 for (size_t i = 0; i < infos.size(); ++i) { |
142 if (!origin_matcher.is_null() && | 142 if (!origin_matcher.is_null() && |
143 !origin_matcher.Run(infos[i].origin, special_storage_policy.get())) { | 143 !origin_matcher.Run(infos[i].origin, special_storage_policy.get())) { |
144 continue; | 144 continue; |
145 } | 145 } |
146 dom_storage_context->DeleteSessionStorage(infos[i]); | 146 dom_storage_context->DeleteSessionStorage(infos[i]); |
147 } | 147 } |
148 | 148 |
149 callback.Run(); | 149 callback.Run(); |
150 } | 150 } |
151 | 151 |
152 void ClearLocalStorageOnUIThread( | 152 void ClearLocalStorageOnUIThread( |
153 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, | 153 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
154 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 154 const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, |
155 const StoragePartition::OriginMatcherFunction& origin_matcher, | 155 const StoragePartition::OriginMatcherFunction& origin_matcher, |
156 const GURL& storage_origin, | 156 const GURL& storage_origin, |
157 const base::Time begin, | 157 const base::Time begin, |
158 const base::Time end, | 158 const base::Time end, |
159 const base::Closure& callback) { | 159 const base::Closure& callback) { |
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
161 | 161 |
162 if (!storage_origin.is_empty()) { | 162 if (!storage_origin.is_empty()) { |
163 bool can_delete = origin_matcher.is_null() || | 163 bool can_delete = origin_matcher.is_null() || |
164 origin_matcher.Run(storage_origin, | 164 origin_matcher.Run(storage_origin, |
165 special_storage_policy.get()); | 165 special_storage_policy.get()); |
166 if (can_delete) | 166 if (can_delete) |
167 dom_storage_context->DeleteLocalStorage(storage_origin); | 167 dom_storage_context->DeleteLocalStorage(storage_origin); |
168 | 168 |
169 callback.Run(); | 169 callback.Run(); |
170 return; | 170 return; |
171 } | 171 } |
172 | 172 |
173 dom_storage_context->GetLocalStorageUsage( | 173 dom_storage_context->GetLocalStorageUsage( |
174 base::Bind(&OnLocalStorageUsageInfo, | 174 base::Bind(&OnLocalStorageUsageInfo, |
175 dom_storage_context, special_storage_policy, origin_matcher, | 175 dom_storage_context, special_storage_policy, origin_matcher, |
176 begin, end, callback)); | 176 begin, end, callback)); |
177 } | 177 } |
178 | 178 |
179 void ClearSessionStorageOnUIThread( | 179 void ClearSessionStorageOnUIThread( |
180 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, | 180 const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context, |
181 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 181 const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, |
182 const StoragePartition::OriginMatcherFunction& origin_matcher, | 182 const StoragePartition::OriginMatcherFunction& origin_matcher, |
183 const base::Closure& callback) { | 183 const base::Closure& callback) { |
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
185 | 185 |
186 dom_storage_context->GetSessionStorageUsage( | 186 dom_storage_context->GetSessionStorageUsage( |
187 base::Bind(&OnSessionStorageUsageInfo, dom_storage_context, | 187 base::Bind(&OnSessionStorageUsageInfo, dom_storage_context, |
188 special_storage_policy, origin_matcher, | 188 special_storage_policy, origin_matcher, |
189 callback)); | 189 callback)); |
190 } | 190 } |
191 | 191 |
(...skipping 27 matching lines...) Expand all Loading... |
219 STATIC_CONST_MEMBER_DEFINITION const uint32 | 219 STATIC_CONST_MEMBER_DEFINITION const uint32 |
220 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE; | 220 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE; |
221 STATIC_CONST_MEMBER_DEFINITION const uint32 | 221 STATIC_CONST_MEMBER_DEFINITION const uint32 |
222 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL; | 222 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL; |
223 | 223 |
224 // Static. | 224 // Static. |
225 int StoragePartitionImpl::GenerateQuotaClientMask(uint32 remove_mask) { | 225 int StoragePartitionImpl::GenerateQuotaClientMask(uint32 remove_mask) { |
226 int quota_client_mask = 0; | 226 int quota_client_mask = 0; |
227 | 227 |
228 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS) | 228 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS) |
229 quota_client_mask |= quota::QuotaClient::kFileSystem; | 229 quota_client_mask |= storage::QuotaClient::kFileSystem; |
230 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_WEBSQL) | 230 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_WEBSQL) |
231 quota_client_mask |= quota::QuotaClient::kDatabase; | 231 quota_client_mask |= storage::QuotaClient::kDatabase; |
232 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_APPCACHE) | 232 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_APPCACHE) |
233 quota_client_mask |= quota::QuotaClient::kAppcache; | 233 quota_client_mask |= storage::QuotaClient::kAppcache; |
234 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_INDEXEDDB) | 234 if (remove_mask & StoragePartition::REMOVE_DATA_MASK_INDEXEDDB) |
235 quota_client_mask |= quota::QuotaClient::kIndexedDatabase; | 235 quota_client_mask |= storage::QuotaClient::kIndexedDatabase; |
236 // TODO(jsbell): StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS) | 236 // TODO(jsbell): StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS) |
237 | 237 |
238 return quota_client_mask; | 238 return quota_client_mask; |
239 } | 239 } |
240 | 240 |
241 // Helper for deleting quota managed data from a partition. | 241 // Helper for deleting quota managed data from a partition. |
242 // | 242 // |
243 // Most of the operations in this class are done on IO thread. | 243 // Most of the operations in this class are done on IO thread. |
244 struct StoragePartitionImpl::QuotaManagedDataDeletionHelper { | 244 struct StoragePartitionImpl::QuotaManagedDataDeletionHelper { |
245 QuotaManagedDataDeletionHelper(uint32 remove_mask, | 245 QuotaManagedDataDeletionHelper(uint32 remove_mask, |
246 uint32 quota_storage_remove_mask, | 246 uint32 quota_storage_remove_mask, |
247 const GURL& storage_origin, | 247 const GURL& storage_origin, |
248 const base::Closure& callback) | 248 const base::Closure& callback) |
249 : remove_mask(remove_mask), | 249 : remove_mask(remove_mask), |
250 quota_storage_remove_mask(quota_storage_remove_mask), | 250 quota_storage_remove_mask(quota_storage_remove_mask), |
251 storage_origin(storage_origin), | 251 storage_origin(storage_origin), |
252 callback(callback), | 252 callback(callback), |
253 task_count(0) { | 253 task_count(0) { |
254 } | 254 } |
255 | 255 |
256 void IncrementTaskCountOnIO(); | 256 void IncrementTaskCountOnIO(); |
257 void DecrementTaskCountOnIO(); | 257 void DecrementTaskCountOnIO(); |
258 | 258 |
259 void ClearDataOnIOThread( | 259 void ClearDataOnIOThread( |
260 const scoped_refptr<quota::QuotaManager>& quota_manager, | 260 const scoped_refptr<storage::QuotaManager>& quota_manager, |
261 const base::Time begin, | 261 const base::Time begin, |
262 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 262 const scoped_refptr<storage::SpecialStoragePolicy>& |
| 263 special_storage_policy, |
263 const StoragePartition::OriginMatcherFunction& origin_matcher); | 264 const StoragePartition::OriginMatcherFunction& origin_matcher); |
264 | 265 |
265 void ClearOriginsOnIOThread( | 266 void ClearOriginsOnIOThread( |
266 quota::QuotaManager* quota_manager, | 267 storage::QuotaManager* quota_manager, |
267 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 268 const scoped_refptr<storage::SpecialStoragePolicy>& |
| 269 special_storage_policy, |
268 const StoragePartition::OriginMatcherFunction& origin_matcher, | 270 const StoragePartition::OriginMatcherFunction& origin_matcher, |
269 const base::Closure& callback, | 271 const base::Closure& callback, |
270 const std::set<GURL>& origins, | 272 const std::set<GURL>& origins, |
271 quota::StorageType quota_storage_type); | 273 storage::StorageType quota_storage_type); |
272 | 274 |
273 // All of these data are accessed on IO thread. | 275 // All of these data are accessed on IO thread. |
274 uint32 remove_mask; | 276 uint32 remove_mask; |
275 uint32 quota_storage_remove_mask; | 277 uint32 quota_storage_remove_mask; |
276 GURL storage_origin; | 278 GURL storage_origin; |
277 const base::Closure callback; | 279 const base::Closure callback; |
278 int task_count; | 280 int task_count; |
279 }; | 281 }; |
280 | 282 |
281 // Helper for deleting all sorts of data from a partition, keeps track of | 283 // Helper for deleting all sorts of data from a partition, keeps track of |
(...skipping 12 matching lines...) Expand all Loading... |
294 const base::Closure& callback) | 296 const base::Closure& callback) |
295 : remove_mask(remove_mask), | 297 : remove_mask(remove_mask), |
296 quota_storage_remove_mask(quota_storage_remove_mask), | 298 quota_storage_remove_mask(quota_storage_remove_mask), |
297 callback(callback), | 299 callback(callback), |
298 task_count(0) { | 300 task_count(0) { |
299 } | 301 } |
300 | 302 |
301 void IncrementTaskCountOnUI(); | 303 void IncrementTaskCountOnUI(); |
302 void DecrementTaskCountOnUI(); | 304 void DecrementTaskCountOnUI(); |
303 | 305 |
304 void ClearDataOnUIThread(const GURL& storage_origin, | 306 void ClearDataOnUIThread( |
305 const OriginMatcherFunction& origin_matcher, | 307 const GURL& storage_origin, |
306 const base::FilePath& path, | 308 const OriginMatcherFunction& origin_matcher, |
307 net::URLRequestContextGetter* rq_context, | 309 const base::FilePath& path, |
308 DOMStorageContextWrapper* dom_storage_context, | 310 net::URLRequestContextGetter* rq_context, |
309 quota::QuotaManager* quota_manager, | 311 DOMStorageContextWrapper* dom_storage_context, |
310 quota::SpecialStoragePolicy* special_storage_policy, | 312 storage::QuotaManager* quota_manager, |
311 WebRTCIdentityStore* webrtc_identity_store, | 313 storage::SpecialStoragePolicy* special_storage_policy, |
312 const base::Time begin, | 314 WebRTCIdentityStore* webrtc_identity_store, |
313 const base::Time end); | 315 const base::Time begin, |
| 316 const base::Time end); |
314 | 317 |
315 void ClearQuotaManagedDataOnIOThread( | 318 void ClearQuotaManagedDataOnIOThread( |
316 const scoped_refptr<quota::QuotaManager>& quota_manager, | 319 const scoped_refptr<storage::QuotaManager>& quota_manager, |
317 const base::Time begin, | 320 const base::Time begin, |
318 const GURL& storage_origin, | 321 const GURL& storage_origin, |
319 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 322 const scoped_refptr<storage::SpecialStoragePolicy>& |
| 323 special_storage_policy, |
320 const StoragePartition::OriginMatcherFunction& origin_matcher, | 324 const StoragePartition::OriginMatcherFunction& origin_matcher, |
321 const base::Closure& callback); | 325 const base::Closure& callback); |
322 | 326 |
323 uint32 remove_mask; | 327 uint32 remove_mask; |
324 uint32 quota_storage_remove_mask; | 328 uint32 quota_storage_remove_mask; |
325 | 329 |
326 // Accessed on UI thread. | 330 // Accessed on UI thread. |
327 const base::Closure callback; | 331 const base::Closure callback; |
328 // Accessed on UI thread. | 332 // Accessed on UI thread. |
329 int task_count; | 333 int task_count; |
330 }; | 334 }; |
331 | 335 |
332 void StoragePartitionImpl::DataDeletionHelper::ClearQuotaManagedDataOnIOThread( | 336 void StoragePartitionImpl::DataDeletionHelper::ClearQuotaManagedDataOnIOThread( |
333 const scoped_refptr<quota::QuotaManager>& quota_manager, | 337 const scoped_refptr<storage::QuotaManager>& quota_manager, |
334 const base::Time begin, | 338 const base::Time begin, |
335 const GURL& storage_origin, | 339 const GURL& storage_origin, |
336 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 340 const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, |
337 const StoragePartition::OriginMatcherFunction& origin_matcher, | 341 const StoragePartition::OriginMatcherFunction& origin_matcher, |
338 const base::Closure& callback) { | 342 const base::Closure& callback) { |
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
340 | 344 |
341 StoragePartitionImpl::QuotaManagedDataDeletionHelper* helper = | 345 StoragePartitionImpl::QuotaManagedDataDeletionHelper* helper = |
342 new StoragePartitionImpl::QuotaManagedDataDeletionHelper( | 346 new StoragePartitionImpl::QuotaManagedDataDeletionHelper( |
343 remove_mask, | 347 remove_mask, |
344 quota_storage_remove_mask, | 348 quota_storage_remove_mask, |
345 storage_origin, | 349 storage_origin, |
346 callback); | 350 callback); |
347 helper->ClearDataOnIOThread(quota_manager, begin, special_storage_policy, | 351 helper->ClearDataOnIOThread(quota_manager, begin, special_storage_policy, |
348 origin_matcher); | 352 origin_matcher); |
349 } | 353 } |
350 | 354 |
351 StoragePartitionImpl::StoragePartitionImpl( | 355 StoragePartitionImpl::StoragePartitionImpl( |
352 const base::FilePath& partition_path, | 356 const base::FilePath& partition_path, |
353 quota::QuotaManager* quota_manager, | 357 storage::QuotaManager* quota_manager, |
354 ChromeAppCacheService* appcache_service, | 358 ChromeAppCacheService* appcache_service, |
355 fileapi::FileSystemContext* filesystem_context, | 359 storage::FileSystemContext* filesystem_context, |
356 webkit_database::DatabaseTracker* database_tracker, | 360 storage::DatabaseTracker* database_tracker, |
357 DOMStorageContextWrapper* dom_storage_context, | 361 DOMStorageContextWrapper* dom_storage_context, |
358 IndexedDBContextImpl* indexed_db_context, | 362 IndexedDBContextImpl* indexed_db_context, |
359 ServiceWorkerContextWrapper* service_worker_context, | 363 ServiceWorkerContextWrapper* service_worker_context, |
360 WebRTCIdentityStore* webrtc_identity_store, | 364 WebRTCIdentityStore* webrtc_identity_store, |
361 quota::SpecialStoragePolicy* special_storage_policy) | 365 storage::SpecialStoragePolicy* special_storage_policy) |
362 : partition_path_(partition_path), | 366 : partition_path_(partition_path), |
363 quota_manager_(quota_manager), | 367 quota_manager_(quota_manager), |
364 appcache_service_(appcache_service), | 368 appcache_service_(appcache_service), |
365 filesystem_context_(filesystem_context), | 369 filesystem_context_(filesystem_context), |
366 database_tracker_(database_tracker), | 370 database_tracker_(database_tracker), |
367 dom_storage_context_(dom_storage_context), | 371 dom_storage_context_(dom_storage_context), |
368 indexed_db_context_(indexed_db_context), | 372 indexed_db_context_(indexed_db_context), |
369 service_worker_context_(service_worker_context), | 373 service_worker_context_(service_worker_context), |
370 webrtc_identity_store_(webrtc_identity_store), | 374 webrtc_identity_store_(webrtc_identity_store), |
371 special_storage_policy_(special_storage_policy) {} | 375 special_storage_policy_(special_storage_policy) { |
| 376 } |
372 | 377 |
373 StoragePartitionImpl::~StoragePartitionImpl() { | 378 StoragePartitionImpl::~StoragePartitionImpl() { |
374 // These message loop checks are just to avoid leaks in unittests. | 379 // These message loop checks are just to avoid leaks in unittests. |
375 if (GetDatabaseTracker() && | 380 if (GetDatabaseTracker() && |
376 BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { | 381 BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { |
377 BrowserThread::PostTask( | 382 BrowserThread::PostTask( |
378 BrowserThread::FILE, FROM_HERE, | 383 BrowserThread::FILE, |
379 base::Bind(&webkit_database::DatabaseTracker::Shutdown, | 384 FROM_HERE, |
380 GetDatabaseTracker())); | 385 base::Bind(&storage::DatabaseTracker::Shutdown, GetDatabaseTracker())); |
381 } | 386 } |
382 | 387 |
383 if (GetFileSystemContext()) | 388 if (GetFileSystemContext()) |
384 GetFileSystemContext()->Shutdown(); | 389 GetFileSystemContext()->Shutdown(); |
385 | 390 |
386 if (GetDOMStorageContext()) | 391 if (GetDOMStorageContext()) |
387 GetDOMStorageContext()->Shutdown(); | 392 GetDOMStorageContext()->Shutdown(); |
388 | 393 |
389 if (GetServiceWorkerContext()) | 394 if (GetServiceWorkerContext()) |
390 GetServiceWorkerContext()->Shutdown(); | 395 GetServiceWorkerContext()->Shutdown(); |
391 } | 396 } |
392 | 397 |
393 // TODO(ajwong): Break the direct dependency on |context|. We only | 398 // TODO(ajwong): Break the direct dependency on |context|. We only |
394 // need 3 pieces of info from it. | 399 // need 3 pieces of info from it. |
395 StoragePartitionImpl* StoragePartitionImpl::Create( | 400 StoragePartitionImpl* StoragePartitionImpl::Create( |
396 BrowserContext* context, | 401 BrowserContext* context, |
397 bool in_memory, | 402 bool in_memory, |
398 const base::FilePath& partition_path) { | 403 const base::FilePath& partition_path) { |
399 // Ensure that these methods are called on the UI thread, except for | 404 // Ensure that these methods are called on the UI thread, except for |
400 // unittests where a UI thread might not have been created. | 405 // unittests where a UI thread might not have been created. |
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || | 406 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
402 !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); | 407 !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); |
403 | 408 |
404 // All of the clients have to be created and registered with the | 409 // All of the clients have to be created and registered with the |
405 // QuotaManager prior to the QuotaManger being used. We do them | 410 // QuotaManager prior to the QuotaManger being used. We do them |
406 // all together here prior to handing out a reference to anything | 411 // all together here prior to handing out a reference to anything |
407 // that utilizes the QuotaManager. | 412 // that utilizes the QuotaManager. |
408 scoped_refptr<quota::QuotaManager> quota_manager = new quota::QuotaManager( | 413 scoped_refptr<storage::QuotaManager> quota_manager = |
409 in_memory, | 414 new storage::QuotaManager( |
410 partition_path, | 415 in_memory, |
411 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(), | 416 partition_path, |
412 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(), | 417 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(), |
413 context->GetSpecialStoragePolicy()); | 418 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(), |
| 419 context->GetSpecialStoragePolicy()); |
414 | 420 |
415 // Each consumer is responsible for registering its QuotaClient during | 421 // Each consumer is responsible for registering its QuotaClient during |
416 // its construction. | 422 // its construction. |
417 scoped_refptr<fileapi::FileSystemContext> filesystem_context = | 423 scoped_refptr<storage::FileSystemContext> filesystem_context = |
418 CreateFileSystemContext(context, | 424 CreateFileSystemContext( |
419 partition_path, in_memory, | 425 context, partition_path, in_memory, quota_manager->proxy()); |
420 quota_manager->proxy()); | |
421 | 426 |
422 scoped_refptr<webkit_database::DatabaseTracker> database_tracker = | 427 scoped_refptr<storage::DatabaseTracker> database_tracker = |
423 new webkit_database::DatabaseTracker( | 428 new storage::DatabaseTracker(partition_path, |
424 partition_path, | 429 in_memory, |
425 in_memory, | 430 context->GetSpecialStoragePolicy(), |
426 context->GetSpecialStoragePolicy(), | 431 quota_manager->proxy(), |
427 quota_manager->proxy(), | 432 BrowserThread::GetMessageLoopProxyForThread( |
428 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) | 433 BrowserThread::FILE).get()); |
429 .get()); | |
430 | 434 |
431 base::FilePath path = in_memory ? base::FilePath() : partition_path; | 435 base::FilePath path = in_memory ? base::FilePath() : partition_path; |
432 scoped_refptr<DOMStorageContextWrapper> dom_storage_context = | 436 scoped_refptr<DOMStorageContextWrapper> dom_storage_context = |
433 new DOMStorageContextWrapper(path, context->GetSpecialStoragePolicy()); | 437 new DOMStorageContextWrapper(path, context->GetSpecialStoragePolicy()); |
434 | 438 |
435 // BrowserMainLoop may not be initialized in unit tests. Tests will | 439 // BrowserMainLoop may not be initialized in unit tests. Tests will |
436 // need to inject their own task runner into the IndexedDBContext. | 440 // need to inject their own task runner into the IndexedDBContext. |
437 base::SequencedTaskRunner* idb_task_runner = | 441 base::SequencedTaskRunner* idb_task_runner = |
438 BrowserThread::CurrentlyOn(BrowserThread::UI) && | 442 BrowserThread::CurrentlyOn(BrowserThread::UI) && |
439 BrowserMainLoop::GetInstance() | 443 BrowserMainLoop::GetInstance() |
440 ? BrowserMainLoop::GetInstance()->indexed_db_thread() | 444 ? BrowserMainLoop::GetInstance()->indexed_db_thread() |
441 ->message_loop_proxy().get() | 445 ->message_loop_proxy().get() |
442 : NULL; | 446 : NULL; |
443 scoped_refptr<IndexedDBContextImpl> indexed_db_context = | 447 scoped_refptr<IndexedDBContextImpl> indexed_db_context = |
444 new IndexedDBContextImpl(path, | 448 new IndexedDBContextImpl(path, |
445 context->GetSpecialStoragePolicy(), | 449 context->GetSpecialStoragePolicy(), |
446 quota_manager->proxy(), | 450 quota_manager->proxy(), |
447 idb_task_runner); | 451 idb_task_runner); |
448 | 452 |
449 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context = | 453 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context = |
450 new ServiceWorkerContextWrapper(context); | 454 new ServiceWorkerContextWrapper(context); |
451 service_worker_context->Init(path, quota_manager->proxy()); | 455 service_worker_context->Init(path, quota_manager->proxy()); |
452 | 456 |
453 scoped_refptr<ChromeAppCacheService> appcache_service = | 457 scoped_refptr<ChromeAppCacheService> appcache_service = |
454 new ChromeAppCacheService(quota_manager->proxy()); | 458 new ChromeAppCacheService(quota_manager->proxy()); |
455 | 459 |
456 scoped_refptr<WebRTCIdentityStore> webrtc_identity_store( | 460 scoped_refptr<WebRTCIdentityStore> webrtc_identity_store( |
457 new WebRTCIdentityStore(path, context->GetSpecialStoragePolicy())); | 461 new WebRTCIdentityStore(path, context->GetSpecialStoragePolicy())); |
458 | 462 |
459 scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy( | 463 scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy( |
460 context->GetSpecialStoragePolicy()); | 464 context->GetSpecialStoragePolicy()); |
461 | 465 |
462 return new StoragePartitionImpl(partition_path, | 466 return new StoragePartitionImpl(partition_path, |
463 quota_manager.get(), | 467 quota_manager.get(), |
464 appcache_service.get(), | 468 appcache_service.get(), |
465 filesystem_context.get(), | 469 filesystem_context.get(), |
466 database_tracker.get(), | 470 database_tracker.get(), |
467 dom_storage_context.get(), | 471 dom_storage_context.get(), |
468 indexed_db_context.get(), | 472 indexed_db_context.get(), |
469 service_worker_context.get(), | 473 service_worker_context.get(), |
470 webrtc_identity_store.get(), | 474 webrtc_identity_store.get(), |
471 special_storage_policy.get()); | 475 special_storage_policy.get()); |
472 } | 476 } |
473 | 477 |
474 base::FilePath StoragePartitionImpl::GetPath() { | 478 base::FilePath StoragePartitionImpl::GetPath() { |
475 return partition_path_; | 479 return partition_path_; |
476 } | 480 } |
477 | 481 |
478 net::URLRequestContextGetter* StoragePartitionImpl::GetURLRequestContext() { | 482 net::URLRequestContextGetter* StoragePartitionImpl::GetURLRequestContext() { |
479 return url_request_context_.get(); | 483 return url_request_context_.get(); |
480 } | 484 } |
481 | 485 |
482 net::URLRequestContextGetter* | 486 net::URLRequestContextGetter* |
483 StoragePartitionImpl::GetMediaURLRequestContext() { | 487 StoragePartitionImpl::GetMediaURLRequestContext() { |
484 return media_url_request_context_.get(); | 488 return media_url_request_context_.get(); |
485 } | 489 } |
486 | 490 |
487 quota::QuotaManager* StoragePartitionImpl::GetQuotaManager() { | 491 storage::QuotaManager* StoragePartitionImpl::GetQuotaManager() { |
488 return quota_manager_.get(); | 492 return quota_manager_.get(); |
489 } | 493 } |
490 | 494 |
491 ChromeAppCacheService* StoragePartitionImpl::GetAppCacheService() { | 495 ChromeAppCacheService* StoragePartitionImpl::GetAppCacheService() { |
492 return appcache_service_.get(); | 496 return appcache_service_.get(); |
493 } | 497 } |
494 | 498 |
495 fileapi::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() { | 499 storage::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() { |
496 return filesystem_context_.get(); | 500 return filesystem_context_.get(); |
497 } | 501 } |
498 | 502 |
499 webkit_database::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() { | 503 storage::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() { |
500 return database_tracker_.get(); | 504 return database_tracker_.get(); |
501 } | 505 } |
502 | 506 |
503 DOMStorageContextWrapper* StoragePartitionImpl::GetDOMStorageContext() { | 507 DOMStorageContextWrapper* StoragePartitionImpl::GetDOMStorageContext() { |
504 return dom_storage_context_.get(); | 508 return dom_storage_context_.get(); |
505 } | 509 } |
506 | 510 |
507 IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() { | 511 IndexedDBContextImpl* StoragePartitionImpl::GetIndexedDBContext() { |
508 return indexed_db_context_.get(); | 512 return indexed_db_context_.get(); |
509 } | 513 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 DCHECK_GT(task_count, 0); | 549 DCHECK_GT(task_count, 0); |
546 --task_count; | 550 --task_count; |
547 if (task_count) | 551 if (task_count) |
548 return; | 552 return; |
549 | 553 |
550 callback.Run(); | 554 callback.Run(); |
551 delete this; | 555 delete this; |
552 } | 556 } |
553 | 557 |
554 void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread( | 558 void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread( |
555 const scoped_refptr<quota::QuotaManager>& quota_manager, | 559 const scoped_refptr<storage::QuotaManager>& quota_manager, |
556 const base::Time begin, | 560 const base::Time begin, |
557 const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy, | 561 const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, |
558 const StoragePartition::OriginMatcherFunction& origin_matcher) { | 562 const StoragePartition::OriginMatcherFunction& origin_matcher) { |
559 IncrementTaskCountOnIO(); | 563 IncrementTaskCountOnIO(); |
560 base::Closure decrement_callback = base::Bind( | 564 base::Closure decrement_callback = base::Bind( |
561 &QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO, | 565 &QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO, |
562 base::Unretained(this)); | 566 base::Unretained(this)); |
563 | 567 |
564 if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_PERSISTENT) { | 568 if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_PERSISTENT) { |
565 IncrementTaskCountOnIO(); | 569 IncrementTaskCountOnIO(); |
566 // Ask the QuotaManager for all origins with persistent quota modified | 570 // Ask the QuotaManager for all origins with persistent quota modified |
567 // within the user-specified timeframe, and deal with the resulting set in | 571 // within the user-specified timeframe, and deal with the resulting set in |
568 // ClearQuotaManagedOriginsOnIOThread(). | 572 // ClearQuotaManagedOriginsOnIOThread(). |
569 quota_manager->GetOriginsModifiedSince( | 573 quota_manager->GetOriginsModifiedSince( |
570 quota::kStorageTypePersistent, begin, | 574 storage::kStorageTypePersistent, |
| 575 begin, |
571 base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread, | 576 base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread, |
572 base::Unretained(this), | 577 base::Unretained(this), |
573 quota_manager, | 578 quota_manager, |
574 special_storage_policy, | 579 special_storage_policy, |
575 origin_matcher, | 580 origin_matcher, |
576 decrement_callback)); | 581 decrement_callback)); |
577 } | 582 } |
578 | 583 |
579 // Do the same for temporary quota. | 584 // Do the same for temporary quota. |
580 if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_TEMPORARY) { | 585 if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_TEMPORARY) { |
581 IncrementTaskCountOnIO(); | 586 IncrementTaskCountOnIO(); |
582 quota_manager->GetOriginsModifiedSince( | 587 quota_manager->GetOriginsModifiedSince( |
583 quota::kStorageTypeTemporary, begin, | 588 storage::kStorageTypeTemporary, |
| 589 begin, |
584 base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread, | 590 base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread, |
585 base::Unretained(this), | 591 base::Unretained(this), |
586 quota_manager, | 592 quota_manager, |
587 special_storage_policy, | 593 special_storage_policy, |
588 origin_matcher, | 594 origin_matcher, |
589 decrement_callback)); | 595 decrement_callback)); |
590 } | 596 } |
591 | 597 |
592 // Do the same for syncable quota. | 598 // Do the same for syncable quota. |
593 if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_SYNCABLE) { | 599 if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_SYNCABLE) { |
594 IncrementTaskCountOnIO(); | 600 IncrementTaskCountOnIO(); |
595 quota_manager->GetOriginsModifiedSince( | 601 quota_manager->GetOriginsModifiedSince( |
596 quota::kStorageTypeSyncable, begin, | 602 storage::kStorageTypeSyncable, |
| 603 begin, |
597 base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread, | 604 base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread, |
598 base::Unretained(this), | 605 base::Unretained(this), |
599 quota_manager, | 606 quota_manager, |
600 special_storage_policy, | 607 special_storage_policy, |
601 origin_matcher, | 608 origin_matcher, |
602 decrement_callback)); | 609 decrement_callback)); |
603 } | 610 } |
604 | 611 |
605 DecrementTaskCountOnIO(); | 612 DecrementTaskCountOnIO(); |
606 } | 613 } |
607 | 614 |
608 void StoragePartitionImpl:: | 615 void |
609 QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread( | 616 StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread( |
610 quota::QuotaManager* quota_manager, | 617 storage::QuotaManager* quota_manager, |
611 const scoped_refptr<quota::SpecialStoragePolicy>& | 618 const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, |
612 special_storage_policy, | 619 const StoragePartition::OriginMatcherFunction& origin_matcher, |
613 const StoragePartition::OriginMatcherFunction& origin_matcher, | 620 const base::Closure& callback, |
614 const base::Closure& callback, | 621 const std::set<GURL>& origins, |
615 const std::set<GURL>& origins, | 622 storage::StorageType quota_storage_type) { |
616 quota::StorageType quota_storage_type) { | |
617 // The QuotaManager manages all storage other than cookies, LocalStorage, | 623 // The QuotaManager manages all storage other than cookies, LocalStorage, |
618 // and SessionStorage. This loop wipes out most HTML5 storage for the given | 624 // and SessionStorage. This loop wipes out most HTML5 storage for the given |
619 // origins. | 625 // origins. |
620 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 626 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
621 if (!origins.size()) { | 627 if (!origins.size()) { |
622 callback.Run(); | 628 callback.Run(); |
623 return; | 629 return; |
624 } | 630 } |
625 | 631 |
626 size_t* deletion_task_count = new size_t(0u); | 632 size_t* deletion_task_count = new size_t(0u); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 delete this; | 675 delete this; |
670 } | 676 } |
671 } | 677 } |
672 | 678 |
673 void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread( | 679 void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread( |
674 const GURL& storage_origin, | 680 const GURL& storage_origin, |
675 const OriginMatcherFunction& origin_matcher, | 681 const OriginMatcherFunction& origin_matcher, |
676 const base::FilePath& path, | 682 const base::FilePath& path, |
677 net::URLRequestContextGetter* rq_context, | 683 net::URLRequestContextGetter* rq_context, |
678 DOMStorageContextWrapper* dom_storage_context, | 684 DOMStorageContextWrapper* dom_storage_context, |
679 quota::QuotaManager* quota_manager, | 685 storage::QuotaManager* quota_manager, |
680 quota::SpecialStoragePolicy* special_storage_policy, | 686 storage::SpecialStoragePolicy* special_storage_policy, |
681 WebRTCIdentityStore* webrtc_identity_store, | 687 WebRTCIdentityStore* webrtc_identity_store, |
682 const base::Time begin, | 688 const base::Time begin, |
683 const base::Time end) { | 689 const base::Time end) { |
684 DCHECK_NE(remove_mask, 0u); | 690 DCHECK_NE(remove_mask, 0u); |
685 DCHECK(!callback.is_null()); | 691 DCHECK(!callback.is_null()); |
686 | 692 |
687 IncrementTaskCountOnUI(); | 693 IncrementTaskCountOnUI(); |
688 base::Closure decrement_callback = base::Bind( | 694 base::Closure decrement_callback = base::Bind( |
689 &DataDeletionHelper::DecrementTaskCountOnUI, base::Unretained(this)); | 695 &DataDeletionHelper::DecrementTaskCountOnUI, base::Unretained(this)); |
690 | 696 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 const base::Closure& callback) { | 794 const base::Closure& callback) { |
789 ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin, | 795 ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin, |
790 origin_matcher, GetURLRequestContext(), begin, end, callback); | 796 origin_matcher, GetURLRequestContext(), begin, end, callback); |
791 } | 797 } |
792 | 798 |
793 WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() { | 799 WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() { |
794 return webrtc_identity_store_.get(); | 800 return webrtc_identity_store_.get(); |
795 } | 801 } |
796 | 802 |
797 void StoragePartitionImpl::OverrideQuotaManagerForTesting( | 803 void StoragePartitionImpl::OverrideQuotaManagerForTesting( |
798 quota::QuotaManager* quota_manager) { | 804 storage::QuotaManager* quota_manager) { |
799 quota_manager_ = quota_manager; | 805 quota_manager_ = quota_manager; |
800 } | 806 } |
801 | 807 |
802 void StoragePartitionImpl::OverrideSpecialStoragePolicyForTesting( | 808 void StoragePartitionImpl::OverrideSpecialStoragePolicyForTesting( |
803 quota::SpecialStoragePolicy* special_storage_policy) { | 809 storage::SpecialStoragePolicy* special_storage_policy) { |
804 special_storage_policy_ = special_storage_policy; | 810 special_storage_policy_ = special_storage_policy; |
805 } | 811 } |
806 | 812 |
807 void StoragePartitionImpl::SetURLRequestContext( | 813 void StoragePartitionImpl::SetURLRequestContext( |
808 net::URLRequestContextGetter* url_request_context) { | 814 net::URLRequestContextGetter* url_request_context) { |
809 url_request_context_ = url_request_context; | 815 url_request_context_ = url_request_context; |
810 } | 816 } |
811 | 817 |
812 void StoragePartitionImpl::SetMediaURLRequestContext( | 818 void StoragePartitionImpl::SetMediaURLRequestContext( |
813 net::URLRequestContextGetter* media_url_request_context) { | 819 net::URLRequestContextGetter* media_url_request_context) { |
814 media_url_request_context_ = media_url_request_context; | 820 media_url_request_context_ = media_url_request_context; |
815 } | 821 } |
816 | 822 |
817 } // namespace content | 823 } // namespace content |
OLD | NEW |