| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "app/sql/connection.h" | 9 #include "app/sql/connection.h" |
| 10 #include "app/sql/diagnostic_error_delegate.h" | 10 #include "app/sql/diagnostic_error_delegate.h" |
| 11 #include "app/sql/meta_table.h" | 11 #include "app/sql/meta_table.h" |
| 12 #include "app/sql/statement.h" | 12 #include "app/sql/statement.h" |
| 13 #include "app/sql/transaction.h" | 13 #include "app/sql/transaction.h" |
| 14 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
| 15 #include "base/file_path.h" | |
| 16 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 16 #include "base/string_util.h" |
| 17 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 19 #include "webkit/database/databases_table.h" | 19 #include "webkit/database/databases_table.h" |
| 20 #include "webkit/database/quota_table.h" | 20 #include "webkit/database/quota_table.h" |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 class HistogramUniquifier { | 24 class HistogramUniquifier { |
| 25 public: | 25 public: |
| 26 static const char* name() { return "Sqlite.DatabaseTracker.Error"; } | 26 static const char* name() { return "Sqlite.DatabaseTracker.Error"; } |
| 27 }; | 27 }; |
| 28 | 28 |
| 29 sql::ErrorDelegate* GetErrorHandlerForTrackerDb() { | 29 sql::ErrorDelegate* GetErrorHandlerForTrackerDb() { |
| 30 return new sql::DiagnosticErrorDelegate<HistogramUniquifier>(); | 30 return new sql::DiagnosticErrorDelegate<HistogramUniquifier>(); |
| 31 } | 31 } |
| 32 | 32 |
| 33 } // anon namespace | 33 } // anon namespace |
| 34 | 34 |
| 35 namespace webkit_database { | 35 namespace webkit_database { |
| 36 | 36 |
| 37 const FilePath::CharType kDatabaseDirectoryName[] = | 37 const FilePath::CharType kDatabaseDirectoryName[] = |
| 38 FILE_PATH_LITERAL("databases"); | 38 FILE_PATH_LITERAL("databases"); |
| 39 const FilePath::CharType kIncognitoDatabaseDirectoryName[] = |
| 40 FILE_PATH_LITERAL("databases-incognito"); |
| 39 const FilePath::CharType kTrackerDatabaseFileName[] = | 41 const FilePath::CharType kTrackerDatabaseFileName[] = |
| 40 FILE_PATH_LITERAL("Databases.db"); | 42 FILE_PATH_LITERAL("Databases.db"); |
| 41 static const int kCurrentVersion = 2; | 43 static const int kCurrentVersion = 2; |
| 42 static const int kCompatibleVersion = 1; | 44 static const int kCompatibleVersion = 1; |
| 43 static const char* kExtensionOriginIdentifierPrefix = "chrome-extension_"; | 45 static const char* kExtensionOriginIdentifierPrefix = "chrome-extension_"; |
| 44 | 46 |
| 45 DatabaseTracker::DatabaseTracker(const FilePath& profile_path) | 47 DatabaseTracker::DatabaseTracker(const FilePath& profile_path, |
| 48 bool is_incognito) |
| 46 : is_initialized_(false), | 49 : is_initialized_(false), |
| 47 is_incognito_(profile_path.empty()), | 50 is_incognito_(is_incognito), |
| 51 shutting_down_(false), |
| 52 profile_path_(profile_path), |
| 48 db_dir_(is_incognito_ ? | 53 db_dir_(is_incognito_ ? |
| 49 FilePath() : profile_path.Append(kDatabaseDirectoryName)), | 54 profile_path_.Append(kIncognitoDatabaseDirectoryName) : |
| 55 profile_path_.Append(kDatabaseDirectoryName)), |
| 50 db_(new sql::Connection()), | 56 db_(new sql::Connection()), |
| 51 databases_table_(NULL), | 57 databases_table_(NULL), |
| 52 meta_table_(NULL), | 58 meta_table_(NULL), |
| 53 default_quota_(5 * 1024 * 1024) { | 59 default_quota_(5 * 1024 * 1024), |
| 60 incognito_origin_directories_generator_(0) { |
| 54 } | 61 } |
| 55 | 62 |
| 56 DatabaseTracker::~DatabaseTracker() { | 63 DatabaseTracker::~DatabaseTracker() { |
| 57 DCHECK(dbs_to_be_deleted_.empty()); | 64 DCHECK(dbs_to_be_deleted_.empty()); |
| 58 DCHECK(deletion_callbacks_.empty()); | 65 DCHECK(deletion_callbacks_.empty()); |
| 59 } | 66 } |
| 60 | 67 |
| 61 void DatabaseTracker::SetDefaultQuota(int64 quota) { | 68 void DatabaseTracker::SetDefaultQuota(int64 quota) { |
| 62 default_quota_ = quota; | 69 default_quota_ = quota; |
| 63 ClearAllCachedOriginInfo(); | 70 ClearAllCachedOriginInfo(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 void DatabaseTracker::RemoveObserver(Observer* observer) { | 168 void DatabaseTracker::RemoveObserver(Observer* observer) { |
| 162 // When we remove a listener, we do not know which cached information | 169 // When we remove a listener, we do not know which cached information |
| 163 // is still needed and which information can be discarded. So we just | 170 // is still needed and which information can be discarded. So we just |
| 164 // clear all caches and re-populate them as needed. | 171 // clear all caches and re-populate them as needed. |
| 165 observers_.RemoveObserver(observer); | 172 observers_.RemoveObserver(observer); |
| 166 ClearAllCachedOriginInfo(); | 173 ClearAllCachedOriginInfo(); |
| 167 } | 174 } |
| 168 | 175 |
| 169 void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() { | 176 void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() { |
| 170 ClearAllCachedOriginInfo(); | 177 ClearAllCachedOriginInfo(); |
| 171 meta_table_.reset(NULL); | 178 |
| 172 databases_table_.reset(NULL); | 179 if (!is_incognito_) { |
| 173 quota_table_.reset(NULL); | 180 meta_table_.reset(NULL); |
| 174 db_->Close(); | 181 databases_table_.reset(NULL); |
| 175 is_initialized_ = false; | 182 quota_table_.reset(NULL); |
| 183 db_->Close(); |
| 184 is_initialized_ = false; |
| 185 } |
| 186 } |
| 187 |
| 188 string16 DatabaseTracker::GetOriginDirectory( |
| 189 const string16& origin_identifier) { |
| 190 if (!is_incognito_) |
| 191 return origin_identifier; |
| 192 |
| 193 OriginDirectoriesMap::const_iterator it = |
| 194 incognito_origin_directories_.find(origin_identifier); |
| 195 if (it != incognito_origin_directories_.end()) |
| 196 return it->second; |
| 197 |
| 198 string16 origin_directory = |
| 199 IntToString16(incognito_origin_directories_generator_++); |
| 200 incognito_origin_directories_[origin_identifier] = origin_directory; |
| 201 return origin_directory; |
| 176 } | 202 } |
| 177 | 203 |
| 178 FilePath DatabaseTracker::GetFullDBFilePath( | 204 FilePath DatabaseTracker::GetFullDBFilePath( |
| 179 const string16& origin_identifier, | 205 const string16& origin_identifier, |
| 180 const string16& database_name) { | 206 const string16& database_name) { |
| 181 DCHECK(!origin_identifier.empty()); | 207 DCHECK(!origin_identifier.empty()); |
| 182 DCHECK(!database_name.empty()); | 208 DCHECK(!database_name.empty()); |
| 183 if (!LazyInit()) | 209 if (!LazyInit()) |
| 184 return FilePath(); | 210 return FilePath(); |
| 185 | 211 |
| 186 int64 id = databases_table_->GetDatabaseID( | 212 int64 id = databases_table_->GetDatabaseID( |
| 187 origin_identifier, database_name); | 213 origin_identifier, database_name); |
| 188 if (id < 0) | 214 if (id < 0) |
| 189 return FilePath(); | 215 return FilePath(); |
| 190 | 216 |
| 191 FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id)); | 217 FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id)); |
| 192 return db_dir_.Append(FilePath::FromWStringHack( | 218 return db_dir_.Append(FilePath::FromWStringHack( |
| 193 UTF16ToWide(origin_identifier))).Append(file_name); | 219 UTF16ToWide(GetOriginDirectory(origin_identifier)))).Append(file_name); |
| 194 } | 220 } |
| 195 | 221 |
| 196 bool DatabaseTracker::GetAllOriginsInfo(std::vector<OriginInfo>* origins_info) { | 222 bool DatabaseTracker::GetAllOriginsInfo(std::vector<OriginInfo>* origins_info) { |
| 197 DCHECK(origins_info); | 223 DCHECK(origins_info); |
| 198 DCHECK(origins_info->empty()); | 224 DCHECK(origins_info->empty()); |
| 199 if (!LazyInit()) | 225 if (!LazyInit()) |
| 200 return false; | 226 return false; |
| 201 | 227 |
| 202 std::vector<string16> origins; | 228 std::vector<string16> origins; |
| 203 if (!databases_table_->GetAllOrigins(&origins)) | 229 if (!databases_table_->GetAllOrigins(&origins)) |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 const string16& database_name) { | 318 const string16& database_name) { |
| 293 DatabaseSet::iterator it = dbs_to_be_deleted_.find(origin_identifier); | 319 DatabaseSet::iterator it = dbs_to_be_deleted_.find(origin_identifier); |
| 294 if (it == dbs_to_be_deleted_.end()) | 320 if (it == dbs_to_be_deleted_.end()) |
| 295 return false; | 321 return false; |
| 296 | 322 |
| 297 std::set<string16>& databases = it->second; | 323 std::set<string16>& databases = it->second; |
| 298 return (databases.find(database_name) != databases.end()); | 324 return (databases.find(database_name) != databases.end()); |
| 299 } | 325 } |
| 300 | 326 |
| 301 bool DatabaseTracker::LazyInit() { | 327 bool DatabaseTracker::LazyInit() { |
| 302 if (!is_initialized_ && !is_incognito_) { | 328 if (!is_initialized_ && !shutting_down_) { |
| 303 DCHECK(!db_->is_open()); | 329 DCHECK(!db_->is_open()); |
| 304 DCHECK(!databases_table_.get()); | 330 DCHECK(!databases_table_.get()); |
| 305 DCHECK(!quota_table_.get()); | 331 DCHECK(!quota_table_.get()); |
| 306 DCHECK(!meta_table_.get()); | 332 DCHECK(!meta_table_.get()); |
| 307 | 333 |
| 308 // If the tracker database exists, but it's corrupt or doesn't | 334 // If the tracker database exists, but it's corrupt or doesn't |
| 309 // have a meta table, delete the database directory. | 335 // have a meta table, delete the database directory. |
| 310 const FilePath kTrackerDatabaseFullPath = | 336 const FilePath kTrackerDatabaseFullPath = |
| 311 db_dir_.Append(FilePath(kTrackerDatabaseFileName)); | 337 db_dir_.Append(FilePath(kTrackerDatabaseFileName)); |
| 312 if (file_util::DirectoryExists(db_dir_) && | 338 if (file_util::DirectoryExists(db_dir_) && |
| 313 file_util::PathExists(kTrackerDatabaseFullPath) && | 339 file_util::PathExists(kTrackerDatabaseFullPath) && |
| 314 (!db_->Open(kTrackerDatabaseFullPath) || | 340 (!db_->Open(kTrackerDatabaseFullPath) || |
| 315 !sql::MetaTable::DoesTableExist(db_.get()))) { | 341 !sql::MetaTable::DoesTableExist(db_.get()))) { |
| 316 db_->Close(); | 342 db_->Close(); |
| 317 if (!file_util::Delete(db_dir_, true)) | 343 if (!file_util::Delete(db_dir_, true)) |
| 318 return false; | 344 return false; |
| 319 } | 345 } |
| 320 | 346 |
| 321 db_->set_error_delegate(GetErrorHandlerForTrackerDb()); | 347 db_->set_error_delegate(GetErrorHandlerForTrackerDb()); |
| 322 | 348 |
| 323 databases_table_.reset(new DatabasesTable(db_.get())); | 349 databases_table_.reset(new DatabasesTable(db_.get())); |
| 324 quota_table_.reset(new QuotaTable(db_.get())); | 350 quota_table_.reset(new QuotaTable(db_.get())); |
| 325 meta_table_.reset(new sql::MetaTable()); | 351 meta_table_.reset(new sql::MetaTable()); |
| 326 | 352 |
| 327 is_initialized_ = | 353 is_initialized_ = |
| 328 file_util::CreateDirectory(db_dir_) && | 354 file_util::CreateDirectory(db_dir_) && |
| 329 (db_->is_open() || db_->Open(kTrackerDatabaseFullPath)) && | 355 (db_->is_open() || |
| 356 (is_incognito_ ? db_->OpenInMemory() : |
| 357 db_->Open(kTrackerDatabaseFullPath))) && |
| 330 UpgradeToCurrentVersion(); | 358 UpgradeToCurrentVersion(); |
| 331 if (!is_initialized_) { | 359 if (!is_initialized_) { |
| 332 databases_table_.reset(NULL); | 360 databases_table_.reset(NULL); |
| 333 quota_table_.reset(NULL); | 361 quota_table_.reset(NULL); |
| 334 meta_table_.reset(NULL); | 362 meta_table_.reset(NULL); |
| 335 db_->Close(); | 363 db_->Close(); |
| 336 } | 364 } |
| 337 } | 365 } |
| 338 return is_initialized_; | 366 return is_initialized_; |
| 339 } | 367 } |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 DeleteClosedDatabase(origin, db->database_name); | 585 DeleteClosedDatabase(origin, db->database_name); |
| 558 } | 586 } |
| 559 | 587 |
| 560 if (!to_be_deleted.empty()) { | 588 if (!to_be_deleted.empty()) { |
| 561 ScheduleDatabasesForDeletion(to_be_deleted, callback); | 589 ScheduleDatabasesForDeletion(to_be_deleted, callback); |
| 562 return net::ERR_IO_PENDING; | 590 return net::ERR_IO_PENDING; |
| 563 } | 591 } |
| 564 return net::OK; | 592 return net::OK; |
| 565 } | 593 } |
| 566 | 594 |
| 595 void DatabaseTracker::GetIncognitoFileHandle( |
| 596 const string16& vfs_file_name, base::PlatformFile* file_handle) const { |
| 597 DCHECK(is_incognito_); |
| 598 FileHandlesMap::const_iterator it = |
| 599 incognito_file_handles_.find(vfs_file_name); |
| 600 if (it != incognito_file_handles_.end()) |
| 601 *file_handle = it->second; |
| 602 else |
| 603 *file_handle = base::kInvalidPlatformFileValue; |
| 604 } |
| 605 |
| 606 void DatabaseTracker::SaveIncognitoFileHandle( |
| 607 const string16& vfs_file_name, const base::PlatformFile& file_handle) { |
| 608 DCHECK(is_incognito_); |
| 609 DCHECK(incognito_file_handles_.find(vfs_file_name) == |
| 610 incognito_file_handles_.end()); |
| 611 if (file_handle != base::kInvalidPlatformFileValue) |
| 612 incognito_file_handles_[vfs_file_name] = file_handle; |
| 613 } |
| 614 |
| 615 bool DatabaseTracker::CloseIncognitoFileHandle(const string16& vfs_file_name) { |
| 616 DCHECK(is_incognito_); |
| 617 DCHECK(incognito_file_handles_.find(vfs_file_name) != |
| 618 incognito_file_handles_.end()); |
| 619 |
| 620 bool handle_closed = false; |
| 621 FileHandlesMap::iterator it = incognito_file_handles_.find(vfs_file_name); |
| 622 if (it != incognito_file_handles_.end()) { |
| 623 handle_closed = !base::ClosePlatformFile(it->second); |
| 624 if (handle_closed) |
| 625 incognito_file_handles_.erase(it); |
| 626 } |
| 627 return handle_closed; |
| 628 } |
| 629 |
| 630 bool DatabaseTracker::HasSavedIncognitoFileHandle( |
| 631 const string16& vfs_file_name) const { |
| 632 return (incognito_file_handles_.find(vfs_file_name) != |
| 633 incognito_file_handles_.end()); |
| 634 } |
| 635 |
| 636 void DatabaseTracker::DeleteIncognitoDBDirectory() { |
| 637 shutting_down_ = true; |
| 638 is_initialized_ = false; |
| 639 |
| 640 for (FileHandlesMap::iterator it = incognito_file_handles_.begin(); |
| 641 it != incognito_file_handles_.end(); it++) |
| 642 base::ClosePlatformFile(it->second); |
| 643 |
| 644 FilePath incognito_db_dir = |
| 645 profile_path_.Append(kIncognitoDatabaseDirectoryName); |
| 646 if (file_util::DirectoryExists(incognito_db_dir)) |
| 647 file_util::Delete(incognito_db_dir, true); |
| 648 } |
| 649 |
| 567 // static | 650 // static |
| 568 void DatabaseTracker::ClearLocalState(const FilePath& profile_path) { | 651 void DatabaseTracker::ClearLocalState(const FilePath& profile_path) { |
| 569 FilePath db_dir = profile_path.Append(FilePath(kDatabaseDirectoryName)); | 652 FilePath db_dir = profile_path.Append(FilePath(kDatabaseDirectoryName)); |
| 570 FilePath db_tracker = db_dir.Append(FilePath(kTrackerDatabaseFileName)); | 653 FilePath db_tracker = db_dir.Append(FilePath(kTrackerDatabaseFileName)); |
| 571 if (file_util::DirectoryExists(db_dir) && | 654 if (file_util::DirectoryExists(db_dir) && |
| 572 file_util::PathExists(db_tracker)) { | 655 file_util::PathExists(db_tracker)) { |
| 573 scoped_ptr<sql::Connection> db_(new sql::Connection); | 656 scoped_ptr<sql::Connection> db_(new sql::Connection); |
| 574 if (!db_->Open(db_tracker) || | 657 if (!db_->Open(db_tracker) || |
| 575 !db_->DoesTableExist("Databases")) { | 658 !db_->DoesTableExist("Databases")) { |
| 576 db_->Close(); | 659 db_->Close(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 595 file_path = file_enumerator.Next()) { | 678 file_path = file_enumerator.Next()) { |
| 596 if (file_path.BaseName() != FilePath(kTrackerDatabaseFileName)) { | 679 if (file_path.BaseName() != FilePath(kTrackerDatabaseFileName)) { |
| 597 if (!StartsWith(file_path.BaseName().ToWStringHack(), | 680 if (!StartsWith(file_path.BaseName().ToWStringHack(), |
| 598 ASCIIToWide(kExtensionOriginIdentifierPrefix), true)) | 681 ASCIIToWide(kExtensionOriginIdentifierPrefix), true)) |
| 599 file_util::Delete(file_path, true); | 682 file_util::Delete(file_path, true); |
| 600 } | 683 } |
| 601 } | 684 } |
| 602 } | 685 } |
| 603 | 686 |
| 604 } // namespace webkit_database | 687 } // namespace webkit_database |
| OLD | NEW |