Index: webkit/database/database_tracker.cc |
diff --git a/webkit/database/database_tracker.cc b/webkit/database/database_tracker.cc |
index f2bb4aee9f386c8e050dd753d84462a9941d859a..1d75260e90b91753c3e3449ecf212e1fcc99570f 100644 |
--- a/webkit/database/database_tracker.cc |
+++ b/webkit/database/database_tracker.cc |
@@ -36,14 +36,13 @@ DatabaseTracker::DatabaseTracker(const FilePath& profile_path) |
db_(new sql::Connection()), |
databases_table_(NULL), |
meta_table_(NULL), |
- dbs_deleted_callback_(NULL), |
default_quota_(5 * 1024 * 1024) { |
} |
DatabaseTracker::~DatabaseTracker() { |
DCHECK(observers_.size() == 0); |
DCHECK(dbs_to_be_deleted_.empty()); |
- DCHECK(!dbs_deleted_callback_); |
+ DCHECK(deletion_callbacks_.empty()); |
} |
void DatabaseTracker::SetDefaultQuota(int64 quota) { |
@@ -105,15 +104,32 @@ void DatabaseTracker::DeleteDatabaseIfNeeded(const string16& origin_identifier, |
DCHECK(!database_connections_.IsDatabaseOpened(origin_identifier, |
database_name)); |
if (IsDatabaseScheduledForDeletion(origin_identifier, database_name)) { |
- DeleteDatabase(origin_identifier, database_name); |
+ DeleteClosedDatabase(origin_identifier, database_name); |
dbs_to_be_deleted_[origin_identifier].erase(database_name); |
if (dbs_to_be_deleted_[origin_identifier].empty()) |
dbs_to_be_deleted_.erase(origin_identifier); |
- if (dbs_to_be_deleted_.empty()) { |
- DCHECK(dbs_deleted_callback_); |
- dbs_deleted_callback_->Run(net::OK); |
- dbs_deleted_callback_ = NULL; |
+ |
+ std::vector<net::CompletionCallback*> to_be_deleted; |
+ for (PendingCompletionMap::iterator callback = deletion_callbacks_.begin(); |
+ callback != deletion_callbacks_.end(); ++callback) { |
+ DatabaseSet::iterator found_origin = |
+ callback->second.find(origin_identifier); |
+ if (found_origin != callback->second.end()) { |
+ std::set<string16>& databases = found_origin->second; |
+ databases.erase(database_name); |
+ if (databases.empty()) { |
+ callback->second.erase(found_origin); |
+ if (callback->second.empty()) { |
+ net::CompletionCallback* cb = callback->first; |
+ cb->Run(net::OK); |
+ to_be_deleted.push_back(cb); |
+ } |
+ } |
+ } |
} |
+ for (std::vector<net::CompletionCallback*>::iterator cb = |
+ to_be_deleted.begin(); cb != to_be_deleted.end(); ++cb) |
+ deletion_callbacks_.erase(*cb); |
} |
} |
@@ -185,14 +201,13 @@ void DatabaseTracker::SetOriginQuota(const string16& origin_identifier, |
} |
} |
-bool DatabaseTracker::DeleteDatabase(const string16& origin_identifier, |
- const string16& database_name) { |
+bool DatabaseTracker::DeleteClosedDatabase(const string16& origin_identifier, |
+ const string16& database_name) { |
// Check if the database is opened by any renderer. |
if (database_connections_.IsDatabaseOpened(origin_identifier, database_name)) |
return false; |
// Try to delete the file on the hard drive. |
- // TODO(jochen): Delete directory if this was the last database. |
// TODO(jochen): Delete journal files associated with this database. |
FilePath db_file = GetFullDBFilePath(origin_identifier, database_name); |
if (file_util::PathExists(db_file) && !file_util::Delete(db_file, false)) |
@@ -201,6 +216,12 @@ bool DatabaseTracker::DeleteDatabase(const string16& origin_identifier, |
// Clean up the main database and invalidate the cached record. |
databases_table_->DeleteDatabaseDetails(origin_identifier, database_name); |
origins_info_map_.erase(origin_identifier); |
+ |
+ // Try to delete the origin in case this was the last database. |
+ std::vector<DatabaseDetails> details; |
+ if (databases_table_->GetAllDatabaseDetailsForOrigin( |
+ origin_identifier, &details) && details.empty()) |
+ DeleteOrigin(origin_identifier); |
return true; |
} |
@@ -225,8 +246,7 @@ bool DatabaseTracker::DeleteOrigin(const string16& origin_identifier) { |
bool DatabaseTracker::IsDatabaseScheduledForDeletion( |
const string16& origin_identifier, |
const string16& database_name) { |
- std::map<string16, std::set<string16> >::iterator it = |
- dbs_to_be_deleted_.find(origin_identifier); |
+ DatabaseSet::iterator it = dbs_to_be_deleted_.find(origin_identifier); |
if (it == dbs_to_be_deleted_.end()) |
return false; |
@@ -388,31 +408,47 @@ void DatabaseTracker::ScheduleDatabaseForDeletion( |
origin_identifier, database_name)); |
} |
+int DatabaseTracker::DeleteDatabase(const string16& origin_identifier, |
+ const string16& database_name, |
+ net::CompletionCallback* callback) { |
+ if (!LazyInit()) |
+ return net::ERR_FAILED; |
+ |
+ DCHECK(!callback || |
+ deletion_callbacks_.find(callback) == deletion_callbacks_.end()); |
+ |
+ if (database_connections_.IsDatabaseOpened(origin_identifier, |
+ database_name)) { |
+ if (callback) |
+ deletion_callbacks_[callback][origin_identifier].insert(database_name); |
+ ScheduleDatabaseForDeletion(origin_identifier, database_name); |
+ return net::ERR_IO_PENDING; |
+ } |
+ DeleteClosedDatabase(origin_identifier, database_name); |
+ return net::OK; |
+} |
+ |
int DatabaseTracker::DeleteDataModifiedSince( |
const base::Time& cutoff, |
net::CompletionCallback* callback) { |
- // Check for reentrancy. |
- if (dbs_deleted_callback_ || !LazyInit()) |
+ if (!LazyInit()) |
return net::ERR_FAILED; |
- DCHECK(callback); |
- dbs_deleted_callback_ = callback; |
+ DCHECK(!callback || |
+ deletion_callbacks_.find(callback) == deletion_callbacks_.end()); |
+ DatabaseSet to_be_deleted; |
std::vector<string16> origins; |
- if (!databases_table_->GetAllOrigins(&origins)) { |
- dbs_deleted_callback_ = NULL; |
+ if (!databases_table_->GetAllOrigins(&origins)) |
return net::ERR_FAILED; |
- } |
int rv = net::OK; |
for (std::vector<string16>::const_iterator ori = origins.begin(); |
ori != origins.end(); ++ori) { |
if (StartsWith(*ori, ASCIIToUTF16(kExtensionOriginIdentifierPrefix), true)) |
continue; |
std::vector<DatabaseDetails> details; |
- if (!databases_table_->GetAllDatabaseDetailsForOrigin(*ori, &details)) { |
+ if (!databases_table_->GetAllDatabaseDetailsForOrigin(*ori, &details)) |
rv = net::ERR_FAILED; |
- continue; |
- } |
for (std::vector<DatabaseDetails>::const_iterator db = details.begin(); |
db != details.end(); ++db) { |
FilePath db_file = GetFullDBFilePath(*ori, db->database_name); |
@@ -422,18 +458,23 @@ int DatabaseTracker::DeleteDataModifiedSince( |
continue; |
// Check if the database is opened by any renderer. |
- if (database_connections_.IsDatabaseOpened(*ori, db->database_name)) { |
- ScheduleDatabaseForDeletion(*ori, db->database_name); |
- rv = net::ERR_IO_PENDING; |
- } else { |
- DeleteDatabase(*ori, db->database_name); |
- } |
+ if (database_connections_.IsDatabaseOpened(*ori, db->database_name)) |
+ to_be_deleted[*ori].insert(db->database_name); |
+ else |
+ DeleteClosedDatabase(*ori, db->database_name); |
} |
} |
- if (rv != net::ERR_IO_PENDING) { |
- dbs_to_be_deleted_.clear(); |
- dbs_deleted_callback_ = NULL; |
+ if (!to_be_deleted.empty()) { |
+ if (callback) |
+ deletion_callbacks_[callback] = to_be_deleted; |
+ for (DatabaseSet::iterator ori = to_be_deleted.begin(); |
+ ori != to_be_deleted.end(); ++ori) { |
+ for (std::set<string16>::iterator db = ori->second.begin(); |
+ db != ori->second.end(); ++db) |
+ ScheduleDatabaseForDeletion(ori->first, *db); |
+ } |
+ rv = net::ERR_IO_PENDING; |
} |
return rv; |
} |