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

Side by Side Diff: content/browser/storage_partition_impl_map.cc

Issue 11362268: Implement the ability to obliterate a storage partition from disk. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Correctly delete all data. Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
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_map.h" 5 #include "content/browser/storage_partition_impl_map.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/file_util.h"
10 #include "base/stl_util.h" 11 #include "base/stl_util.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
12 #include "base/string_number_conversions.h" 13 #include "base/string_number_conversions.h"
14 #include "base/threading/worker_pool.h"
13 #include "content/browser/appcache/chrome_appcache_service.h" 15 #include "content/browser/appcache/chrome_appcache_service.h"
14 #include "content/browser/fileapi/browser_file_system_helper.h" 16 #include "content/browser/fileapi/browser_file_system_helper.h"
15 #include "content/browser/fileapi/chrome_blob_storage_context.h" 17 #include "content/browser/fileapi/chrome_blob_storage_context.h"
16 #include "content/browser/histogram_internals_request_job.h" 18 #include "content/browser/histogram_internals_request_job.h"
17 #include "content/browser/net/view_blob_internals_job_factory.h" 19 #include "content/browser/net/view_blob_internals_job_factory.h"
18 #include "content/browser/net/view_http_cache_job_factory.h" 20 #include "content/browser/net/view_http_cache_job_factory.h"
19 #include "content/browser/renderer_host/resource_request_info_impl.h" 21 #include "content/browser/renderer_host/resource_request_info_impl.h"
20 #include "content/browser/resource_context_impl.h" 22 #include "content/browser/resource_context_impl.h"
21 #include "content/browser/storage_partition_impl.h" 23 #include "content/browser/storage_partition_impl.h"
22 #include "content/browser/tcmalloc_internals_request_job.h" 24 #include "content/browser/tcmalloc_internals_request_job.h"
23 #include "content/public/browser/browser_context.h" 25 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/content_browser_client.h"
25 #include "content/public/browser/storage_partition.h" 28 #include "content/public/browser/storage_partition.h"
26 #include "content/public/common/content_constants.h" 29 #include "content/public/common/content_constants.h"
27 #include "content/public/common/url_constants.h" 30 #include "content/public/common/url_constants.h"
28 #include "crypto/sha2.h" 31 #include "crypto/sha2.h"
29 #include "net/url_request/url_request_context_getter.h" 32 #include "net/url_request/url_request_context_getter.h"
30 #include "net/url_request/url_request_context.h" 33 #include "net/url_request/url_request_context.h"
31 #include "webkit/appcache/view_appcache_internals_job.h" 34 #include "webkit/appcache/view_appcache_internals_job.h"
32 #include "webkit/blob/blob_data.h" 35 #include "webkit/blob/blob_data.h"
33 #include "webkit/blob/blob_url_request_job_factory.h" 36 #include "webkit/blob/blob_url_request_job_factory.h"
34 #include "webkit/fileapi/file_system_url_request_job_factory.h" 37 #include "webkit/fileapi/file_system_url_request_job_factory.h"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 // 234 //
232 // For a 6-byte hash, H = 2^(6*8). n(10^-11, H) ~= 75 235 // For a 6-byte hash, H = 2^(6*8). n(10^-11, H) ~= 75
233 // 236 //
234 // An average partition domain is likely to have less than 10 unique 237 // An average partition domain is likely to have less than 10 unique
235 // partition names which is far lower than 75. 238 // partition names which is far lower than 75.
236 // 239 //
237 // Note, that for 4 9s of reliability, the limit is 237 partition names per 240 // Note, that for 4 9s of reliability, the limit is 237 partition names per
238 // partition domain. 241 // partition domain.
239 const int kPartitionNameHashBytes = 6; 242 const int kPartitionNameHashBytes = 6;
240 243
244 // Needed for selecting all files in ObliterateOneDirectory() below.
245 #if defined(OS_POSIX)
nasko 2012/11/15 17:48:10 Why not put these right before the function that u
awong 2012/11/16 00:36:04 Was keeping all constants grouped...
246 const int kAllFileTypes = file_util::FileEnumerator::FILES |
247 file_util::FileEnumerator::DIRECTORIES |
248 file_util::FileEnumerator::SHOW_SYM_LINKS;
249 #else
250 const int kAllFileTypes = file_util::FileEnumerator::FILES |
251 file_util::FileEnumerator::DIRECTORIES;
252 #endif
253
254 FilePath GetStoragePartitionDomainPath(
255 const std::string& partition_domain) {
256 CHECK(IsStringUTF8(partition_domain));
257
258 return FilePath(kStoragePartitionDirname).Append(kExtensionsDirname)
259 .Append(FilePath::FromUTF8Unsafe(partition_domain));
260 }
261
262 // Helper function for doing a depth-first deletion of the data on disk.
263 // Examines paths directly in |current_dir| (no recursion) and tries to
264 // delete from disk anything that is in, or isn't a parent of something in
265 // |paths_to_keep|. Paths that need further expansion are added to
266 // |paths_to_consider|.
267 void ObliterateOneDirectory(const FilePath& current_dir,
Charlie Reis 2012/11/15 18:28:21 Why so violent? :) Obliterate seems like an unus
awong 2012/11/16 00:36:04 I was avoiding "Delete" because there's so many De
268 const std::vector<FilePath>& paths_to_keep,
269 std::vector<FilePath>* paths_to_consider) {
270 file_util::FileEnumerator enumerator(current_dir, false, kAllFileTypes);
271 for (FilePath to_delete = enumerator.Next(); !to_delete.empty();
272 to_delete = enumerator.Next()) {
273 for (std::vector<FilePath>::const_iterator to_keep = paths_to_keep.begin();
274 to_keep != paths_to_keep.end();
275 ++to_keep) {
276 if (to_delete == *to_keep) {
277 // Do nothing because this path shouldn't be deleted.
278 } else if (to_delete.IsParent(*to_keep)) {
279 // |to_delete| contains a path to keep. Add to stack for further
280 // processing.
281 paths_to_consider->push_back(*to_keep);
282 } else {
283 // |to_delete| isn't protected. Just delete it.
284 file_util::Delete(to_delete, true);
285 }
286 }
287 }
288 }
289
290 // Synchronously attempts to delete |root|, preserving only entries in
291 // |paths_to_keep|. If there are no entries in |paths_to_keep| on disk, then it
292 // completely removes |root|. All paths must be absolute paths.
293 void BlockingObliteratePath(const FilePath& root,
294 const std::vector<FilePath>& paths_to_keep) {
295 // Reduce |active_paths| set to those under the root and actually on disk.
nasko 2012/11/15 17:48:10 What is |active_paths|?
awong 2012/11/16 00:36:04 Old name. Fixed.
296 std::vector<FilePath> valid_paths_to_keep;
297 for (std::vector<FilePath>::const_iterator it = paths_to_keep.begin();
298 it != paths_to_keep.end();
299 ++it) {
300 if (root.IsParent(*it) && file_util::PathExists(*it)) {
nasko 2012/11/15 17:48:10 nit: no braces needed.
awong 2012/11/16 00:36:04 Done.
301 valid_paths_to_keep.push_back(*it);
302 }
303 }
304
305 // If none of the |paths_to_keep| are valid anymore then we just whack the
306 // root and be done with it.
307 if (valid_paths_to_keep.empty()) {
308 file_util::Delete(root, true);
309 return;
310 }
311
312 // Otherwise, start at the root and delete everything that is not in
313 // |valid_paths_to_keep|.
314 std::vector<FilePath> paths_to_consider;
315 paths_to_consider.push_back(root);
316 while(!paths_to_consider.empty()) {
317 FilePath path = paths_to_consider.back();
318 paths_to_consider.pop_back();
319 ObliterateOneDirectory(path, valid_paths_to_keep, &paths_to_consider);
320 }
321 }
322
241 } // namespace 323 } // namespace
242 324
243 // static 325 // static
244 FilePath StoragePartitionImplMap::GetStoragePartitionPath( 326 FilePath StoragePartitionImplMap::GetStoragePartitionPath(
245 const std::string& partition_domain, 327 const std::string& partition_domain,
246 const std::string& partition_name) { 328 const std::string& partition_name) {
247 if (partition_domain.empty()) 329 if (partition_domain.empty())
248 return FilePath(); 330 return FilePath();
249 331
250 CHECK(IsStringUTF8(partition_domain)); 332 FilePath path = GetStoragePartitionDomainPath(partition_domain);
251 333
252 FilePath path = FilePath(kStoragePartitionDirname).Append(kExtensionsDirname) 334 // TODO(ajwong): Mangle in-memory into this somehow, either by putting
253 .Append(FilePath::FromUTF8Unsafe(partition_domain)); 335 // it into the partition_name, or by manually adding another path component
254 336 // here. Otherwise, it's possible to have an in-memory StoragePartition and
337 // a persistent one that return the same FilePath for GetPath().
nasko 2012/11/15 17:48:10 Adding a path component might not work with the qu
awong 2012/11/16 00:36:04 The more I think about this, the more I think we s
255 if (!partition_name.empty()) { 338 if (!partition_name.empty()) {
256 // For analysis of why we can ignore collisions, see the comment above 339 // For analysis of why we can ignore collisions, see the comment above
257 // kPartitionNameHashBytes. 340 // kPartitionNameHashBytes.
258 char buffer[kPartitionNameHashBytes]; 341 char buffer[kPartitionNameHashBytes];
259 crypto::SHA256HashString(partition_name, &buffer[0], 342 crypto::SHA256HashString(partition_name, &buffer[0],
260 sizeof(buffer)); 343 sizeof(buffer));
261 return path.AppendASCII(base::HexEncode(buffer, sizeof(buffer))); 344 return path.AppendASCII(base::HexEncode(buffer, sizeof(buffer)));
262 } 345 }
263 346
264 return path.Append(kDefaultPartitionDirname); 347 return path.Append(kDefaultPartitionDirname);
265 } 348 }
266 349
267
268 StoragePartitionImplMap::StoragePartitionImplMap( 350 StoragePartitionImplMap::StoragePartitionImplMap(
269 BrowserContext* browser_context) 351 BrowserContext* browser_context)
270 : browser_context_(browser_context), 352 : browser_context_(browser_context),
271 resource_context_initialized_(false) { 353 resource_context_initialized_(false) {
272 } 354 }
273 355
274 StoragePartitionImplMap::~StoragePartitionImplMap() { 356 StoragePartitionImplMap::~StoragePartitionImplMap() {
275 STLDeleteContainerPairSecondPointers(partitions_.begin(), 357 STLDeleteContainerPairSecondPointers(partitions_.begin(),
276 partitions_.end()); 358 partitions_.end());
277 } 359 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 partition_domain.empty() ? 397 partition_domain.empty() ?
316 browser_context_->GetMediaRequestContext() : 398 browser_context_->GetMediaRequestContext() :
317 browser_context_->GetMediaRequestContextForStoragePartition( 399 browser_context_->GetMediaRequestContextForStoragePartition(
318 partition->GetPath(), in_memory)); 400 partition->GetPath(), in_memory));
319 401
320 PostCreateInitialization(partition); 402 PostCreateInitialization(partition);
321 403
322 return partition; 404 return partition;
323 } 405 }
324 406
407 void StoragePartitionImplMap::AsyncObliterate(const GURL& site) {
408 // This method should avoid creating any StoragePartition (which would
409 // create more open file handles) so that it can delete as much of the
410 // data off disk as possible.
411 std::string partition_domain;
412 std::string partition_name;
413 bool in_memory = false;
414 GetContentClient()->browser()->GetStoragePartitionConfigForSite(
415 browser_context_, site, &partition_domain,
416 &partition_name, &in_memory);
417
418 // The default partition is the whole profile. We can't obliterate that and
419 // should never even try.
420 CHECK(!partition_domain.empty());
421
422 // Find the active partitions for the domain. Because these cannot be removed
423 // from disk, start deletions in all of them.
424 std::vector<StoragePartitionImpl*> active_partitions;
425 std::vector<FilePath> paths_to_keep;
426 for (PartitionMap::const_iterator it = partitions_.begin();
427 it != partitions_.end();
428 ++it) {
429 const StoragePartitionConfig& config = it->first;
430 if (config.partition_domain == partition_domain) {
431 it->second->AsyncClearAllData();
432 if (!config.in_memory) {
nasko 2012/11/15 17:48:10 nit: no braces needed.
awong 2012/11/16 00:36:04 Done.
433 paths_to_keep.push_back(it->second->GetPath());
434 }
435 }
436 }
437
438 // Start a best-effort delete of the on-disk storage excluding paths that are
439 // known to still be in use. This is to delete any previously created
440 // StoragePartition state that just happens to not been used during this run
441 // of the browser.
442 //
443 // TODO(ajwong): Schedule a final cleanup of the whole directory on the next
444 // browser start.
445 FilePath domain_root = browser_context_->GetPath().Append(
446 GetStoragePartitionDomainPath(partition_domain));
447 base::WorkerPool::PostTask(
448 FROM_HERE,
449 base::Bind(&BlockingObliteratePath, domain_root, paths_to_keep),
450 true);
451 }
452
325 void StoragePartitionImplMap::ForEach( 453 void StoragePartitionImplMap::ForEach(
326 const BrowserContext::StoragePartitionCallback& callback) { 454 const BrowserContext::StoragePartitionCallback& callback) {
327 for (PartitionMap::const_iterator it = partitions_.begin(); 455 for (PartitionMap::const_iterator it = partitions_.begin();
328 it != partitions_.end(); 456 it != partitions_.end();
329 ++it) { 457 ++it) {
330 callback.Run(it->second); 458 callback.Run(it->second);
331 } 459 }
332 } 460 }
333 461
334 void StoragePartitionImplMap::PostCreateInitialization( 462 void StoragePartitionImplMap::PostCreateInitialization(
335 StoragePartitionImpl* partition) { 463 StoragePartitionImpl* partition) {
464 // TODO(ajwong): I think we lost the in-memory portion here.
336 // Check first to avoid memory leak in unittests. 465 // Check first to avoid memory leak in unittests.
337 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { 466 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
338 BrowserThread::PostTask( 467 BrowserThread::PostTask(
339 BrowserThread::IO, FROM_HERE, 468 BrowserThread::IO, FROM_HERE,
340 base::Bind(&ChromeAppCacheService::InitializeOnIOThread, 469 base::Bind(&ChromeAppCacheService::InitializeOnIOThread,
341 partition->GetAppCacheService(), 470 partition->GetAppCacheService(),
342 browser_context_->IsOffTheRecord() ? FilePath() : 471 browser_context_->IsOffTheRecord() ? FilePath() :
343 partition->GetPath().Append(kAppCacheDirname), 472 partition->GetPath().Append(kAppCacheDirname),
344 browser_context_->GetResourceContext(), 473 browser_context_->GetResourceContext(),
345 make_scoped_refptr(partition->GetURLRequestContext()), 474 make_scoped_refptr(partition->GetURLRequestContext()),
(...skipping 13 matching lines...) Expand all
359 488
360 // We do not call InitializeURLRequestContext() for media contexts because, 489 // We do not call InitializeURLRequestContext() for media contexts because,
361 // other than the HTTP cache, the media contexts share the same backing 490 // other than the HTTP cache, the media contexts share the same backing
362 // objects as their associated "normal" request context. Thus, the previous 491 // objects as their associated "normal" request context. Thus, the previous
363 // call serves to initialize the media request context for this storage 492 // call serves to initialize the media request context for this storage
364 // partition as well. 493 // partition as well.
365 } 494 }
366 } 495 }
367 496
368 } // namespace content 497 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698