summaryrefslogtreecommitdiffstats
path: root/webkit/database
diff options
context:
space:
mode:
authordumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-13 09:08:41 +0000
committerdumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-13 09:08:41 +0000
commitfe615f3a28aba7377b1ef177390b67927cc32290 (patch)
treeaac68857f269f74d0414627fb11657fde8706962 /webkit/database
parent517507bd359f4ab111f6c119e4fdc9bcea145fbf (diff)
downloadchromium_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.cc109
-rw-r--r--webkit/database/database_tracker.h39
-rw-r--r--webkit/database/database_tracker_unittest.cc629
-rw-r--r--webkit/database/vfs_backend.cc67
-rw-r--r--webkit/database/vfs_backend.h12
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: