diff options
author | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-13 09:08:41 +0000 |
---|---|---|
committer | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-13 09:08:41 +0000 |
commit | fe615f3a28aba7377b1ef177390b67927cc32290 (patch) | |
tree | aac68857f269f74d0414627fb11657fde8706962 /webkit/database | |
parent | 517507bd359f4ab111f6c119e4fdc9bcea145fbf (diff) | |
download | chromium_src-fe615f3a28aba7377b1ef177390b67927cc32290.zip chromium_src-fe615f3a28aba7377b1ef177390b67927cc32290.tar.gz chromium_src-fe615f3a28aba7377b1ef177390b67927cc32290.tar.bz2 |
Support WebSQLDatabases in incognito mode.
BUG=43232
TEST=none
Review URL: http://codereview.chromium.org/2746003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49644 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/database')
-rw-r--r-- | webkit/database/database_tracker.cc | 109 | ||||
-rw-r--r-- | webkit/database/database_tracker.h | 39 | ||||
-rw-r--r-- | webkit/database/database_tracker_unittest.cc | 629 | ||||
-rw-r--r-- | webkit/database/vfs_backend.cc | 67 | ||||
-rw-r--r-- | webkit/database/vfs_backend.h | 12 |
5 files changed, 495 insertions, 361 deletions
diff --git a/webkit/database/database_tracker.cc b/webkit/database/database_tracker.cc index c184c8b..f18189b 100644 --- a/webkit/database/database_tracker.cc +++ b/webkit/database/database_tracker.cc @@ -12,8 +12,8 @@ #include "app/sql/statement.h" #include "app/sql/transaction.h" #include "base/basictypes.h" -#include "base/file_path.h" #include "base/file_util.h" +#include "base/string_util.h" #include "base/utf_string_conversions.h" #include "net/base/net_errors.h" #include "webkit/database/databases_table.h" @@ -36,21 +36,28 @@ namespace webkit_database { const FilePath::CharType kDatabaseDirectoryName[] = FILE_PATH_LITERAL("databases"); +const FilePath::CharType kIncognitoDatabaseDirectoryName[] = + FILE_PATH_LITERAL("databases-incognito"); const FilePath::CharType kTrackerDatabaseFileName[] = FILE_PATH_LITERAL("Databases.db"); static const int kCurrentVersion = 2; static const int kCompatibleVersion = 1; static const char* kExtensionOriginIdentifierPrefix = "chrome-extension_"; -DatabaseTracker::DatabaseTracker(const FilePath& profile_path) +DatabaseTracker::DatabaseTracker(const FilePath& profile_path, + bool is_incognito) : is_initialized_(false), - is_incognito_(profile_path.empty()), + is_incognito_(is_incognito), + shutting_down_(false), + profile_path_(profile_path), db_dir_(is_incognito_ ? - FilePath() : profile_path.Append(kDatabaseDirectoryName)), + profile_path_.Append(kIncognitoDatabaseDirectoryName) : + profile_path_.Append(kDatabaseDirectoryName)), db_(new sql::Connection()), databases_table_(NULL), meta_table_(NULL), - default_quota_(5 * 1024 * 1024) { + default_quota_(5 * 1024 * 1024), + incognito_origin_directories_generator_(0) { } DatabaseTracker::~DatabaseTracker() { @@ -168,11 +175,30 @@ void DatabaseTracker::RemoveObserver(Observer* observer) { void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() { ClearAllCachedOriginInfo(); - meta_table_.reset(NULL); - databases_table_.reset(NULL); - quota_table_.reset(NULL); - db_->Close(); - is_initialized_ = false; + + if (!is_incognito_) { + meta_table_.reset(NULL); + databases_table_.reset(NULL); + quota_table_.reset(NULL); + db_->Close(); + is_initialized_ = false; + } +} + +string16 DatabaseTracker::GetOriginDirectory( + const string16& origin_identifier) { + if (!is_incognito_) + return origin_identifier; + + OriginDirectoriesMap::const_iterator it = + incognito_origin_directories_.find(origin_identifier); + if (it != incognito_origin_directories_.end()) + return it->second; + + string16 origin_directory = + IntToString16(incognito_origin_directories_generator_++); + incognito_origin_directories_[origin_identifier] = origin_directory; + return origin_directory; } FilePath DatabaseTracker::GetFullDBFilePath( @@ -190,7 +216,7 @@ FilePath DatabaseTracker::GetFullDBFilePath( FilePath file_name = FilePath::FromWStringHack(Int64ToWString(id)); return db_dir_.Append(FilePath::FromWStringHack( - UTF16ToWide(origin_identifier))).Append(file_name); + UTF16ToWide(GetOriginDirectory(origin_identifier)))).Append(file_name); } bool DatabaseTracker::GetAllOriginsInfo(std::vector<OriginInfo>* origins_info) { @@ -299,7 +325,7 @@ bool DatabaseTracker::IsDatabaseScheduledForDeletion( } bool DatabaseTracker::LazyInit() { - if (!is_initialized_ && !is_incognito_) { + if (!is_initialized_ && !shutting_down_) { DCHECK(!db_->is_open()); DCHECK(!databases_table_.get()); DCHECK(!quota_table_.get()); @@ -326,7 +352,9 @@ bool DatabaseTracker::LazyInit() { is_initialized_ = file_util::CreateDirectory(db_dir_) && - (db_->is_open() || db_->Open(kTrackerDatabaseFullPath)) && + (db_->is_open() || + (is_incognito_ ? db_->OpenInMemory() : + db_->Open(kTrackerDatabaseFullPath))) && UpgradeToCurrentVersion(); if (!is_initialized_) { databases_table_.reset(NULL); @@ -564,6 +592,61 @@ int DatabaseTracker::DeleteDataForOrigin(const string16& origin, return net::OK; } +void DatabaseTracker::GetIncognitoFileHandle( + const string16& vfs_file_name, base::PlatformFile* file_handle) const { + DCHECK(is_incognito_); + FileHandlesMap::const_iterator it = + incognito_file_handles_.find(vfs_file_name); + if (it != incognito_file_handles_.end()) + *file_handle = it->second; + else + *file_handle = base::kInvalidPlatformFileValue; +} + +void DatabaseTracker::SaveIncognitoFileHandle( + const string16& vfs_file_name, const base::PlatformFile& file_handle) { + DCHECK(is_incognito_); + DCHECK(incognito_file_handles_.find(vfs_file_name) == + incognito_file_handles_.end()); + if (file_handle != base::kInvalidPlatformFileValue) + incognito_file_handles_[vfs_file_name] = file_handle; +} + +bool DatabaseTracker::CloseIncognitoFileHandle(const string16& vfs_file_name) { + DCHECK(is_incognito_); + DCHECK(incognito_file_handles_.find(vfs_file_name) != + incognito_file_handles_.end()); + + bool handle_closed = false; + FileHandlesMap::iterator it = incognito_file_handles_.find(vfs_file_name); + if (it != incognito_file_handles_.end()) { + handle_closed = !base::ClosePlatformFile(it->second); + if (handle_closed) + incognito_file_handles_.erase(it); + } + return handle_closed; +} + +bool DatabaseTracker::HasSavedIncognitoFileHandle( + const string16& vfs_file_name) const { + return (incognito_file_handles_.find(vfs_file_name) != + incognito_file_handles_.end()); +} + +void DatabaseTracker::DeleteIncognitoDBDirectory() { + shutting_down_ = true; + is_initialized_ = false; + + for (FileHandlesMap::iterator it = incognito_file_handles_.begin(); + it != incognito_file_handles_.end(); it++) + base::ClosePlatformFile(it->second); + + FilePath incognito_db_dir = + profile_path_.Append(kIncognitoDatabaseDirectoryName); + if (file_util::DirectoryExists(incognito_db_dir)) + file_util::Delete(incognito_db_dir, true); +} + // static void DatabaseTracker::ClearLocalState(const FilePath& profile_path) { FilePath db_dir = profile_path.Append(FilePath(kDatabaseDirectoryName)); diff --git a/webkit/database/database_tracker.h b/webkit/database/database_tracker.h index 9bad23b..55b0e12 100644 --- a/webkit/database/database_tracker.h +++ b/webkit/database/database_tracker.h @@ -10,6 +10,7 @@ #include "base/file_path.h" #include "base/observer_list.h" +#include "base/platform_file.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/string16.h" @@ -100,7 +101,7 @@ class DatabaseTracker virtual ~Observer() {} }; - explicit DatabaseTracker(const FilePath& profile_path); + DatabaseTracker(const FilePath& profile_path, bool is_incognito); void DatabaseOpened(const string16& origin_identifier, const string16& database_name, @@ -156,6 +157,18 @@ class DatabaseTracker int DeleteDataForOrigin(const string16& origin_identifier, net::CompletionCallback* callback); + bool IsIncognitoProfile() const { return is_incognito_; } + + void GetIncognitoFileHandle(const string16& vfs_file_path, + base::PlatformFile* file_handle) const; + void SaveIncognitoFileHandle(const string16& vfs_file_path, + const base::PlatformFile& file_handle); + bool CloseIncognitoFileHandle(const string16& vfs_file_path); + bool HasSavedIncognitoFileHandle(const string16& vfs_file_path) const; + + // Deletes the directory that stores all DBs in incognito mode, if it exists. + void DeleteIncognitoDBDirectory(); + static void ClearLocalState(const FilePath& profile_path); private: @@ -164,6 +177,8 @@ class DatabaseTracker typedef std::map<string16, std::set<string16> > DatabaseSet; typedef std::map<net::CompletionCallback*, DatabaseSet> PendingCompletionMap; + typedef std::map<string16, base::PlatformFile> FileHandlesMap; + typedef std::map<string16, string16> OriginDirectoriesMap; class CachedOriginInfo : public OriginInfo { public: @@ -216,8 +231,13 @@ class DatabaseTracker void ScheduleDatabasesForDeletion(const DatabaseSet& databases, net::CompletionCallback* callback); + // Returns the directory where all DB files for the given origin are stored. + string16 GetOriginDirectory(const string16& origin_identifier); + bool is_initialized_; const bool is_incognito_; + bool shutting_down_; + const FilePath profile_path_; const FilePath db_dir_; scoped_ptr<sql::Connection> db_; scoped_ptr<DatabasesTable> databases_table_; @@ -238,8 +258,21 @@ class DatabaseTracker // to quota_table_ every time an extention is loaded. std::map<string16, int64> in_memory_quotas_; - FRIEND_TEST(DatabaseTrackerTest, DatabaseTracker); - FRIEND_TEST(DatabaseTrackerTest, NoInitIncognito); + // When in incognito mode, store a DELETE_ON_CLOSE handle to each + // main DB and journal file that was accessed. When the incognito profile + // goes away (or when the browser crashes), all these handles will be + // closed, and the files will be deleted. + FileHandlesMap incognito_file_handles_; + + // In a non-incognito profile, all DBs in an origin are stored in a directory + // named after the origin. In an incognito profile though, we do not want the + // directory structure to reveal the origins visited by the user (in case the + // browser process crashes and those directories are not deleted). So we use + // this map to assign directory names that do not reveal this information. + OriginDirectoriesMap incognito_origin_directories_; + int incognito_origin_directories_generator_; + + FRIEND_TEST(DatabaseTracker, TestHelper); }; } // namespace webkit_database diff --git a/webkit/database/database_tracker_unittest.cc b/webkit/database/database_tracker_unittest.cc index 14bd480..8bb3f247 100644 --- a/webkit/database/database_tracker_unittest.cc +++ b/webkit/database/database_tracker_unittest.cc @@ -72,327 +72,326 @@ void CheckNotificationReceived(TestObserver* observer, namespace webkit_database { +// We declare a helper class, and make it a friend of DatabaseTracker using +// the FRIEND_TEST() macro, and we implement all tests we want to run as +// static methods of this class. Then we make our TEST() targets call these +// static functions. This allows us to run each test in normal mode and +// incognito mode without writing the same code twice. +class DatabaseTracker_TestHelper_Test { + public: + static void TestDeleteOpenDatabase(bool incognito_mode) { + // Initialize the tracker database. + ScopedTempDir temp_dir; + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + scoped_refptr<DatabaseTracker> tracker( + new DatabaseTracker(temp_dir.path(), incognito_mode)); + + // Create and open three databases. + int64 database_size = 0; + int64 space_available = 0; + const string16 kOrigin1 = ASCIIToUTF16("origin1"); + const string16 kOrigin2 = ASCIIToUTF16("origin2"); + const string16 kDB1 = ASCIIToUTF16("db1"); + const string16 kDB2 = ASCIIToUTF16("db2"); + const string16 kDB3 = ASCIIToUTF16("db3"); + const string16 kDescription = ASCIIToUTF16("database_description"); + + tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, + &database_size, &space_available); + tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, + &database_size, &space_available); + tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0, + &database_size, &space_available); + + EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( + FilePath::FromWStringHack(UTF16ToWide( + tracker->GetOriginDirectory(kOrigin1)))))); + EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( + FilePath::FromWStringHack(UTF16ToWide( + tracker->GetOriginDirectory(kOrigin2)))))); + EXPECT_EQ(1, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); + EXPECT_EQ(2, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2)); + EXPECT_EQ(3, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin2, kDB3), "aaa", 3)); + tracker->DatabaseModified(kOrigin1, kDB1); + tracker->DatabaseModified(kOrigin2, kDB2); + tracker->DatabaseModified(kOrigin2, kDB3); + + // Delete db1. Should also delete origin1. + TestObserver observer; + tracker->AddObserver(&observer); + TestCompletionCallback callback; + int result = tracker->DeleteDatabase(kOrigin1, kDB1, &callback); + EXPECT_EQ(net::ERR_IO_PENDING, result); + ASSERT_FALSE(callback.have_result()); + EXPECT_TRUE(observer.DidReceiveNewNotification()); + EXPECT_EQ(kOrigin1, observer.GetNotificationOriginIdentifier()); + EXPECT_EQ(kDB1, observer.GetNotificationDatabaseName()); + tracker->DatabaseClosed(kOrigin1, kDB1); + result = callback.GetResult(result); + EXPECT_EQ(net::OK, result); + EXPECT_FALSE(file_util::PathExists(tracker->DatabaseDirectory().Append( + FilePath::FromWStringHack(UTF16ToWide(kOrigin1))))); + + // Recreate db1. + tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, + &database_size, &space_available); + EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( + FilePath::FromWStringHack(UTF16ToWide( + tracker->GetOriginDirectory(kOrigin1)))))); + EXPECT_EQ(1, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); + tracker->DatabaseModified(kOrigin1, kDB1); + + // Setup file modification times. db1 and db2 are modified now, db3 three + // days ago. + EXPECT_TRUE(file_util::SetLastModifiedTime( + tracker->GetFullDBFilePath(kOrigin1, kDB1), base::Time::Now())); + EXPECT_TRUE(file_util::SetLastModifiedTime( + tracker->GetFullDBFilePath(kOrigin2, kDB2), base::Time::Now())); + base::Time three_days_ago = base::Time::Now(); + three_days_ago -= base::TimeDelta::FromDays(3); + EXPECT_TRUE(file_util::SetLastModifiedTime( + tracker->GetFullDBFilePath(kOrigin2, kDB3), three_days_ago)); + + // Delete databases modified since yesterday. + base::Time yesterday = base::Time::Now(); + yesterday -= base::TimeDelta::FromDays(1); + result = tracker->DeleteDataModifiedSince(yesterday, &callback); + EXPECT_EQ(net::ERR_IO_PENDING, result); + ASSERT_FALSE(callback.have_result()); + EXPECT_TRUE(observer.DidReceiveNewNotification()); + tracker->DatabaseClosed(kOrigin1, kDB1); + tracker->DatabaseClosed(kOrigin2, kDB2); + result = callback.GetResult(result); + EXPECT_EQ(net::OK, result); + EXPECT_FALSE(file_util::PathExists(tracker->DatabaseDirectory().Append( + FilePath::FromWStringHack(UTF16ToWide(kOrigin1))))); + EXPECT_FALSE( + file_util::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2))); + EXPECT_TRUE( + file_util::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB3))); + + tracker->DatabaseClosed(kOrigin2, kDB3); + tracker->RemoveObserver(&observer); + } + + static void TestDatabaseTracker(bool incognito_mode) { + // Initialize the tracker database. + ScopedTempDir temp_dir; + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + scoped_refptr<DatabaseTracker> tracker( + new DatabaseTracker(temp_dir.path(), incognito_mode)); + + // Add two observers. + TestObserver observer1; + TestObserver observer2; + tracker->AddObserver(&observer1); + tracker->AddObserver(&observer2); + + // Open three new databases. + int64 database_size = 0; + int64 space_available = 0; + const string16 kOrigin1 = ASCIIToUTF16("origin1"); + const string16 kOrigin2 = ASCIIToUTF16("origin2"); + const string16 kDB1 = ASCIIToUTF16("db1"); + const string16 kDB2 = ASCIIToUTF16("db2"); + const string16 kDB3 = ASCIIToUTF16("db3"); + const string16 kDescription = ASCIIToUTF16("database_description"); + + // Get the quota for kOrigin1 and kOrigin2 + DatabaseTracker::CachedOriginInfo* origin1_info = + tracker->GetCachedOriginInfo(kOrigin1); + DatabaseTracker::CachedOriginInfo* origin2_info = + tracker->GetCachedOriginInfo(kOrigin1); + EXPECT_TRUE(origin1_info); + EXPECT_TRUE(origin2_info); + int64 origin1_quota = origin1_info->Quota(); + int64 origin2_quota = origin2_info->Quota(); + EXPECT_EQ(origin1_quota, tracker->GetOriginSpaceAvailable(kOrigin1)); + EXPECT_EQ(origin2_quota, tracker->GetOriginSpaceAvailable(kOrigin2)); + + // Set a new quota for kOrigin1 + origin1_quota *= 2; + tracker->SetOriginQuota(kOrigin1, origin1_quota); + origin1_info = tracker->GetCachedOriginInfo(kOrigin1); + EXPECT_TRUE(origin1_info); + EXPECT_EQ(origin1_quota, origin1_info->Quota()); + + tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, + &database_size, &space_available); + EXPECT_EQ(0, database_size); + EXPECT_EQ(origin1_quota, space_available); + tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, + &database_size, &space_available); + EXPECT_EQ(0, database_size); + EXPECT_EQ(origin2_quota, space_available); + tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0, + &database_size, &space_available); + EXPECT_EQ(0, database_size); + EXPECT_EQ(origin1_quota, space_available); + + // Tell the tracker that a database has changed. + // Even though nothing has changed, the observers should be notified. + tracker->DatabaseModified(kOrigin1, kDB1); + CheckNotificationReceived(&observer1, kOrigin1, kDB1, 0, origin1_quota); + CheckNotificationReceived(&observer2, kOrigin1, kDB1, 0, origin1_quota); + + // Write some data to each file and check that the listeners are + // called with the appropriate values. + EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( + FilePath::FromWStringHack(UTF16ToWide( + tracker->GetOriginDirectory(kOrigin1)))))); + EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( + FilePath::FromWStringHack(UTF16ToWide( + tracker->GetOriginDirectory(kOrigin2)))))); + EXPECT_EQ(1, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); + EXPECT_EQ(2, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2)); + EXPECT_EQ(4, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin1, kDB3), "aaaa", 4)); + tracker->DatabaseModified(kOrigin1, kDB1); + CheckNotificationReceived(&observer1, kOrigin1, kDB1, 1, origin1_quota - 1); + CheckNotificationReceived(&observer2, kOrigin1, kDB1, 1, origin1_quota - 1); + tracker->DatabaseModified(kOrigin2, kDB2); + CheckNotificationReceived(&observer1, kOrigin2, kDB2, 2, origin2_quota - 2); + CheckNotificationReceived(&observer2, kOrigin2, kDB2, 2, origin2_quota - 2); + tracker->DatabaseModified(kOrigin1, kDB3); + CheckNotificationReceived(&observer1, kOrigin1, kDB3, 4, origin1_quota - 5); + CheckNotificationReceived(&observer2, kOrigin1, kDB3, 4, origin1_quota - 5); + + // Make sure the available space for kOrigin1 and kOrigin2 changed too. + EXPECT_EQ(origin1_quota - 5, tracker->GetOriginSpaceAvailable(kOrigin1)); + EXPECT_EQ(origin2_quota - 2, tracker->GetOriginSpaceAvailable(kOrigin2)); + + // Close all databases + tracker->DatabaseClosed(kOrigin1, kDB1); + tracker->DatabaseClosed(kOrigin2, kDB2); + tracker->DatabaseClosed(kOrigin1, kDB3); + + // Open an existing database and check the reported size + tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, + &database_size, &space_available); + EXPECT_EQ(1, database_size); + EXPECT_EQ(origin1_quota - 5, space_available); + + // Make sure that the observers are notified even if + // the size of the database hasn't changed. + EXPECT_EQ(1, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin1, kDB1), "b", 1)); + tracker->DatabaseModified(kOrigin1, kDB1); + CheckNotificationReceived(&observer1, kOrigin1, kDB1, 1, origin1_quota - 5); + CheckNotificationReceived(&observer2, kOrigin1, kDB1, 1, origin1_quota - 5); + tracker->DatabaseClosed(kOrigin1, kDB1); + + // Remove an observer; this should clear all caches. + tracker->RemoveObserver(&observer2); + + // Change kDB1's and kDB3's size and call tracker->DatabaseModified() + // for kDB1 only. If the caches were indeed cleared, then calling + // tracker->DatabaseModified() should re-populate the cache for + // kOrigin1 == kOrigin1, and thus, should pick up kDB3's size change too. + EXPECT_EQ(5, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin1, kDB1), "ccccc", 5)); + EXPECT_EQ(6, file_util::WriteFile( + tracker->GetFullDBFilePath(kOrigin1, kDB3), "dddddd", 6)); + tracker->DatabaseModified(kOrigin1, kDB1); + CheckNotificationReceived(&observer1, kOrigin1, kDB1, 5, + origin1_quota - 11); + EXPECT_FALSE(observer2.DidReceiveNewNotification()); + EXPECT_EQ(origin1_quota - 11, tracker->GetOriginSpaceAvailable(kOrigin1)); + + // Close the tracker database and clear all caches. + // Then make sure that DatabaseOpened() still returns the correct result. + tracker->CloseTrackerDatabaseAndClearCaches(); + tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, + &database_size, &space_available); + EXPECT_EQ(5, database_size); + EXPECT_EQ(origin1_quota - 11, space_available); + + // Close the tracker database and clear all caches. Then make sure that + // DatabaseModified() still calls the observers with correct values. + tracker->CloseTrackerDatabaseAndClearCaches(); + tracker->DatabaseModified(kOrigin1, kDB3); + CheckNotificationReceived(&observer1, kOrigin1, kDB3, 6, + origin1_quota - 11); + tracker->DatabaseClosed(kOrigin1, kDB1); + + // Remove all observers. + tracker->RemoveObserver(&observer1); + + // Trying to delete a database in use should fail + tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0, + &database_size, &space_available); + EXPECT_FALSE(tracker->DeleteClosedDatabase(kOrigin1, kDB3)); + origin1_info = tracker->GetCachedOriginInfo(kOrigin1); + EXPECT_TRUE(origin1_info); + EXPECT_EQ(6, origin1_info->GetDatabaseSize(kDB3)); + tracker->DatabaseClosed(kOrigin1, kDB3); + + // Delete a database and make sure the space used by that origin is updated + EXPECT_TRUE(tracker->DeleteClosedDatabase(kOrigin1, kDB3)); + origin1_info = tracker->GetCachedOriginInfo(kOrigin1); + EXPECT_TRUE(origin1_info); + EXPECT_EQ(origin1_quota - 5, tracker->GetOriginSpaceAvailable(kOrigin1)); + EXPECT_EQ(5, origin1_info->GetDatabaseSize(kDB1)); + EXPECT_EQ(0, origin1_info->GetDatabaseSize(kDB3)); + + // Get all data for all origins + std::vector<OriginInfo> origins_info; + EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info)); + EXPECT_EQ(size_t(2), origins_info.size()); + EXPECT_EQ(kOrigin1, origins_info[0].GetOrigin()); + EXPECT_EQ(5, origins_info[0].TotalSize()); + EXPECT_EQ(origin1_quota, origins_info[0].Quota()); + EXPECT_EQ(5, origins_info[0].GetDatabaseSize(kDB1)); + EXPECT_EQ(0, origins_info[0].GetDatabaseSize(kDB3)); + + EXPECT_EQ(kOrigin2, origins_info[1].GetOrigin()); + EXPECT_EQ(2, origins_info[1].TotalSize()); + EXPECT_EQ(origin2_quota, origins_info[1].Quota()); + + // Trying to delete an origin with databases in use should fail + tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, + &database_size, &space_available); + EXPECT_FALSE(tracker->DeleteOrigin(kOrigin1)); + origin1_info = tracker->GetCachedOriginInfo(kOrigin1); + EXPECT_TRUE(origin1_info); + EXPECT_EQ(5, origin1_info->GetDatabaseSize(kDB1)); + tracker->DatabaseClosed(kOrigin1, kDB1); + + // Delete an origin that doesn't have any database in use + EXPECT_TRUE(tracker->DeleteOrigin(kOrigin1)); + origins_info.clear(); + EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info)); + EXPECT_EQ(size_t(1), origins_info.size()); + EXPECT_EQ(kOrigin2, origins_info[0].GetOrigin()); + + origin1_info = tracker->GetCachedOriginInfo(kOrigin1); + EXPECT_TRUE(origin1_info); + EXPECT_EQ(origin1_quota, origin1_info->Quota()); + EXPECT_EQ(0, origin1_info->TotalSize()); + EXPECT_EQ(origin1_quota, tracker->GetOriginSpaceAvailable(kOrigin1)); + } +}; + TEST(DatabaseTrackerTest, DeleteOpenDatabase) { - // Initialize the tracker database. - ScopedTempDir temp_dir; - EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); - scoped_refptr<DatabaseTracker> tracker(new DatabaseTracker(temp_dir.path())); - - // Create and open three databases. - int64 database_size = 0; - int64 space_available = 0; - const string16 kOrigin1 = ASCIIToUTF16("origin1"); - const string16 kOrigin2 = ASCIIToUTF16("origin2"); - const string16 kDB1 = ASCIIToUTF16("db1"); - const string16 kDB2 = ASCIIToUTF16("db2"); - const string16 kDB3 = ASCIIToUTF16("db3"); - const string16 kDescription = ASCIIToUTF16("database_description"); - - tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, - &database_size, &space_available); - tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, - &database_size, &space_available); - tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0, - &database_size, &space_available); - - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - FilePath::FromWStringHack(UTF16ToWide(kOrigin1))))); - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - FilePath::FromWStringHack(UTF16ToWide(kOrigin2))))); - EXPECT_EQ(1, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); - EXPECT_EQ(2, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2)); - EXPECT_EQ(3, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin2, kDB3), "aaa", 3)); - tracker->DatabaseModified(kOrigin1, kDB1); - tracker->DatabaseModified(kOrigin2, kDB2); - tracker->DatabaseModified(kOrigin2, kDB3); - - // Delete db1. Should also delete origin1. - TestObserver observer; - tracker->AddObserver(&observer); - TestCompletionCallback callback; - int result = tracker->DeleteDatabase(kOrigin1, kDB1, &callback); - EXPECT_EQ(net::ERR_IO_PENDING, result); - ASSERT_FALSE(callback.have_result()); - EXPECT_TRUE(observer.DidReceiveNewNotification()); - EXPECT_EQ(kOrigin1, observer.GetNotificationOriginIdentifier()); - EXPECT_EQ(kDB1, observer.GetNotificationDatabaseName()); - tracker->DatabaseClosed(kOrigin1, kDB1); - result = callback.GetResult(result); - EXPECT_EQ(net::OK, result); - EXPECT_FALSE(file_util::PathExists(tracker->DatabaseDirectory().Append( - FilePath::FromWStringHack(UTF16ToWide(kOrigin1))))); - - // Recreate db1. - tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, - &database_size, &space_available); - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - FilePath::FromWStringHack(UTF16ToWide(kOrigin1))))); - EXPECT_EQ(1, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); - tracker->DatabaseModified(kOrigin1, kDB1); - - // Setup file modification times. db1 and db2 are modified now, db3 three - // days ago. - EXPECT_TRUE(file_util::SetLastModifiedTime( - tracker->GetFullDBFilePath(kOrigin1, kDB1), base::Time::Now())); - EXPECT_TRUE(file_util::SetLastModifiedTime( - tracker->GetFullDBFilePath(kOrigin2, kDB2), base::Time::Now())); - base::Time three_days_ago = base::Time::Now(); - three_days_ago -= base::TimeDelta::FromDays(3); - EXPECT_TRUE(file_util::SetLastModifiedTime( - tracker->GetFullDBFilePath(kOrigin2, kDB3), three_days_ago)); - - // Delete databases modified since yesterday. - base::Time yesterday = base::Time::Now(); - yesterday -= base::TimeDelta::FromDays(1); - result = tracker->DeleteDataModifiedSince(yesterday, &callback); - EXPECT_EQ(net::ERR_IO_PENDING, result); - ASSERT_FALSE(callback.have_result()); - EXPECT_TRUE(observer.DidReceiveNewNotification()); - tracker->DatabaseClosed(kOrigin1, kDB1); - tracker->DatabaseClosed(kOrigin2, kDB2); - result = callback.GetResult(result); - EXPECT_EQ(net::OK, result); - EXPECT_FALSE(file_util::PathExists(tracker->DatabaseDirectory().Append( - FilePath::FromWStringHack(UTF16ToWide(kOrigin1))))); - EXPECT_FALSE( - file_util::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB2))); - EXPECT_TRUE( - file_util::PathExists(tracker->GetFullDBFilePath(kOrigin2, kDB3))); - - tracker->DatabaseClosed(kOrigin2, kDB3); - tracker->RemoveObserver(&observer); + DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(false); +} + +TEST(DatabaseTrackerTest, DeleteOpenDatabaseIncognitoMode) { + DatabaseTracker_TestHelper_Test::TestDeleteOpenDatabase(true); } TEST(DatabaseTrackerTest, DatabaseTracker) { - // Initialize the tracker database. - ScopedTempDir temp_dir; - EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); - scoped_refptr<DatabaseTracker> tracker(new DatabaseTracker(temp_dir.path())); - - // Add two observers. - TestObserver observer1; - TestObserver observer2; - tracker->AddObserver(&observer1); - tracker->AddObserver(&observer2); - - // Open three new databases. - int64 database_size = 0; - int64 space_available = 0; - const string16 kOrigin1 = ASCIIToUTF16("origin1"); - const string16 kOrigin2 = ASCIIToUTF16("origin2"); - const string16 kDB1 = ASCIIToUTF16("db1"); - const string16 kDB2 = ASCIIToUTF16("db2"); - const string16 kDB3 = ASCIIToUTF16("db3"); - const string16 kDescription = ASCIIToUTF16("database_description"); - - // Get the quota for kOrigin1 and kOrigin2 - DatabaseTracker::CachedOriginInfo* origin1_info = - tracker->GetCachedOriginInfo(kOrigin1); - DatabaseTracker::CachedOriginInfo* origin2_info = - tracker->GetCachedOriginInfo(kOrigin1); - EXPECT_TRUE(origin1_info); - EXPECT_TRUE(origin2_info); - int64 origin1_quota = origin1_info->Quota(); - int64 origin2_quota = origin2_info->Quota(); - EXPECT_EQ(origin1_quota, tracker->GetOriginSpaceAvailable(kOrigin1)); - EXPECT_EQ(origin2_quota, tracker->GetOriginSpaceAvailable(kOrigin2)); - - // Set a new quota for kOrigin1 - origin1_quota *= 2; - tracker->SetOriginQuota(kOrigin1, origin1_quota); - origin1_info = tracker->GetCachedOriginInfo(kOrigin1); - EXPECT_TRUE(origin1_info); - EXPECT_EQ(origin1_quota, origin1_info->Quota()); - - tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, - &database_size, &space_available); - EXPECT_EQ(0, database_size); - EXPECT_EQ(origin1_quota, space_available); - tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0, - &database_size, &space_available); - EXPECT_EQ(0, database_size); - EXPECT_EQ(origin2_quota, space_available); - tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0, - &database_size, &space_available); - EXPECT_EQ(0, database_size); - EXPECT_EQ(origin1_quota, space_available); - - // Tell the tracker that a database has changed. - // Even though nothing has changed, the observers should be notified. - tracker->DatabaseModified(kOrigin1, kDB1); - CheckNotificationReceived(&observer1, kOrigin1, kDB1, 0, origin1_quota); - CheckNotificationReceived(&observer2, kOrigin1, kDB1, 0, origin1_quota); - - // Write some data to each file and check that the listeners are - // called with the appropriate values. - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - FilePath::FromWStringHack(UTF16ToWide(kOrigin1))))); - EXPECT_TRUE(file_util::CreateDirectory(tracker->DatabaseDirectory().Append( - FilePath::FromWStringHack(UTF16ToWide(kOrigin2))))); - EXPECT_EQ(1, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin1, kDB1), "a", 1)); - EXPECT_EQ(2, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin2, kDB2), "aa", 2)); - EXPECT_EQ(4, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin1, kDB3), "aaaa", 4)); - tracker->DatabaseModified(kOrigin1, kDB1); - CheckNotificationReceived(&observer1, kOrigin1, kDB1, 1, origin1_quota - 1); - CheckNotificationReceived(&observer2, kOrigin1, kDB1, 1, origin1_quota - 1); - tracker->DatabaseModified(kOrigin2, kDB2); - CheckNotificationReceived(&observer1, kOrigin2, kDB2, 2, origin2_quota - 2); - CheckNotificationReceived(&observer2, kOrigin2, kDB2, 2, origin2_quota - 2); - tracker->DatabaseModified(kOrigin1, kDB3); - CheckNotificationReceived(&observer1, kOrigin1, kDB3, 4, origin1_quota - 5); - CheckNotificationReceived(&observer2, kOrigin1, kDB3, 4, origin1_quota - 5); - - // Make sure the available space for kOrigin1 and kOrigin2 changed accordingly - EXPECT_EQ(origin1_quota - 5, tracker->GetOriginSpaceAvailable(kOrigin1)); - EXPECT_EQ(origin2_quota - 2, tracker->GetOriginSpaceAvailable(kOrigin2)); - - // Close all databases - tracker->DatabaseClosed(kOrigin1, kDB1); - tracker->DatabaseClosed(kOrigin2, kDB2); - tracker->DatabaseClosed(kOrigin1, kDB3); - - // Open an existing database and check the reported size - tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, - &database_size, &space_available); - EXPECT_EQ(1, database_size); - EXPECT_EQ(origin1_quota - 5, space_available); - - // Make sure that the observers are notified even if - // the size of the database hasn't changed. - EXPECT_EQ(1, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin1, kDB1), "b", 1)); - tracker->DatabaseModified(kOrigin1, kDB1); - CheckNotificationReceived(&observer1, kOrigin1, kDB1, 1, origin1_quota - 5); - CheckNotificationReceived(&observer2, kOrigin1, kDB1, 1, origin1_quota - 5); - tracker->DatabaseClosed(kOrigin1, kDB1); - - // Remove an observer; this should clear all caches. - tracker->RemoveObserver(&observer2); - - // Change kDB1's and kDB3's size and call tracker->DatabaseModified() - // for kDB1 only. If the caches were indeed cleared, then calling - // tracker->DatabaseModified() should re-populate the cache for - // kOrigin1 == kOrigin1, and thus, should pick up kDB3's size change too. - EXPECT_EQ(5, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin1, kDB1), "ccccc", 5)); - EXPECT_EQ(6, file_util::WriteFile( - tracker->GetFullDBFilePath(kOrigin1, kDB3), "dddddd", 6)); - tracker->DatabaseModified(kOrigin1, kDB1); - CheckNotificationReceived(&observer1, kOrigin1, kDB1, 5, origin1_quota - 11); - EXPECT_FALSE(observer2.DidReceiveNewNotification()); - EXPECT_EQ(origin1_quota - 11, tracker->GetOriginSpaceAvailable(kOrigin1)); - - // Close the tracker database and clear all caches. - // Then make sure that DatabaseOpened() still returns the correct result. - tracker->CloseTrackerDatabaseAndClearCaches(); - tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, - &database_size, &space_available); - EXPECT_EQ(5, database_size); - EXPECT_EQ(origin1_quota - 11, space_available); - - // Close the tracker database and clear all caches. Then make sure that - // DatabaseModified() still calls the observers with correct values. - tracker->CloseTrackerDatabaseAndClearCaches(); - tracker->DatabaseModified(kOrigin1, kDB3); - CheckNotificationReceived(&observer1, kOrigin1, kDB3, 6, origin1_quota - 11); - tracker->DatabaseClosed(kOrigin1, kDB1); - - // Remove all observers. - tracker->RemoveObserver(&observer1); - - // Trying to delete a database in use should fail - tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0, - &database_size, &space_available); - EXPECT_FALSE(tracker->DeleteClosedDatabase(kOrigin1, kDB3)); - origin1_info = tracker->GetCachedOriginInfo(kOrigin1); - EXPECT_TRUE(origin1_info); - EXPECT_EQ(6, origin1_info->GetDatabaseSize(kDB3)); - tracker->DatabaseClosed(kOrigin1, kDB3); - - // Delete a database and make sure the space used by that origin is updated - EXPECT_TRUE(tracker->DeleteClosedDatabase(kOrigin1, kDB3)); - origin1_info = tracker->GetCachedOriginInfo(kOrigin1); - EXPECT_TRUE(origin1_info); - EXPECT_EQ(origin1_quota - 5, tracker->GetOriginSpaceAvailable(kOrigin1)); - EXPECT_EQ(5, origin1_info->GetDatabaseSize(kDB1)); - EXPECT_EQ(0, origin1_info->GetDatabaseSize(kDB3)); - - // Get all data for all origins - std::vector<OriginInfo> origins_info; - EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info)); - EXPECT_EQ(size_t(2), origins_info.size()); - EXPECT_EQ(kOrigin1, origins_info[0].GetOrigin()); - EXPECT_EQ(5, origins_info[0].TotalSize()); - EXPECT_EQ(origin1_quota, origins_info[0].Quota()); - EXPECT_EQ(5, origins_info[0].GetDatabaseSize(kDB1)); - EXPECT_EQ(0, origins_info[0].GetDatabaseSize(kDB3)); - - EXPECT_EQ(kOrigin2, origins_info[1].GetOrigin()); - EXPECT_EQ(2, origins_info[1].TotalSize()); - EXPECT_EQ(origin2_quota, origins_info[1].Quota()); - - // Trying to delete an origin with databases in use should fail - tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0, - &database_size, &space_available); - EXPECT_FALSE(tracker->DeleteOrigin(kOrigin1)); - origin1_info = tracker->GetCachedOriginInfo(kOrigin1); - EXPECT_TRUE(origin1_info); - EXPECT_EQ(5, origin1_info->GetDatabaseSize(kDB1)); - tracker->DatabaseClosed(kOrigin1, kDB1); - - // Delete an origin that doesn't have any database in use - EXPECT_TRUE(tracker->DeleteOrigin(kOrigin1)); - origins_info.clear(); - EXPECT_TRUE(tracker->GetAllOriginsInfo(&origins_info)); - EXPECT_EQ(size_t(1), origins_info.size()); - EXPECT_EQ(kOrigin2, origins_info[0].GetOrigin()); - - origin1_info = tracker->GetCachedOriginInfo(kOrigin1); - EXPECT_TRUE(origin1_info); - EXPECT_EQ(origin1_quota, origin1_info->Quota()); - EXPECT_EQ(0, origin1_info->TotalSize()); - EXPECT_EQ(origin1_quota, tracker->GetOriginSpaceAvailable(kOrigin1)); + DatabaseTracker_TestHelper_Test::TestDatabaseTracker(false); } -TEST(DatabaseTrackerTest, NoInitIncognito) { - const string16 kOrigin = ASCIIToUTF16("origin"); - const string16 kName = ASCIIToUTF16("name"); - const string16 kDescription = ASCIIToUTF16("description"); - const DatabaseConnections kEmptyCollection; - - std::vector<OriginInfo> infos; - scoped_refptr<DatabaseTracker> tracker(new DatabaseTracker(FilePath())); - EXPECT_TRUE(tracker->is_incognito_); - EXPECT_FALSE(tracker->LazyInit()); - EXPECT_TRUE(tracker->DatabaseDirectory().empty()); - EXPECT_TRUE(tracker->GetFullDBFilePath(kOrigin, kName).empty()); - EXPECT_FALSE(tracker->GetAllOriginsInfo(&infos)); - EXPECT_FALSE(tracker->IsDatabaseScheduledForDeletion(kOrigin, kName)); - EXPECT_EQ(net::ERR_FAILED, - tracker->DeleteDatabase(kOrigin, kName, NULL)); - EXPECT_EQ(net::ERR_FAILED, - tracker->DeleteDataModifiedSince(base::Time(), NULL)); - EXPECT_EQ(net::ERR_FAILED, - tracker->DeleteDataForOrigin(kOrigin, NULL)); - - // These should not assert or crash when called in this state. - int64 size_out(0), space_available_out(0); - tracker->DatabaseOpened(kOrigin, kName, kDescription, 1, - &size_out, &space_available_out); - tracker->DatabaseModified(kOrigin, kName); - tracker->DatabaseClosed(kOrigin, kName); - tracker->CloseDatabases(kEmptyCollection); - tracker->CloseTrackerDatabaseAndClearCaches(); - tracker->SetOriginQuota(kOrigin, 5); - tracker->SetOriginQuotaInMemory(kOrigin, 5); - tracker->ResetOriginQuotaInMemory(kOrigin); +TEST(DatabaseTrackerTest, DatabaseTrackerIncognitoMode) { + DatabaseTracker_TestHelper_Test::TestDatabaseTracker(true); } } // namespace webkit_database diff --git a/webkit/database/vfs_backend.cc b/webkit/database/vfs_backend.cc index 0d9cb4f..94cec80 100644 --- a/webkit/database/vfs_backend.cc +++ b/webkit/database/vfs_backend.cc @@ -19,11 +19,44 @@ namespace webkit_database { static const int kFileTypeMask = 0x00007F00; // static +void VfsBackend::GetFileHandleForProcess(base::ProcessHandle process_handle, + const base::PlatformFile& file_handle, + base::PlatformFile* target_handle, + bool close_source_handle) { + if (file_handle == base::kInvalidPlatformFileValue) { + *target_handle = base::kInvalidPlatformFileValue; + return; + } + +#if defined(OS_WIN) + // Duplicate the file handle. + if (!DuplicateHandle(GetCurrentProcess(), file_handle, + process_handle, target_handle, 0, false, + DUPLICATE_SAME_ACCESS | + (close_source_handle ? DUPLICATE_CLOSE_SOURCE : 0))) { + // file_handle is closed whether or not DuplicateHandle succeeds. + *target_handle = INVALID_HANDLE_VALUE; + } +#elif defined(OS_POSIX) + *target_handle = file_handle; +#endif +} + +// static bool VfsBackend::FileTypeIsMainDB(int desired_flags) { return (desired_flags & kFileTypeMask) == SQLITE_OPEN_MAIN_DB; } // static +bool VfsBackend::FileTypeIsJournal(int desired_flags) { + int file_type = desired_flags & kFileTypeMask; + return ((file_type == SQLITE_OPEN_MAIN_JOURNAL) || + (file_type == SQLITE_OPEN_TEMP_JOURNAL) || + (file_type == SQLITE_OPEN_SUBJOURNAL) || + (file_type == SQLITE_OPEN_MASTER_JOURNAL)); +} + +// static bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) { return (desired_flags & SQLITE_OPEN_READWRITE) != 0; } @@ -47,16 +80,13 @@ bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) { // If we're accessing an existing file, we cannot give exclusive access, and // we can't delete it. + // Normally, we'd also check that 'is_delete' is false for a main DB, main + // journal or master journal file; however, when in incognito mode, we use + // the SQLITE_OPEN_DELETEONCLOSE flag when opening those files too and keep + // an open handle to them for as long as the incognito profile is around. if ((is_exclusive || is_delete) && !is_create) return false; - // The main DB, main journal and master journal cannot be auto-deleted. - if (is_delete && ((file_type == SQLITE_OPEN_MAIN_DB) || - (file_type == SQLITE_OPEN_MAIN_JOURNAL) || - (file_type == SQLITE_OPEN_MASTER_JOURNAL))) { - return false; - } - // Make sure we're opening the DB directory or that a file type is set. return (file_type == SQLITE_OPEN_MAIN_DB) || (file_type == SQLITE_OPEN_TEMP_DB) || @@ -70,8 +100,7 @@ bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) { // static void VfsBackend::OpenFile(const FilePath& file_path, int desired_flags, - base::ProcessHandle handle, - base::PlatformFile* target_handle) { + base::PlatformFile* file_handle) { DCHECK(!file_path.empty()); // Verify the flags for consistency and create the database @@ -104,29 +133,15 @@ void VfsBackend::OpenFile(const FilePath& file_path, } // Try to open/create the DB file. - base::PlatformFile file_handle = + *file_handle = base::CreatePlatformFile(file_path.ToWStringHack(), flags, NULL); - if (file_handle != base::kInvalidPlatformFileValue) { -#if defined(OS_WIN) - // Duplicate the file handle. - if (!DuplicateHandle(GetCurrentProcess(), file_handle, - handle, target_handle, 0, false, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - // file_handle is closed whether or not DuplicateHandle succeeds. - *target_handle = INVALID_HANDLE_VALUE; - } -#elif defined(OS_POSIX) - *target_handle = file_handle; -#endif - } } // static void VfsBackend::OpenTempFileInDirectory( const FilePath& dir_path, int desired_flags, - base::ProcessHandle handle, - base::PlatformFile* target_handle) { + base::PlatformFile* file_handle) { // We should be able to delete temp files when they're closed // and create them as needed if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) || @@ -139,7 +154,7 @@ void VfsBackend::OpenTempFileInDirectory( if (!file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path)) return; - OpenFile(temp_file_path, desired_flags, handle, target_handle); + OpenFile(temp_file_path, desired_flags, file_handle); } // static diff --git a/webkit/database/vfs_backend.h b/webkit/database/vfs_backend.h index 267ce90..99effc8 100644 --- a/webkit/database/vfs_backend.h +++ b/webkit/database/vfs_backend.h @@ -15,15 +15,18 @@ namespace webkit_database { class VfsBackend { public: + static void GetFileHandleForProcess(base::ProcessHandle process_handle, + const base::PlatformFile& file_handle, + base::PlatformFile* target_handle, + bool close_source_handle); + static void OpenFile(const FilePath& file_path, int desired_flags, - base::ProcessHandle handle, - base::PlatformFile* target_handle); + base::PlatformFile* file_handle); static void OpenTempFileInDirectory(const FilePath& dir_path, int desired_flags, - base::ProcessHandle handle, - base::PlatformFile* target_handle); + base::PlatformFile* file_handle); static int DeleteFile(const FilePath& file_path, bool sync_dir); @@ -33,6 +36,7 @@ class VfsBackend { // Used to make decisions in the DatabaseDispatcherHost. static bool FileTypeIsMainDB(int desired_flags); + static bool FileTypeIsJournal(int desired_flags); static bool OpenTypeIsReadWrite(int desired_flags); private: |