| 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_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/file_util.h" |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 // further partitioned by extension id, followed by another level of directories | 215 // further partitioned by extension id, followed by another level of directories |
| 216 // for the "default" extension storage partition and one directory for each | 216 // for the "default" extension storage partition and one directory for each |
| 217 // persistent partition used by a webview tag. Example: | 217 // persistent partition used by a webview tag. Example: |
| 218 // | 218 // |
| 219 // Storage/ext/ABCDEF/def | 219 // Storage/ext/ABCDEF/def |
| 220 // Storage/ext/ABCDEF/hash(partition name) | 220 // Storage/ext/ABCDEF/hash(partition name) |
| 221 // | 221 // |
| 222 // The code in GetStoragePartitionPath() constructs these path names. | 222 // The code in GetStoragePartitionPath() constructs these path names. |
| 223 // | 223 // |
| 224 // TODO(nasko): Move extension related path code out of content. | 224 // TODO(nasko): Move extension related path code out of content. |
| 225 const FilePath::CharType kStoragePartitionDirname[] = | 225 const base::FilePath::CharType kStoragePartitionDirname[] = |
| 226 FILE_PATH_LITERAL("Storage"); | 226 FILE_PATH_LITERAL("Storage"); |
| 227 const FilePath::CharType kExtensionsDirname[] = | 227 const base::FilePath::CharType kExtensionsDirname[] = |
| 228 FILE_PATH_LITERAL("ext"); | 228 FILE_PATH_LITERAL("ext"); |
| 229 const FilePath::CharType kDefaultPartitionDirname[] = | 229 const base::FilePath::CharType kDefaultPartitionDirname[] = |
| 230 FILE_PATH_LITERAL("def"); | 230 FILE_PATH_LITERAL("def"); |
| 231 const FilePath::CharType kTrashDirname[] = | 231 const base::FilePath::CharType kTrashDirname[] = |
| 232 FILE_PATH_LITERAL("trash"); | 232 FILE_PATH_LITERAL("trash"); |
| 233 | 233 |
| 234 // Because partition names are user specified, they can be arbitrarily long | 234 // Because partition names are user specified, they can be arbitrarily long |
| 235 // which makes them unsuitable for paths names. We use a truncation of a | 235 // which makes them unsuitable for paths names. We use a truncation of a |
| 236 // SHA256 hash to perform a deterministic shortening of the string. The | 236 // SHA256 hash to perform a deterministic shortening of the string. The |
| 237 // kPartitionNameHashBytes constant controls the length of the truncation. | 237 // kPartitionNameHashBytes constant controls the length of the truncation. |
| 238 // We use 6 bytes, which gives us 99.999% reliability against collisions over | 238 // We use 6 bytes, which gives us 99.999% reliability against collisions over |
| 239 // 1 million partition domains. | 239 // 1 million partition domains. |
| 240 // | 240 // |
| 241 // Analysis: | 241 // Analysis: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 264 // Needed for selecting all files in ObliterateOneDirectory() below. | 264 // Needed for selecting all files in ObliterateOneDirectory() below. |
| 265 #if defined(OS_POSIX) | 265 #if defined(OS_POSIX) |
| 266 const int kAllFileTypes = file_util::FileEnumerator::FILES | | 266 const int kAllFileTypes = file_util::FileEnumerator::FILES | |
| 267 file_util::FileEnumerator::DIRECTORIES | | 267 file_util::FileEnumerator::DIRECTORIES | |
| 268 file_util::FileEnumerator::SHOW_SYM_LINKS; | 268 file_util::FileEnumerator::SHOW_SYM_LINKS; |
| 269 #else | 269 #else |
| 270 const int kAllFileTypes = file_util::FileEnumerator::FILES | | 270 const int kAllFileTypes = file_util::FileEnumerator::FILES | |
| 271 file_util::FileEnumerator::DIRECTORIES; | 271 file_util::FileEnumerator::DIRECTORIES; |
| 272 #endif | 272 #endif |
| 273 | 273 |
| 274 FilePath GetStoragePartitionDomainPath( | 274 base::FilePath GetStoragePartitionDomainPath( |
| 275 const std::string& partition_domain) { | 275 const std::string& partition_domain) { |
| 276 CHECK(IsStringUTF8(partition_domain)); | 276 CHECK(IsStringUTF8(partition_domain)); |
| 277 | 277 |
| 278 return FilePath(kStoragePartitionDirname).Append(kExtensionsDirname) | 278 return base::FilePath(kStoragePartitionDirname).Append(kExtensionsDirname) |
| 279 .Append(FilePath::FromUTF8Unsafe(partition_domain)); | 279 .Append(base::FilePath::FromUTF8Unsafe(partition_domain)); |
| 280 } | 280 } |
| 281 | 281 |
| 282 // Helper function for doing a depth-first deletion of the data on disk. | 282 // Helper function for doing a depth-first deletion of the data on disk. |
| 283 // Examines paths directly in |current_dir| (no recursion) and tries to | 283 // Examines paths directly in |current_dir| (no recursion) and tries to |
| 284 // delete from disk anything that is in, or isn't a parent of something in | 284 // delete from disk anything that is in, or isn't a parent of something in |
| 285 // |paths_to_keep|. Paths that need further expansion are added to | 285 // |paths_to_keep|. Paths that need further expansion are added to |
| 286 // |paths_to_consider|. | 286 // |paths_to_consider|. |
| 287 void ObliterateOneDirectory(const FilePath& current_dir, | 287 void ObliterateOneDirectory(const base::FilePath& current_dir, |
| 288 const std::vector<FilePath>& paths_to_keep, | 288 const std::vector<base::FilePath>& paths_to_keep, |
| 289 std::vector<FilePath>* paths_to_consider) { | 289 std::vector<base::FilePath>* paths_to_consider) { |
| 290 CHECK(current_dir.IsAbsolute()); | 290 CHECK(current_dir.IsAbsolute()); |
| 291 | 291 |
| 292 file_util::FileEnumerator enumerator(current_dir, false, kAllFileTypes); | 292 file_util::FileEnumerator enumerator(current_dir, false, kAllFileTypes); |
| 293 for (FilePath to_delete = enumerator.Next(); !to_delete.empty(); | 293 for (base::FilePath to_delete = enumerator.Next(); !to_delete.empty(); |
| 294 to_delete = enumerator.Next()) { | 294 to_delete = enumerator.Next()) { |
| 295 // Enum tracking which of the 3 possible actions to take for |to_delete|. | 295 // Enum tracking which of the 3 possible actions to take for |to_delete|. |
| 296 enum { kSkip, kEnqueue, kDelete } action = kDelete; | 296 enum { kSkip, kEnqueue, kDelete } action = kDelete; |
| 297 | 297 |
| 298 for (std::vector<FilePath>::const_iterator to_keep = paths_to_keep.begin(); | 298 for (std::vector<base::FilePath>::const_iterator to_keep = |
| 299 paths_to_keep.begin(); |
| 299 to_keep != paths_to_keep.end(); | 300 to_keep != paths_to_keep.end(); |
| 300 ++to_keep) { | 301 ++to_keep) { |
| 301 if (to_delete == *to_keep) { | 302 if (to_delete == *to_keep) { |
| 302 action = kSkip; | 303 action = kSkip; |
| 303 break; | 304 break; |
| 304 } else if (to_delete.IsParent(*to_keep)) { | 305 } else if (to_delete.IsParent(*to_keep)) { |
| 305 // |to_delete| contains a path to keep. Add to stack for further | 306 // |to_delete| contains a path to keep. Add to stack for further |
| 306 // processing. | 307 // processing. |
| 307 action = kEnqueue; | 308 action = kEnqueue; |
| 308 break; | 309 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 322 break; | 323 break; |
| 323 } | 324 } |
| 324 } | 325 } |
| 325 } | 326 } |
| 326 | 327 |
| 327 // Synchronously attempts to delete |unnormalized_root|, preserving only | 328 // Synchronously attempts to delete |unnormalized_root|, preserving only |
| 328 // entries in |paths_to_keep|. If there are no entries in |paths_to_keep| on | 329 // entries in |paths_to_keep|. If there are no entries in |paths_to_keep| on |
| 329 // disk, then it completely removes |unnormalized_root|. All paths must be | 330 // disk, then it completely removes |unnormalized_root|. All paths must be |
| 330 // absolute paths. | 331 // absolute paths. |
| 331 void BlockingObliteratePath( | 332 void BlockingObliteratePath( |
| 332 const FilePath& unnormalized_browser_context_root, | 333 const base::FilePath& unnormalized_browser_context_root, |
| 333 const FilePath& unnormalized_root, | 334 const base::FilePath& unnormalized_root, |
| 334 const std::vector<FilePath>& paths_to_keep, | 335 const std::vector<base::FilePath>& paths_to_keep, |
| 335 const scoped_refptr<base::TaskRunner>& closure_runner, | 336 const scoped_refptr<base::TaskRunner>& closure_runner, |
| 336 const base::Closure& on_gc_required) { | 337 const base::Closure& on_gc_required) { |
| 337 // Early exit required because file_util::AbsolutePath() will fail on POSIX | 338 // Early exit required because file_util::AbsolutePath() will fail on POSIX |
| 338 // if |unnormalized_root| does not exist. This is safe because there is | 339 // if |unnormalized_root| does not exist. This is safe because there is |
| 339 // nothing to do in this situation anwyays. | 340 // nothing to do in this situation anwyays. |
| 340 if (!file_util::PathExists(unnormalized_root)) { | 341 if (!file_util::PathExists(unnormalized_root)) { |
| 341 return; | 342 return; |
| 342 } | 343 } |
| 343 | 344 |
| 344 // Never try to obliterate things outside of the browser context root or the | 345 // Never try to obliterate things outside of the browser context root or the |
| 345 // browser context root itself. Die hard. | 346 // browser context root itself. Die hard. |
| 346 FilePath root = unnormalized_root; | 347 base::FilePath root = unnormalized_root; |
| 347 FilePath browser_context_root = unnormalized_browser_context_root; | 348 base::FilePath browser_context_root = unnormalized_browser_context_root; |
| 348 CHECK(file_util::AbsolutePath(&root)); | 349 CHECK(file_util::AbsolutePath(&root)); |
| 349 CHECK(file_util::AbsolutePath(&browser_context_root)); | 350 CHECK(file_util::AbsolutePath(&browser_context_root)); |
| 350 CHECK(file_util::ContainsPath(browser_context_root, root) && | 351 CHECK(file_util::ContainsPath(browser_context_root, root) && |
| 351 browser_context_root != root); | 352 browser_context_root != root); |
| 352 | 353 |
| 353 // Reduce |paths_to_keep| set to those under the root and actually on disk. | 354 // Reduce |paths_to_keep| set to those under the root and actually on disk. |
| 354 std::vector<FilePath> valid_paths_to_keep; | 355 std::vector<base::FilePath> valid_paths_to_keep; |
| 355 for (std::vector<FilePath>::const_iterator it = paths_to_keep.begin(); | 356 for (std::vector<base::FilePath>::const_iterator it = paths_to_keep.begin(); |
| 356 it != paths_to_keep.end(); | 357 it != paths_to_keep.end(); |
| 357 ++it) { | 358 ++it) { |
| 358 if (root.IsParent(*it) && file_util::PathExists(*it)) | 359 if (root.IsParent(*it) && file_util::PathExists(*it)) |
| 359 valid_paths_to_keep.push_back(*it); | 360 valid_paths_to_keep.push_back(*it); |
| 360 } | 361 } |
| 361 | 362 |
| 362 // If none of the |paths_to_keep| are valid anymore then we just whack the | 363 // If none of the |paths_to_keep| are valid anymore then we just whack the |
| 363 // root and be done with it. Otherwise, signal garbage collection and do | 364 // root and be done with it. Otherwise, signal garbage collection and do |
| 364 // a best-effort delete of the on-disk structures. | 365 // a best-effort delete of the on-disk structures. |
| 365 if (valid_paths_to_keep.empty()) { | 366 if (valid_paths_to_keep.empty()) { |
| 366 file_util::Delete(root, true); | 367 file_util::Delete(root, true); |
| 367 return; | 368 return; |
| 368 } | 369 } |
| 369 closure_runner->PostTask(FROM_HERE, on_gc_required); | 370 closure_runner->PostTask(FROM_HERE, on_gc_required); |
| 370 | 371 |
| 371 // Otherwise, start at the root and delete everything that is not in | 372 // Otherwise, start at the root and delete everything that is not in |
| 372 // |valid_paths_to_keep|. | 373 // |valid_paths_to_keep|. |
| 373 std::vector<FilePath> paths_to_consider; | 374 std::vector<base::FilePath> paths_to_consider; |
| 374 paths_to_consider.push_back(root); | 375 paths_to_consider.push_back(root); |
| 375 while(!paths_to_consider.empty()) { | 376 while(!paths_to_consider.empty()) { |
| 376 FilePath path = paths_to_consider.back(); | 377 base::FilePath path = paths_to_consider.back(); |
| 377 paths_to_consider.pop_back(); | 378 paths_to_consider.pop_back(); |
| 378 ObliterateOneDirectory(path, valid_paths_to_keep, &paths_to_consider); | 379 ObliterateOneDirectory(path, valid_paths_to_keep, &paths_to_consider); |
| 379 } | 380 } |
| 380 } | 381 } |
| 381 | 382 |
| 382 // Deletes all entries inside the |storage_root| that are not in the | 383 // Deletes all entries inside the |storage_root| that are not in the |
| 383 // |active_paths|. Deletion is done in 2 steps: | 384 // |active_paths|. Deletion is done in 2 steps: |
| 384 // | 385 // |
| 385 // (1) Moving all garbage collected paths into a trash directory. | 386 // (1) Moving all garbage collected paths into a trash directory. |
| 386 // (2) Asynchronously deleting the trash directory. | 387 // (2) Asynchronously deleting the trash directory. |
| 387 // | 388 // |
| 388 // The deletion is asynchronous because after (1) completes, calling code can | 389 // The deletion is asynchronous because after (1) completes, calling code can |
| 389 // safely continue to use the paths that had just been garbage collected | 390 // safely continue to use the paths that had just been garbage collected |
| 390 // without fear of race conditions. | 391 // without fear of race conditions. |
| 391 // | 392 // |
| 392 // This code also ignores failed moves rather than attempting a smarter retry. | 393 // This code also ignores failed moves rather than attempting a smarter retry. |
| 393 // Moves shouldn't fail here unless there is some out-of-band error (eg., | 394 // Moves shouldn't fail here unless there is some out-of-band error (eg., |
| 394 // FS corruption). Retry logic is dangerous in the general case because | 395 // FS corruption). Retry logic is dangerous in the general case because |
| 395 // there is not necessarily a guaranteed case where the logic may succeed. | 396 // there is not necessarily a guaranteed case where the logic may succeed. |
| 396 // | 397 // |
| 397 // This function is still named BlockingGarbageCollect() because it does | 398 // This function is still named BlockingGarbageCollect() because it does |
| 398 // execute a few filesystem operations synchronously. | 399 // execute a few filesystem operations synchronously. |
| 399 void BlockingGarbageCollect( | 400 void BlockingGarbageCollect( |
| 400 const FilePath& storage_root, | 401 const base::FilePath& storage_root, |
| 401 const scoped_refptr<base::TaskRunner>& file_access_runner, | 402 const scoped_refptr<base::TaskRunner>& file_access_runner, |
| 402 scoped_ptr<base::hash_set<FilePath> > active_paths) { | 403 scoped_ptr<base::hash_set<base::FilePath> > active_paths) { |
| 403 CHECK(storage_root.IsAbsolute()); | 404 CHECK(storage_root.IsAbsolute()); |
| 404 | 405 |
| 405 file_util::FileEnumerator enumerator(storage_root, false, kAllFileTypes); | 406 file_util::FileEnumerator enumerator(storage_root, false, kAllFileTypes); |
| 406 FilePath trash_directory; | 407 base::FilePath trash_directory; |
| 407 if (!file_util::CreateTemporaryDirInDir(storage_root, kTrashDirname, | 408 if (!file_util::CreateTemporaryDirInDir(storage_root, kTrashDirname, |
| 408 &trash_directory)) { | 409 &trash_directory)) { |
| 409 // Unable to continue without creating the trash directory so give up. | 410 // Unable to continue without creating the trash directory so give up. |
| 410 return; | 411 return; |
| 411 } | 412 } |
| 412 for (FilePath path = enumerator.Next(); !path.empty(); | 413 for (base::FilePath path = enumerator.Next(); !path.empty(); |
| 413 path = enumerator.Next()) { | 414 path = enumerator.Next()) { |
| 414 if (active_paths->find(path) == active_paths->end() && | 415 if (active_paths->find(path) == active_paths->end() && |
| 415 path != trash_directory) { | 416 path != trash_directory) { |
| 416 // Since |trash_directory| is unique for each run of this function there | 417 // Since |trash_directory| is unique for each run of this function there |
| 417 // can be no colllisions on the move. | 418 // can be no colllisions on the move. |
| 418 file_util::Move(path, trash_directory.Append(path.BaseName())); | 419 file_util::Move(path, trash_directory.Append(path.BaseName())); |
| 419 } | 420 } |
| 420 } | 421 } |
| 421 | 422 |
| 422 file_access_runner->PostTask( | 423 file_access_runner->PostTask( |
| 423 FROM_HERE, | 424 FROM_HERE, |
| 424 base::Bind(base::IgnoreResult(&file_util::Delete), trash_directory, | 425 base::Bind(base::IgnoreResult(&file_util::Delete), trash_directory, |
| 425 true)); | 426 true)); |
| 426 } | 427 } |
| 427 | 428 |
| 428 } // namespace | 429 } // namespace |
| 429 | 430 |
| 430 // static | 431 // static |
| 431 FilePath StoragePartitionImplMap::GetStoragePartitionPath( | 432 base::FilePath StoragePartitionImplMap::GetStoragePartitionPath( |
| 432 const std::string& partition_domain, | 433 const std::string& partition_domain, |
| 433 const std::string& partition_name) { | 434 const std::string& partition_name) { |
| 434 if (partition_domain.empty()) | 435 if (partition_domain.empty()) |
| 435 return FilePath(); | 436 return base::FilePath(); |
| 436 | 437 |
| 437 FilePath path = GetStoragePartitionDomainPath(partition_domain); | 438 base::FilePath path = GetStoragePartitionDomainPath(partition_domain); |
| 438 | 439 |
| 439 // TODO(ajwong): Mangle in-memory into this somehow, either by putting | 440 // TODO(ajwong): Mangle in-memory into this somehow, either by putting |
| 440 // it into the partition_name, or by manually adding another path component | 441 // it into the partition_name, or by manually adding another path component |
| 441 // here. Otherwise, it's possible to have an in-memory StoragePartition and | 442 // here. Otherwise, it's possible to have an in-memory StoragePartition and |
| 442 // a persistent one that return the same FilePath for GetPath(). | 443 // a persistent one that return the same FilePath for GetPath(). |
| 443 if (!partition_name.empty()) { | 444 if (!partition_name.empty()) { |
| 444 // For analysis of why we can ignore collisions, see the comment above | 445 // For analysis of why we can ignore collisions, see the comment above |
| 445 // kPartitionNameHashBytes. | 446 // kPartitionNameHashBytes. |
| 446 char buffer[kPartitionNameHashBytes]; | 447 char buffer[kPartitionNameHashBytes]; |
| 447 crypto::SHA256HashString(partition_name, &buffer[0], | 448 crypto::SHA256HashString(partition_name, &buffer[0], |
| (...skipping 24 matching lines...) Expand all Loading... |
| 472 const std::string& partition_name, | 473 const std::string& partition_name, |
| 473 bool in_memory) { | 474 bool in_memory) { |
| 474 // Find the previously created partition if it's available. | 475 // Find the previously created partition if it's available. |
| 475 StoragePartitionConfig partition_config( | 476 StoragePartitionConfig partition_config( |
| 476 partition_domain, partition_name, in_memory); | 477 partition_domain, partition_name, in_memory); |
| 477 | 478 |
| 478 PartitionMap::const_iterator it = partitions_.find(partition_config); | 479 PartitionMap::const_iterator it = partitions_.find(partition_config); |
| 479 if (it != partitions_.end()) | 480 if (it != partitions_.end()) |
| 480 return it->second; | 481 return it->second; |
| 481 | 482 |
| 482 FilePath partition_path = | 483 base::FilePath partition_path = |
| 483 browser_context_->GetPath().Append( | 484 browser_context_->GetPath().Append( |
| 484 GetStoragePartitionPath(partition_domain, partition_name)); | 485 GetStoragePartitionPath(partition_domain, partition_name)); |
| 485 StoragePartitionImpl* partition = | 486 StoragePartitionImpl* partition = |
| 486 StoragePartitionImpl::Create(browser_context_, in_memory, | 487 StoragePartitionImpl::Create(browser_context_, in_memory, |
| 487 partition_path); | 488 partition_path); |
| 488 partitions_[partition_config] = partition; | 489 partitions_[partition_config] = partition; |
| 489 | 490 |
| 490 // These calls must happen after StoragePartitionImpl::Create(). | 491 // These calls must happen after StoragePartitionImpl::Create(). |
| 491 partition->SetURLRequestContext( | 492 partition->SetURLRequestContext( |
| 492 partition_domain.empty() ? | 493 partition_domain.empty() ? |
| (...skipping 24 matching lines...) Expand all Loading... |
| 517 browser_context_, site, false, &partition_domain, | 518 browser_context_, site, false, &partition_domain, |
| 518 &partition_name, &in_memory); | 519 &partition_name, &in_memory); |
| 519 | 520 |
| 520 // Find the active partitions for the domain. Because these partitions are | 521 // Find the active partitions for the domain. Because these partitions are |
| 521 // active, it is not possible to just delete the directories that contain | 522 // active, it is not possible to just delete the directories that contain |
| 522 // the backing data structures without causing the browser to crash. Instead, | 523 // the backing data structures without causing the browser to crash. Instead, |
| 523 // of deleteing the directory, we tell each storage context later to | 524 // of deleteing the directory, we tell each storage context later to |
| 524 // remove any data they have saved. This will leave the directory structure | 525 // remove any data they have saved. This will leave the directory structure |
| 525 // intact but it will only contain empty databases. | 526 // intact but it will only contain empty databases. |
| 526 std::vector<StoragePartitionImpl*> active_partitions; | 527 std::vector<StoragePartitionImpl*> active_partitions; |
| 527 std::vector<FilePath> paths_to_keep; | 528 std::vector<base::FilePath> paths_to_keep; |
| 528 for (PartitionMap::const_iterator it = partitions_.begin(); | 529 for (PartitionMap::const_iterator it = partitions_.begin(); |
| 529 it != partitions_.end(); | 530 it != partitions_.end(); |
| 530 ++it) { | 531 ++it) { |
| 531 const StoragePartitionConfig& config = it->first; | 532 const StoragePartitionConfig& config = it->first; |
| 532 if (config.partition_domain == partition_domain) { | 533 if (config.partition_domain == partition_domain) { |
| 533 it->second->AsyncClearAllData(); | 534 it->second->AsyncClearAllData(); |
| 534 if (!config.in_memory) { | 535 if (!config.in_memory) { |
| 535 paths_to_keep.push_back(it->second->GetPath()); | 536 paths_to_keep.push_back(it->second->GetPath()); |
| 536 } | 537 } |
| 537 } | 538 } |
| 538 } | 539 } |
| 539 | 540 |
| 540 // Start a best-effort delete of the on-disk storage excluding paths that are | 541 // Start a best-effort delete of the on-disk storage excluding paths that are |
| 541 // known to still be in use. This is to delete any previously created | 542 // known to still be in use. This is to delete any previously created |
| 542 // StoragePartition state that just happens to not have been used during this | 543 // StoragePartition state that just happens to not have been used during this |
| 543 // run of the browser. | 544 // run of the browser. |
| 544 FilePath domain_root = browser_context_->GetPath().Append( | 545 base::FilePath domain_root = browser_context_->GetPath().Append( |
| 545 GetStoragePartitionDomainPath(partition_domain)); | 546 GetStoragePartitionDomainPath(partition_domain)); |
| 546 | 547 |
| 547 BrowserThread::PostBlockingPoolTask( | 548 BrowserThread::PostBlockingPoolTask( |
| 548 FROM_HERE, | 549 FROM_HERE, |
| 549 base::Bind(&BlockingObliteratePath, browser_context_->GetPath(), | 550 base::Bind(&BlockingObliteratePath, browser_context_->GetPath(), |
| 550 domain_root, paths_to_keep, | 551 domain_root, paths_to_keep, |
| 551 base::MessageLoopProxy::current(), on_gc_required)); | 552 base::MessageLoopProxy::current(), on_gc_required)); |
| 552 } | 553 } |
| 553 | 554 |
| 554 void StoragePartitionImplMap::GarbageCollect( | 555 void StoragePartitionImplMap::GarbageCollect( |
| 555 scoped_ptr<base::hash_set<FilePath> > active_paths, | 556 scoped_ptr<base::hash_set<base::FilePath> > active_paths, |
| 556 const base::Closure& done) { | 557 const base::Closure& done) { |
| 557 // Include all paths for current StoragePartitions in the active_paths since | 558 // Include all paths for current StoragePartitions in the active_paths since |
| 558 // they cannot be deleted safely. | 559 // they cannot be deleted safely. |
| 559 for (PartitionMap::const_iterator it = partitions_.begin(); | 560 for (PartitionMap::const_iterator it = partitions_.begin(); |
| 560 it != partitions_.end(); | 561 it != partitions_.end(); |
| 561 ++it) { | 562 ++it) { |
| 562 const StoragePartitionConfig& config = it->first; | 563 const StoragePartitionConfig& config = it->first; |
| 563 if (!config.in_memory) | 564 if (!config.in_memory) |
| 564 active_paths->insert(it->second->GetPath()); | 565 active_paths->insert(it->second->GetPath()); |
| 565 } | 566 } |
| 566 | 567 |
| 567 // Find the directory holding the StoragePartitions and delete everything in | 568 // Find the directory holding the StoragePartitions and delete everything in |
| 568 // there that isn't considered active. | 569 // there that isn't considered active. |
| 569 FilePath storage_root = browser_context_->GetPath().Append( | 570 base::FilePath storage_root = browser_context_->GetPath().Append( |
| 570 GetStoragePartitionDomainPath(std::string())); | 571 GetStoragePartitionDomainPath(std::string())); |
| 571 file_access_runner_->PostTaskAndReply( | 572 file_access_runner_->PostTaskAndReply( |
| 572 FROM_HERE, | 573 FROM_HERE, |
| 573 base::Bind(&BlockingGarbageCollect, storage_root, | 574 base::Bind(&BlockingGarbageCollect, storage_root, |
| 574 file_access_runner_, | 575 file_access_runner_, |
| 575 base::Passed(&active_paths)), | 576 base::Passed(&active_paths)), |
| 576 done); | 577 done); |
| 577 } | 578 } |
| 578 | 579 |
| 579 void StoragePartitionImplMap::ForEach( | 580 void StoragePartitionImplMap::ForEach( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 597 resource_context_initialized_ = true; | 598 resource_context_initialized_ = true; |
| 598 InitializeResourceContext(browser_context_); | 599 InitializeResourceContext(browser_context_); |
| 599 } | 600 } |
| 600 | 601 |
| 601 // Check first to avoid memory leak in unittests. | 602 // Check first to avoid memory leak in unittests. |
| 602 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { | 603 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { |
| 603 BrowserThread::PostTask( | 604 BrowserThread::PostTask( |
| 604 BrowserThread::IO, FROM_HERE, | 605 BrowserThread::IO, FROM_HERE, |
| 605 base::Bind(&ChromeAppCacheService::InitializeOnIOThread, | 606 base::Bind(&ChromeAppCacheService::InitializeOnIOThread, |
| 606 partition->GetAppCacheService(), | 607 partition->GetAppCacheService(), |
| 607 in_memory ? FilePath() : | 608 in_memory ? base::FilePath() : |
| 608 partition->GetPath().Append(kAppCacheDirname), | 609 partition->GetPath().Append(kAppCacheDirname), |
| 609 browser_context_->GetResourceContext(), | 610 browser_context_->GetResourceContext(), |
| 610 make_scoped_refptr(partition->GetURLRequestContext()), | 611 make_scoped_refptr(partition->GetURLRequestContext()), |
| 611 make_scoped_refptr( | 612 make_scoped_refptr( |
| 612 browser_context_->GetSpecialStoragePolicy()))); | 613 browser_context_->GetSpecialStoragePolicy()))); |
| 613 | 614 |
| 614 // Add content's URLRequestContext's hooks. | 615 // Add content's URLRequestContext's hooks. |
| 615 BrowserThread::PostTask( | 616 BrowserThread::PostTask( |
| 616 BrowserThread::IO, FROM_HERE, | 617 BrowserThread::IO, FROM_HERE, |
| 617 base::Bind( | 618 base::Bind( |
| 618 &InitializeURLRequestContext, | 619 &InitializeURLRequestContext, |
| 619 make_scoped_refptr(partition->GetURLRequestContext()), | 620 make_scoped_refptr(partition->GetURLRequestContext()), |
| 620 make_scoped_refptr(partition->GetAppCacheService()), | 621 make_scoped_refptr(partition->GetAppCacheService()), |
| 621 make_scoped_refptr(partition->GetFileSystemContext()), | 622 make_scoped_refptr(partition->GetFileSystemContext()), |
| 622 make_scoped_refptr( | 623 make_scoped_refptr( |
| 623 ChromeBlobStorageContext::GetFor(browser_context_)), | 624 ChromeBlobStorageContext::GetFor(browser_context_)), |
| 624 browser_context_->GetResourceContext(), | 625 browser_context_->GetResourceContext(), |
| 625 browser_context_->IsOffTheRecord())); | 626 browser_context_->IsOffTheRecord())); |
| 626 | 627 |
| 627 // We do not call InitializeURLRequestContext() for media contexts because, | 628 // We do not call InitializeURLRequestContext() for media contexts because, |
| 628 // other than the HTTP cache, the media contexts share the same backing | 629 // other than the HTTP cache, the media contexts share the same backing |
| 629 // objects as their associated "normal" request context. Thus, the previous | 630 // objects as their associated "normal" request context. Thus, the previous |
| 630 // call serves to initialize the media request context for this storage | 631 // call serves to initialize the media request context for this storage |
| 631 // partition as well. | 632 // partition as well. |
| 632 } | 633 } |
| 633 } | 634 } |
| 634 | 635 |
| 635 } // namespace content | 636 } // namespace content |
| OLD | NEW |