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 "webkit/database/database_tracker.h" | 5 #include "webkit/database/database_tracker.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/message_loop_proxy.h" | 13 #include "base/message_loop_proxy.h" |
14 #include "base/platform_file.h" | 14 #include "base/platform_file.h" |
15 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
18 #include "sql/connection.h" | 18 #include "sql/connection.h" |
19 #include "sql/meta_table.h" | 19 #include "sql/meta_table.h" |
20 #include "sql/transaction.h" | 20 #include "sql/transaction.h" |
21 #include "third_party/sqlite/sqlite3.h" | 21 #include "third_party/sqlite/sqlite3.h" |
22 #include "webkit/database/database_quota_client.h" | 22 #include "webkit/database/database_quota_client.h" |
23 #include "webkit/database/database_util.h" | 23 #include "webkit/database/database_util.h" |
24 #include "webkit/database/databases_table.h" | 24 #include "webkit/database/databases_table.h" |
25 #include "webkit/quota/quota_manager.h" | 25 #include "webkit/quota/quota_manager.h" |
26 #include "webkit/quota/special_storage_policy.h" | 26 #include "webkit/quota/special_storage_policy.h" |
27 | 27 |
28 namespace webkit_database { | 28 namespace webkit_database { |
29 | 29 |
30 const FilePath::CharType kDatabaseDirectoryName[] = | 30 const base::FilePath::CharType kDatabaseDirectoryName[] = |
31 FILE_PATH_LITERAL("databases"); | 31 FILE_PATH_LITERAL("databases"); |
32 const FilePath::CharType kIncognitoDatabaseDirectoryName[] = | 32 const base::FilePath::CharType kIncognitoDatabaseDirectoryName[] = |
33 FILE_PATH_LITERAL("databases-incognito"); | 33 FILE_PATH_LITERAL("databases-incognito"); |
34 const FilePath::CharType kTrackerDatabaseFileName[] = | 34 const base::FilePath::CharType kTrackerDatabaseFileName[] = |
35 FILE_PATH_LITERAL("Databases.db"); | 35 FILE_PATH_LITERAL("Databases.db"); |
36 static const int kCurrentVersion = 2; | 36 static const int kCurrentVersion = 2; |
37 static const int kCompatibleVersion = 1; | 37 static const int kCompatibleVersion = 1; |
38 | 38 |
39 const FilePath::CharType kTemporaryDirectoryPrefix[] = | 39 const base::FilePath::CharType kTemporaryDirectoryPrefix[] = |
40 FILE_PATH_LITERAL("DeleteMe"); | 40 FILE_PATH_LITERAL("DeleteMe"); |
41 const FilePath::CharType kTemporaryDirectoryPattern[] = | 41 const base::FilePath::CharType kTemporaryDirectoryPattern[] = |
42 FILE_PATH_LITERAL("DeleteMe*"); | 42 FILE_PATH_LITERAL("DeleteMe*"); |
43 | 43 |
44 OriginInfo::OriginInfo() | 44 OriginInfo::OriginInfo() |
45 : total_size_(0) {} | 45 : total_size_(0) {} |
46 | 46 |
47 OriginInfo::OriginInfo(const OriginInfo& origin_info) | 47 OriginInfo::OriginInfo(const OriginInfo& origin_info) |
48 : origin_(origin_info.origin_), | 48 : origin_(origin_info.origin_), |
49 total_size_(origin_info.total_size_), | 49 total_size_(origin_info.total_size_), |
50 database_info_(origin_info.database_info_) {} | 50 database_info_(origin_info.database_info_) {} |
51 | 51 |
(...skipping 18 matching lines...) Expand all Loading... |
70 DatabaseInfoMap::const_iterator it = database_info_.find(database_name); | 70 DatabaseInfoMap::const_iterator it = database_info_.find(database_name); |
71 if (it != database_info_.end()) | 71 if (it != database_info_.end()) |
72 return it->second.second; | 72 return it->second.second; |
73 return string16(); | 73 return string16(); |
74 } | 74 } |
75 | 75 |
76 OriginInfo::OriginInfo(const string16& origin, int64 total_size) | 76 OriginInfo::OriginInfo(const string16& origin, int64 total_size) |
77 : origin_(origin), total_size_(total_size) {} | 77 : origin_(origin), total_size_(total_size) {} |
78 | 78 |
79 DatabaseTracker::DatabaseTracker( | 79 DatabaseTracker::DatabaseTracker( |
80 const FilePath& profile_path, | 80 const base::FilePath& profile_path, |
81 bool is_incognito, | 81 bool is_incognito, |
82 quota::SpecialStoragePolicy* special_storage_policy, | 82 quota::SpecialStoragePolicy* special_storage_policy, |
83 quota::QuotaManagerProxy* quota_manager_proxy, | 83 quota::QuotaManagerProxy* quota_manager_proxy, |
84 base::MessageLoopProxy* db_tracker_thread) | 84 base::MessageLoopProxy* db_tracker_thread) |
85 : is_initialized_(false), | 85 : is_initialized_(false), |
86 is_incognito_(is_incognito), | 86 is_incognito_(is_incognito), |
87 force_keep_session_state_(false), | 87 force_keep_session_state_(false), |
88 shutting_down_(false), | 88 shutting_down_(false), |
89 profile_path_(profile_path), | 89 profile_path_(profile_path), |
90 db_dir_(is_incognito_ ? | 90 db_dir_(is_incognito_ ? |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 incognito_origin_directories_.find(origin_identifier); | 273 incognito_origin_directories_.find(origin_identifier); |
274 if (it != incognito_origin_directories_.end()) | 274 if (it != incognito_origin_directories_.end()) |
275 return it->second; | 275 return it->second; |
276 | 276 |
277 string16 origin_directory = | 277 string16 origin_directory = |
278 base::IntToString16(incognito_origin_directories_generator_++); | 278 base::IntToString16(incognito_origin_directories_generator_++); |
279 incognito_origin_directories_[origin_identifier] = origin_directory; | 279 incognito_origin_directories_[origin_identifier] = origin_directory; |
280 return origin_directory; | 280 return origin_directory; |
281 } | 281 } |
282 | 282 |
283 FilePath DatabaseTracker::GetFullDBFilePath( | 283 base::FilePath DatabaseTracker::GetFullDBFilePath( |
284 const string16& origin_identifier, | 284 const string16& origin_identifier, |
285 const string16& database_name) { | 285 const string16& database_name) { |
286 DCHECK(!origin_identifier.empty()); | 286 DCHECK(!origin_identifier.empty()); |
287 if (!LazyInit()) | 287 if (!LazyInit()) |
288 return FilePath(); | 288 return base::FilePath(); |
289 | 289 |
290 int64 id = databases_table_->GetDatabaseID( | 290 int64 id = databases_table_->GetDatabaseID( |
291 origin_identifier, database_name); | 291 origin_identifier, database_name); |
292 if (id < 0) | 292 if (id < 0) |
293 return FilePath(); | 293 return base::FilePath(); |
294 | 294 |
295 FilePath file_name = FilePath::FromWStringHack( | 295 base::FilePath file_name = base::FilePath::FromWStringHack( |
296 UTF8ToWide(base::Int64ToString(id))); | 296 UTF8ToWide(base::Int64ToString(id))); |
297 return db_dir_.Append(FilePath::FromWStringHack( | 297 return db_dir_.Append(base::FilePath::FromWStringHack( |
298 UTF16ToWide(GetOriginDirectory(origin_identifier)))).Append(file_name); | 298 UTF16ToWide(GetOriginDirectory(origin_identifier)))).Append(file_name); |
299 } | 299 } |
300 | 300 |
301 bool DatabaseTracker::GetOriginInfo(const string16& origin_identifier, | 301 bool DatabaseTracker::GetOriginInfo(const string16& origin_identifier, |
302 OriginInfo* info) { | 302 OriginInfo* info) { |
303 DCHECK(info); | 303 DCHECK(info); |
304 CachedOriginInfo* cached_info = GetCachedOriginInfo(origin_identifier); | 304 CachedOriginInfo* cached_info = GetCachedOriginInfo(origin_identifier); |
305 if (!cached_info) | 305 if (!cached_info) |
306 return false; | 306 return false; |
307 *info = OriginInfo(*cached_info); | 307 *info = OriginInfo(*cached_info); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 return false; | 345 return false; |
346 | 346 |
347 // Check if the database is opened by any renderer. | 347 // Check if the database is opened by any renderer. |
348 if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) | 348 if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) |
349 return false; | 349 return false; |
350 | 350 |
351 int64 db_file_size = quota_manager_proxy_ ? | 351 int64 db_file_size = quota_manager_proxy_ ? |
352 GetDBFileSize(origin_identifier, database_name) : 0; | 352 GetDBFileSize(origin_identifier, database_name) : 0; |
353 | 353 |
354 // Try to delete the file on the hard drive. | 354 // Try to delete the file on the hard drive. |
355 FilePath db_file = GetFullDBFilePath(origin_identifier, database_name); | 355 base::FilePath db_file = GetFullDBFilePath(origin_identifier, database_name); |
356 if (file_util::PathExists(db_file) && !file_util::Delete(db_file, false)) | 356 if (file_util::PathExists(db_file) && !file_util::Delete(db_file, false)) |
357 return false; | 357 return false; |
358 | 358 |
359 // Also delete any orphaned journal file. | 359 // Also delete any orphaned journal file. |
360 DCHECK(db_file.Extension().empty()); | 360 DCHECK(db_file.Extension().empty()); |
361 file_util::Delete(db_file.InsertBeforeExtensionASCII( | 361 file_util::Delete(db_file.InsertBeforeExtensionASCII( |
362 DatabaseUtil::kJournalFileSuffix), false); | 362 DatabaseUtil::kJournalFileSuffix), false); |
363 | 363 |
364 if (quota_manager_proxy_ && db_file_size) | 364 if (quota_manager_proxy_ && db_file_size) |
365 quota_manager_proxy_->NotifyStorageModified( | 365 quota_manager_proxy_->NotifyStorageModified( |
(...skipping 25 matching lines...) Expand all Loading... |
391 return false; | 391 return false; |
392 | 392 |
393 int64 deleted_size = 0; | 393 int64 deleted_size = 0; |
394 if (quota_manager_proxy_) { | 394 if (quota_manager_proxy_) { |
395 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); | 395 CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier); |
396 if (origin_info) | 396 if (origin_info) |
397 deleted_size = origin_info->TotalSize(); | 397 deleted_size = origin_info->TotalSize(); |
398 } | 398 } |
399 | 399 |
400 origins_info_map_.erase(origin_identifier); | 400 origins_info_map_.erase(origin_identifier); |
401 FilePath origin_dir = db_dir_.Append(FilePath::FromWStringHack( | 401 base::FilePath origin_dir = db_dir_.Append(base::FilePath::FromWStringHack( |
402 UTF16ToWide(origin_identifier))); | 402 UTF16ToWide(origin_identifier))); |
403 | 403 |
404 // Create a temporary directory to move possibly still existing databases to, | 404 // Create a temporary directory to move possibly still existing databases to, |
405 // as we can't delete the origin directory on windows if it contains opened | 405 // as we can't delete the origin directory on windows if it contains opened |
406 // files. | 406 // files. |
407 FilePath new_origin_dir; | 407 base::FilePath new_origin_dir; |
408 file_util::CreateTemporaryDirInDir(db_dir_, | 408 file_util::CreateTemporaryDirInDir(db_dir_, |
409 kTemporaryDirectoryPrefix, | 409 kTemporaryDirectoryPrefix, |
410 &new_origin_dir); | 410 &new_origin_dir); |
411 file_util::FileEnumerator databases( | 411 file_util::FileEnumerator databases( |
412 origin_dir, | 412 origin_dir, |
413 false, | 413 false, |
414 file_util::FileEnumerator::FILES); | 414 file_util::FileEnumerator::FILES); |
415 for (FilePath database = databases.Next(); !database.empty(); | 415 for (base::FilePath database = databases.Next(); !database.empty(); |
416 database = databases.Next()) { | 416 database = databases.Next()) { |
417 FilePath new_file = new_origin_dir.Append(database.BaseName()); | 417 base::FilePath new_file = new_origin_dir.Append(database.BaseName()); |
418 file_util::Move(database, new_file); | 418 file_util::Move(database, new_file); |
419 } | 419 } |
420 file_util::Delete(origin_dir, true); | 420 file_util::Delete(origin_dir, true); |
421 file_util::Delete(new_origin_dir, true); // might fail on windows. | 421 file_util::Delete(new_origin_dir, true); // might fail on windows. |
422 | 422 |
423 databases_table_->DeleteOrigin(origin_identifier); | 423 databases_table_->DeleteOrigin(origin_identifier); |
424 | 424 |
425 if (quota_manager_proxy_ && deleted_size) { | 425 if (quota_manager_proxy_ && deleted_size) { |
426 quota_manager_proxy_->NotifyStorageModified( | 426 quota_manager_proxy_->NotifyStorageModified( |
427 quota::QuotaClient::kDatabase, | 427 quota::QuotaClient::kDatabase, |
(...skipping 23 matching lines...) Expand all Loading... |
451 DCHECK(!meta_table_.get()); | 451 DCHECK(!meta_table_.get()); |
452 | 452 |
453 // If there are left-over directories from failed deletion attempts, clean | 453 // If there are left-over directories from failed deletion attempts, clean |
454 // them up. | 454 // them up. |
455 if (file_util::DirectoryExists(db_dir_)) { | 455 if (file_util::DirectoryExists(db_dir_)) { |
456 file_util::FileEnumerator directories( | 456 file_util::FileEnumerator directories( |
457 db_dir_, | 457 db_dir_, |
458 false, | 458 false, |
459 file_util::FileEnumerator::DIRECTORIES, | 459 file_util::FileEnumerator::DIRECTORIES, |
460 kTemporaryDirectoryPattern); | 460 kTemporaryDirectoryPattern); |
461 for (FilePath directory = directories.Next(); !directory.empty(); | 461 for (base::FilePath directory = directories.Next(); !directory.empty(); |
462 directory = directories.Next()) { | 462 directory = directories.Next()) { |
463 file_util::Delete(directory, true); | 463 file_util::Delete(directory, true); |
464 } | 464 } |
465 } | 465 } |
466 | 466 |
467 // If the tracker database exists, but it's corrupt or doesn't | 467 // If the tracker database exists, but it's corrupt or doesn't |
468 // have a meta table, delete the database directory. | 468 // have a meta table, delete the database directory. |
469 const FilePath kTrackerDatabaseFullPath = | 469 const base::FilePath kTrackerDatabaseFullPath = |
470 db_dir_.Append(FilePath(kTrackerDatabaseFileName)); | 470 db_dir_.Append(base::FilePath(kTrackerDatabaseFileName)); |
471 if (file_util::DirectoryExists(db_dir_) && | 471 if (file_util::DirectoryExists(db_dir_) && |
472 file_util::PathExists(kTrackerDatabaseFullPath) && | 472 file_util::PathExists(kTrackerDatabaseFullPath) && |
473 (!db_->Open(kTrackerDatabaseFullPath) || | 473 (!db_->Open(kTrackerDatabaseFullPath) || |
474 !sql::MetaTable::DoesTableExist(db_.get()))) { | 474 !sql::MetaTable::DoesTableExist(db_.get()))) { |
475 db_->Close(); | 475 db_->Close(); |
476 if (!file_util::Delete(db_dir_, true)) | 476 if (!file_util::Delete(db_dir_, true)) |
477 return false; | 477 return false; |
478 } | 478 } |
479 | 479 |
480 db_->set_error_histogram_name("Sqlite.DatabaseTracker.Error"); | 480 db_->set_error_histogram_name("Sqlite.DatabaseTracker.Error"); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 origin_info.SetDatabaseSize(it->database_name, db_file_size); | 567 origin_info.SetDatabaseSize(it->database_name, db_file_size); |
568 origin_info.SetDatabaseDescription(it->database_name, it->description); | 568 origin_info.SetDatabaseDescription(it->database_name, it->description); |
569 } | 569 } |
570 } | 570 } |
571 | 571 |
572 return &origins_info_map_[origin_identifier]; | 572 return &origins_info_map_[origin_identifier]; |
573 } | 573 } |
574 | 574 |
575 int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier, | 575 int64 DatabaseTracker::GetDBFileSize(const string16& origin_identifier, |
576 const string16& database_name) { | 576 const string16& database_name) { |
577 FilePath db_file_name = GetFullDBFilePath(origin_identifier, database_name); | 577 base::FilePath db_file_name = GetFullDBFilePath(origin_identifier, |
| 578 database_name); |
578 int64 db_file_size = 0; | 579 int64 db_file_size = 0; |
579 if (!file_util::GetFileSize(db_file_name, &db_file_size)) | 580 if (!file_util::GetFileSize(db_file_name, &db_file_size)) |
580 db_file_size = 0; | 581 db_file_size = 0; |
581 return db_file_size; | 582 return db_file_size; |
582 } | 583 } |
583 | 584 |
584 int64 DatabaseTracker::SeedOpenDatabaseInfo( | 585 int64 DatabaseTracker::SeedOpenDatabaseInfo( |
585 const string16& origin_id, const string16& name, | 586 const string16& origin_id, const string16& name, |
586 const string16& description) { | 587 const string16& description) { |
587 DCHECK(database_connections_.IsDatabaseOpened(origin_id, name)); | 588 DCHECK(database_connections_.IsDatabaseOpened(origin_id, name)); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 special_storage_policy_->IsStorageProtected( | 684 special_storage_policy_->IsStorageProtected( |
684 DatabaseUtil::GetOriginFromIdentifier(*ori))) { | 685 DatabaseUtil::GetOriginFromIdentifier(*ori))) { |
685 continue; | 686 continue; |
686 } | 687 } |
687 | 688 |
688 std::vector<DatabaseDetails> details; | 689 std::vector<DatabaseDetails> details; |
689 if (!databases_table_->GetAllDatabaseDetailsForOrigin(*ori, &details)) | 690 if (!databases_table_->GetAllDatabaseDetailsForOrigin(*ori, &details)) |
690 rv = net::ERR_FAILED; | 691 rv = net::ERR_FAILED; |
691 for (std::vector<DatabaseDetails>::const_iterator db = details.begin(); | 692 for (std::vector<DatabaseDetails>::const_iterator db = details.begin(); |
692 db != details.end(); ++db) { | 693 db != details.end(); ++db) { |
693 FilePath db_file = GetFullDBFilePath(*ori, db->database_name); | 694 base::FilePath db_file = GetFullDBFilePath(*ori, db->database_name); |
694 base::PlatformFileInfo file_info; | 695 base::PlatformFileInfo file_info; |
695 file_util::GetFileInfo(db_file, &file_info); | 696 file_util::GetFileInfo(db_file, &file_info); |
696 if (file_info.last_modified < cutoff) | 697 if (file_info.last_modified < cutoff) |
697 continue; | 698 continue; |
698 | 699 |
699 // Check if the database is opened by any renderer. | 700 // Check if the database is opened by any renderer. |
700 if (database_connections_.IsDatabaseOpened(*ori, db->database_name)) | 701 if (database_connections_.IsDatabaseOpened(*ori, db->database_name)) |
701 to_be_deleted[*ori].insert(db->database_name); | 702 to_be_deleted[*ori].insert(db->database_name); |
702 else | 703 else |
703 DeleteClosedDatabase(*ori, db->database_name); | 704 DeleteClosedDatabase(*ori, db->database_name); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 } | 783 } |
783 | 784 |
784 void DatabaseTracker::DeleteIncognitoDBDirectory() { | 785 void DatabaseTracker::DeleteIncognitoDBDirectory() { |
785 shutting_down_ = true; | 786 shutting_down_ = true; |
786 is_initialized_ = false; | 787 is_initialized_ = false; |
787 | 788 |
788 for (FileHandlesMap::iterator it = incognito_file_handles_.begin(); | 789 for (FileHandlesMap::iterator it = incognito_file_handles_.begin(); |
789 it != incognito_file_handles_.end(); it++) | 790 it != incognito_file_handles_.end(); it++) |
790 base::ClosePlatformFile(it->second); | 791 base::ClosePlatformFile(it->second); |
791 | 792 |
792 FilePath incognito_db_dir = | 793 base::FilePath incognito_db_dir = |
793 profile_path_.Append(kIncognitoDatabaseDirectoryName); | 794 profile_path_.Append(kIncognitoDatabaseDirectoryName); |
794 if (file_util::DirectoryExists(incognito_db_dir)) | 795 if (file_util::DirectoryExists(incognito_db_dir)) |
795 file_util::Delete(incognito_db_dir, true); | 796 file_util::Delete(incognito_db_dir, true); |
796 } | 797 } |
797 | 798 |
798 void DatabaseTracker::ClearSessionOnlyOrigins() { | 799 void DatabaseTracker::ClearSessionOnlyOrigins() { |
799 shutting_down_ = true; | 800 shutting_down_ = true; |
800 | 801 |
801 bool has_session_only_databases = | 802 bool has_session_only_databases = |
802 special_storage_policy_.get() && | 803 special_storage_policy_.get() && |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 if (!db_tracker_thread_->BelongsToCurrentThread()) { | 860 if (!db_tracker_thread_->BelongsToCurrentThread()) { |
860 db_tracker_thread_->PostTask( | 861 db_tracker_thread_->PostTask( |
861 FROM_HERE, | 862 FROM_HERE, |
862 base::Bind(&DatabaseTracker::SetForceKeepSessionState, this)); | 863 base::Bind(&DatabaseTracker::SetForceKeepSessionState, this)); |
863 return; | 864 return; |
864 } | 865 } |
865 force_keep_session_state_ = true; | 866 force_keep_session_state_ = true; |
866 } | 867 } |
867 | 868 |
868 } // namespace webkit_database | 869 } // namespace webkit_database |
OLD | NEW |