diff options
author | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 19:24:04 +0000 |
---|---|---|
committer | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 19:24:04 +0000 |
commit | 2b0ec8bb8b1d5e113ad072b27c3f157d985c6b21 (patch) | |
tree | 7fd39372550d1bbb60dba7483151344a06c3ca60 | |
parent | d84ac11ef8abf2366f8544fe76db3cb0e645e177 (diff) | |
download | chromium_src-2b0ec8bb8b1d5e113ad072b27c3f157d985c6b21.zip chromium_src-2b0ec8bb8b1d5e113ad072b27c3f157d985c6b21.tar.gz chromium_src-2b0ec8bb8b1d5e113ad072b27c3f157d985c6b21.tar.bz2 |
Ask renderers to immediately close all DB handles to a database file
when the file needs to be deleted.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/594002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38911 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/renderer_host/database_dispatcher_host.cc | 31 | ||||
-rw-r--r-- | chrome/browser/renderer_host/database_dispatcher_host.h | 6 | ||||
-rw-r--r-- | chrome/common/db_message_filter.cc | 9 | ||||
-rw-r--r-- | chrome/common/db_message_filter.h | 4 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 5 | ||||
-rw-r--r-- | webkit/database/database_connections.cc | 5 | ||||
-rw-r--r-- | webkit/database/database_connections.h | 9 | ||||
-rw-r--r-- | webkit/database/database_tracker.cc | 82 | ||||
-rw-r--r-- | webkit/database/database_tracker.h | 14 | ||||
-rw-r--r-- | webkit/database/database_tracker_unittest.cc | 3 | ||||
-rw-r--r-- | webkit/tools/test_shell/simple_database_system.cc | 13 | ||||
-rw-r--r-- | webkit/tools/test_shell/simple_database_system.h | 8 |
12 files changed, 160 insertions, 29 deletions
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.cc b/chrome/browser/renderer_host/database_dispatcher_host.cc index d72ca06..a57244a 100644 --- a/chrome/browser/renderer_host/database_dispatcher_host.cc +++ b/chrome/browser/renderer_host/database_dispatcher_host.cc @@ -196,17 +196,22 @@ void DatabaseDispatcherHost::DatabaseOpenFile(const string16& vfs_file_name, DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); base::PlatformFile target_handle = base::kInvalidPlatformFileValue; base::PlatformFile target_dir_handle = base::kInvalidPlatformFileValue; + string16 origin_identifier; + string16 database_name; if (vfs_file_name.empty()) { VfsBackend::OpenTempFileInDirectory(db_tracker_->DatabaseDirectory(), desired_flags, process_handle_, &target_handle, &target_dir_handle); - } else { - FilePath db_file = - DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name); - if (!db_file.empty()) { - VfsBackend::OpenFile(db_file, desired_flags, process_handle_, - &target_handle, &target_dir_handle); - } + } else if (DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier, + &database_name, NULL) && + !db_tracker_->IsDatabaseScheduledForDeletion(origin_identifier, + database_name)) { + FilePath db_file = + DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name); + if (!db_file.empty()) { + VfsBackend::OpenFile(db_file, desired_flags, process_handle_, + &target_handle, &target_dir_handle); + } } ViewMsg_DatabaseOpenFileResponse_Params response_params; @@ -430,6 +435,18 @@ void DatabaseDispatcherHost::OnDatabaseSizeChanged( } } +void DatabaseDispatcherHost::OnDatabaseScheduledForDeletion( + const string16& origin_identifier, + const string16& database_name) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod(this, + &DatabaseDispatcherHost::SendMessage, + new ViewMsg_DatabaseCloseImmediately( + origin_identifier, database_name))); +} + void DatabaseDispatcherHost::OnDatabaseOpenFileAllowed( const string16& vfs_file_name, int desired_flags, int32 message_id) { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); diff --git a/chrome/browser/renderer_host/database_dispatcher_host.h b/chrome/browser/renderer_host/database_dispatcher_host.h index 95f8d86..e9b3f2b 100644 --- a/chrome/browser/renderer_host/database_dispatcher_host.h +++ b/chrome/browser/renderer_host/database_dispatcher_host.h @@ -49,11 +49,13 @@ class DatabaseDispatcherHost void OnDatabaseClosed(const string16& origin_identifier, const string16& database_name); - // DatabaseTracker::Observer callback (file thread) + // DatabaseTracker::Observer callbacks (file thread) virtual void OnDatabaseSizeChanged(const string16& origin_identifier, const string16& database_name, int64 database_size, int64 space_available); + virtual void OnDatabaseScheduledForDeletion(const string16& origin_identifier, + const string16& database_name); private: void AddObserver(); @@ -77,7 +79,7 @@ class DatabaseDispatcherHost // Database tracker message handlers (file thread) void DatabaseOpened(const string16& origin_identifier, - const string16& file_name, + const string16& database_name, const string16& description, int64 estimated_size); void DatabaseModified(const string16& origin_identifier, diff --git a/chrome/common/db_message_filter.cc b/chrome/common/db_message_filter.cc index a3e6bd8..fb1944b 100644 --- a/chrome/common/db_message_filter.cc +++ b/chrome/common/db_message_filter.cc @@ -66,6 +66,8 @@ bool DBMessageFilter::OnMessageReceived(const IPC::Message& message) { OnResponse<uint32>) IPC_MESSAGE_HANDLER(ViewMsg_DatabaseGetFileSizeResponse, OnResponse<int64>) IPC_MESSAGE_HANDLER(ViewMsg_DatabaseUpdateSize, OnDatabaseUpdateSize) + IPC_MESSAGE_HANDLER(ViewMsg_DatabaseCloseImmediately, + OnDatabaseCloseImmediately) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -78,3 +80,10 @@ void DBMessageFilter::OnDatabaseUpdateSize(const string16& origin_identifier, WebKit::WebDatabase::updateDatabaseSize( origin_identifier, database_name, database_size, space_available); } + +void DBMessageFilter::OnDatabaseCloseImmediately( + const string16& origin_identifier, + const string16& database_name) { + WebKit::WebDatabase::closeDatabaseImmediately( + origin_identifier, database_name); +} diff --git a/chrome/common/db_message_filter.h b/chrome/common/db_message_filter.h index f28ea4b..aaf468f 100644 --- a/chrome/common/db_message_filter.h +++ b/chrome/common/db_message_filter.h @@ -98,6 +98,10 @@ class DBMessageFilter : public IPC::ChannelProxy::MessageFilter { int64 database_size, int64 space_available); + // Processes IPCs that ask for a DB to be closed immediately. + void OnDatabaseCloseImmediately(const string16& origin_identifier, + const string16& database_name); + // The message loop for the IO thread. MessageLoop* io_thread_message_loop_; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index a37ba09..ad7f7c4 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -804,6 +804,11 @@ IPC_MESSAGE_ROUTED4(ViewMsg_NotifyLowLatencyAudioStreamCreated, int64 /* the new database size */, int64 /* space available to origin */) + // Asks the child process to close a database immediately + IPC_MESSAGE_CONTROL2(ViewMsg_DatabaseCloseImmediately, + string16 /* the origin */, + string16 /* the database name */) + // Storage events are broadcast to renderer processes. IPC_MESSAGE_CONTROL1(ViewMsg_DOMStorageEvent, ViewMsg_DOMStorageEvent_Params) diff --git a/webkit/database/database_connections.cc b/webkit/database/database_connections.cc index c6e9609..05efb1e 100644 --- a/webkit/database/database_connections.cc +++ b/webkit/database/database_connections.cc @@ -50,7 +50,8 @@ void DatabaseConnections::RemoveAllConnections() { } void DatabaseConnections::RemoveConnections( - const DatabaseConnections& connections) { + const DatabaseConnections& connections, + std::vector<std::pair<string16, string16> >* closed_dbs) { for (OriginConnections::const_iterator origin_it = connections.connections_.begin(); origin_it != connections.connections_.end(); @@ -59,6 +60,8 @@ void DatabaseConnections::RemoveConnections( for (DBConnections::const_iterator db_it = db_connections.begin(); db_it != db_connections.end(); db_it++) { RemoveConnectionsHelper(origin_it->first, db_it->first, db_it->second); + if (!IsDatabaseOpened(origin_it->first, db_it->first)) + closed_dbs->push_back(std::make_pair(origin_it->first, db_it->first)); } } } diff --git a/webkit/database/database_connections.h b/webkit/database/database_connections.h index 02941c8..433bb3f 100644 --- a/webkit/database/database_connections.h +++ b/webkit/database/database_connections.h @@ -5,9 +5,10 @@ #ifndef WEBKIT_DATABASE_DATABASE_CONNECTIONS_H_ #define WEBKIT_DATABASE_DATABASE_CONNECTIONS_H_ -#include "base/string16.h" - #include <map> +#include <vector> + +#include "base/string16.h" namespace webkit_database { @@ -25,7 +26,9 @@ class DatabaseConnections { void RemoveConnection(const string16& origin_identifier, const string16& database_name); void RemoveAllConnections(); - void RemoveConnections(const DatabaseConnections& connections); + void RemoveConnections( + const DatabaseConnections& connections, + std::vector<std::pair<string16, string16> >* closed_dbs); private: typedef std::map<string16, int> DBConnections; diff --git a/webkit/database/database_tracker.cc b/webkit/database/database_tracker.cc index 15079ff..f2bb4ae 100644 --- a/webkit/database/database_tracker.cc +++ b/webkit/database/database_tracker.cc @@ -36,11 +36,14 @@ 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_); } void DatabaseTracker::SetDefaultQuota(int64 quota) { @@ -84,10 +87,34 @@ void DatabaseTracker::DatabaseModified(const string16& origin_identifier, void DatabaseTracker::DatabaseClosed(const string16& origin_identifier, const string16& database_name) { database_connections_.RemoveConnection(origin_identifier, database_name); + if (!database_connections_.IsDatabaseOpened(origin_identifier, database_name)) + DeleteDatabaseIfNeeded(origin_identifier, database_name); } void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) { - database_connections_.RemoveConnections(connections); + std::vector<std::pair<string16, string16> > closed_dbs; + database_connections_.RemoveConnections(connections, &closed_dbs); + for (std::vector<std::pair<string16, string16> >::iterator it = + closed_dbs.begin(); it != closed_dbs.end(); ++it) { + DeleteDatabaseIfNeeded(it->first, it->second); + } +} + +void DatabaseTracker::DeleteDatabaseIfNeeded(const string16& origin_identifier, + const string16& database_name) { + DCHECK(!database_connections_.IsDatabaseOpened(origin_identifier, + database_name)); + if (IsDatabaseScheduledForDeletion(origin_identifier, database_name)) { + DeleteDatabase(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; + } + } } void DatabaseTracker::AddObserver(Observer* observer) { @@ -195,6 +222,18 @@ bool DatabaseTracker::DeleteOrigin(const string16& origin_identifier) { return true; } +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); + if (it == dbs_to_be_deleted_.end()) + return false; + + std::set<string16>& databases = it->second; + return (databases.find(database_name) != databases.end()); +} + bool DatabaseTracker::LazyInit() { if (!initialized_) { DCHECK(!db_->is_open()); @@ -339,15 +378,31 @@ int64 DatabaseTracker::UpdateCachedDatabaseFileSize( return new_size; } +void DatabaseTracker::ScheduleDatabaseForDeletion( + const string16& origin_identifier, + const string16& database_name) { + DCHECK(database_connections_.IsDatabaseOpened(origin_identifier, + database_name)); + dbs_to_be_deleted_[origin_identifier].insert(database_name); + FOR_EACH_OBSERVER(Observer, observers_, OnDatabaseScheduledForDeletion( + origin_identifier, database_name)); +} + int DatabaseTracker::DeleteDataModifiedSince( const base::Time& cutoff, net::CompletionCallback* callback) { - if (!LazyInit()) + // Check for reentrancy. + if (dbs_deleted_callback_ || !LazyInit()) return net::ERR_FAILED; + DCHECK(callback); + dbs_deleted_callback_ = callback; + std::vector<string16> origins; - if (!databases_table_->GetAllOrigins(&origins)) + if (!databases_table_->GetAllOrigins(&origins)) { + dbs_deleted_callback_ = NULL; return net::ERR_FAILED; + } int rv = net::OK; for (std::vector<string16>::const_iterator ori = origins.begin(); ori != origins.end(); ++ori) { @@ -360,19 +415,26 @@ int DatabaseTracker::DeleteDataModifiedSince( } for (std::vector<DatabaseDetails>::const_iterator db = details.begin(); db != details.end(); ++db) { - // Check if the database is opened by any renderer. - if (database_connections_.IsDatabaseOpened(*ori, db->database_name)) { - // TODO(jochen): make renderer close the database. - rv = net::ERR_FAILED; - continue; - } FilePath db_file = GetFullDBFilePath(*ori, db->database_name); file_util::FileInfo file_info; file_util::GetFileInfo(db_file, &file_info); - if (file_info.last_modified >= cutoff) + if (file_info.last_modified < cutoff) + 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 (rv != net::ERR_IO_PENDING) { + dbs_to_be_deleted_.clear(); + dbs_deleted_callback_ = NULL; + } return rv; } diff --git a/webkit/database/database_tracker.h b/webkit/database/database_tracker.h index 93a60e5..a6c7720 100644 --- a/webkit/database/database_tracker.h +++ b/webkit/database/database_tracker.h @@ -6,6 +6,7 @@ #define WEBKIT_DATABASE_DATABASE_TRACKER_H_ #include <map> +#include <set> #include "base/file_path.h" #include "base/observer_list.h" @@ -92,6 +93,9 @@ class DatabaseTracker const string16& database_name, int64 database_size, int64 space_available) = 0; + virtual void OnDatabaseScheduledForDeletion( + const string16& origin_identifier, + const string16& database_name) = 0; virtual ~Observer() {} }; @@ -111,6 +115,8 @@ class DatabaseTracker void DatabaseClosed(const string16& origin_identifier, const string16& database_name); void CloseDatabases(const DatabaseConnections& connections); + void DeleteDatabaseIfNeeded(const string16& origin_identifier, + const string16& database_name); void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -126,6 +132,8 @@ class DatabaseTracker bool DeleteDatabase(const string16& origin_identifier, const string16& database_name); bool DeleteOrigin(const string16& origin_identifier); + bool IsDatabaseScheduledForDeletion(const string16& origin_identifier, + const string16& database_name); // Delete any databases that have been touched since the cutoff date that's // supplied. Returns net::OK on success, net::FAILED if not all databases @@ -178,6 +186,8 @@ class DatabaseTracker int64 UpdateCachedDatabaseFileSize(const string16& origin_identifier, const string16& database_name); + void ScheduleDatabaseForDeletion(const string16& origin_identifier, + const string16& database_name); bool initialized_; const FilePath db_dir_; @@ -189,6 +199,10 @@ class DatabaseTracker std::map<string16, CachedOriginInfo> origins_info_map_; DatabaseConnections database_connections_; + // The set of databases that should be deleted but are still opened + std::map<string16, std::set<string16> > dbs_to_be_deleted_; + net::CompletionCallback* dbs_deleted_callback_; + // Default quota for all origins; changed only by tests int64 default_quota_; diff --git a/webkit/database/database_tracker_unittest.cc b/webkit/database/database_tracker_unittest.cc index 8b44a451..0ed707d 100644 --- a/webkit/database/database_tracker_unittest.cc +++ b/webkit/database/database_tracker_unittest.cc @@ -26,6 +26,9 @@ class TestObserver : public webkit_database::DatabaseTracker::Observer { database_size_ = database_size; space_available_ = space_available; } + virtual void OnDatabaseScheduledForDeletion(const string16& origin_identifier, + const string16& database_name) { + } bool DidReceiveNewNotification() { bool temp_new_notification_received = new_notification_received_; new_notification_received_ = false; diff --git a/webkit/tools/test_shell/simple_database_system.cc b/webkit/tools/test_shell/simple_database_system.cc index a2cd8e3..edc03ee 100644 --- a/webkit/tools/test_shell/simple_database_system.cc +++ b/webkit/tools/test_shell/simple_database_system.cc @@ -1,6 +1,6 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this -// source code is governed by a BSD-style license that can be found in the -// LICENSE file. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "webkit/tools/test_shell/simple_database_system.h" @@ -134,6 +134,13 @@ void SimpleDatabaseSystem::OnDatabaseSizeChanged( } } +void SimpleDatabaseSystem::OnDatabaseScheduledForDeletion( + const string16& origin_identifier, + const string16& database_name) { + WebKit::WebDatabase::closeDatabaseImmediately( + origin_identifier, database_name); +} + void SimpleDatabaseSystem::databaseOpened(const WebKit::WebDatabase& database) { DatabaseOpened(database.securityOrigin().databaseIdentifier(), database.name(), database.displayName(), diff --git a/webkit/tools/test_shell/simple_database_system.h b/webkit/tools/test_shell/simple_database_system.h index 766940e..8441d31 100644 --- a/webkit/tools/test_shell/simple_database_system.h +++ b/webkit/tools/test_shell/simple_database_system.h @@ -1,6 +1,6 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this -// source code is governed by a BSD-style license that can be found in the -// LICENSE file. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef WEBKIT_TOOLS_TEST_SHELL_SIMPLE_DATABASE_SYSTEM_H_ #define WEBKIT_TOOLS_TEST_SHELL_SIMPLE_DATABASE_SYSTEM_H_ @@ -46,6 +46,8 @@ class SimpleDatabaseSystem : public webkit_database::DatabaseTracker::Observer, const string16& database_name, int64 database_size, int64 space_available); + virtual void OnDatabaseScheduledForDeletion(const string16& origin_identifier, + const string16& database_name); // WebDatabaseObserver implementation virtual void databaseOpened(const WebKit::WebDatabase& database); |