summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/DEPS3
-rw-r--r--chrome/browser/automation/automation_profile_impl.h3
-rw-r--r--chrome/browser/profile.cc17
-rw-r--r--chrome/browser/profile.h12
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc16
-rw-r--r--chrome/browser/renderer_host/database_dispatcher_host.cc513
-rw-r--r--chrome/browser/renderer_host/database_dispatcher_host.h118
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc9
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h8
-rw-r--r--chrome/common/db_message_filter.cc10
-rw-r--r--chrome/common/db_message_filter.h10
-rw-r--r--chrome/test/testing_profile.cc7
-rw-r--r--chrome/test/testing_profile.h10
13 files changed, 503 insertions, 233 deletions
diff --git a/chrome/DEPS b/chrome/DEPS
index ca6752e..1e982a0 100644
--- a/chrome/DEPS
+++ b/chrome/DEPS
@@ -21,6 +21,9 @@ include_rules = [
# Allow inclusion of the appcache library.
"+webkit/appcache",
+ # Allow inclusion of the database library.
+ "+webkit/database",
+
# Allow inclusion of Mozilla interface headers.
"+third_party/mozilla",
diff --git a/chrome/browser/automation/automation_profile_impl.h b/chrome/browser/automation/automation_profile_impl.h
index 54abd4c..0151193 100644
--- a/chrome/browser/automation/automation_profile_impl.h
+++ b/chrome/browser/automation/automation_profile_impl.h
@@ -51,6 +51,9 @@ class AutomationProfileImpl : public Profile {
virtual Profile* GetOriginalProfile() {
return original_profile_->GetOriginalProfile();
}
+ virtual webkit_database::DatabaseTracker* GetDatabaseTracker() {
+ return original_profile_->GetDatabaseTracker();
+ }
virtual VisitedLinkMaster* GetVisitedLinkMaster() {
return original_profile_->GetVisitedLinkMaster();
}
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index cbee927..9f62d39 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -55,6 +55,7 @@
#include "chrome/common/render_messages.h"
#include "grit/locale_settings.h"
#include "net/base/strict_transport_security_state.h"
+#include "webkit/database/database_tracker.h"
#if defined(OS_LINUX)
#include "net/ocsp/nss_ocsp.h"
@@ -237,6 +238,12 @@ class OffTheRecordProfileImpl : public Profile,
return profile_;
}
+ virtual webkit_database::DatabaseTracker* GetDatabaseTracker() {
+ if (!db_tracker_)
+ db_tracker_ = new webkit_database::DatabaseTracker(FilePath());
+ return db_tracker_;
+ }
+
virtual VisitedLinkMaster* GetVisitedLinkMaster() {
// We don't provide access to the VisitedLinkMaster when we're OffTheRecord
// because we don't want to leak the sites that the user has visited before.
@@ -565,6 +572,10 @@ class OffTheRecordProfileImpl : public Profile,
// Time we were started.
Time start_time_;
+ // The main database tracker for this profile.
+ // Should be used only on the file thread.
+ scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImpl);
};
@@ -830,6 +841,12 @@ Profile* ProfileImpl::GetOriginalProfile() {
return this;
}
+webkit_database::DatabaseTracker* ProfileImpl::GetDatabaseTracker() {
+ if (!db_tracker_)
+ db_tracker_ = new webkit_database::DatabaseTracker(GetPath());
+ return db_tracker_;
+}
+
VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() {
if (!visited_link_master_.get()) {
scoped_ptr<VisitedLinkMaster> visited_links(
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 659e1bd..7497e6d 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -29,6 +29,10 @@ class StrictTransportSecurityState;
class SSLConfigService;
}
+namespace webkit_database {
+class DatabaseTracker;
+}
+
class Blacklist;
class BookmarkModel;
class BrowserThemeProvider;
@@ -139,6 +143,9 @@ class Profile {
// profile is not off the record.
virtual Profile* GetOriginalProfile() = 0;
+ // Returns a pointer to the DatabaseTracker instance for this profile.
+ virtual webkit_database::DatabaseTracker* GetDatabaseTracker() = 0;
+
// Retrieves a pointer to the VisitedLinkMaster associated with this
// profile. The VisitedLinkMaster is lazily created the first time
// that this method is called.
@@ -421,6 +428,7 @@ class ProfileImpl : public Profile,
virtual Profile* GetOffTheRecordProfile();
virtual void DestroyOffTheRecordProfile();
virtual Profile* GetOriginalProfile();
+ virtual webkit_database::DatabaseTracker* GetDatabaseTracker();
virtual VisitedLinkMaster* GetVisitedLinkMaster();
virtual UserScriptMaster* GetUserScriptMaster();
virtual SSLHostState* GetSSLHostState();
@@ -595,6 +603,10 @@ class ProfileImpl : public Profile,
// GetSessionService won't recreate the SessionService.
bool shutdown_session_service_;
+ // The main database tracker for this profile.
+ // Should be used only on the file thread.
+ scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;
+
#if defined(OS_CHROMEOS)
chromeos::Preferences chromeos_preferences_;
#endif
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 144fb37..212134a 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -545,7 +545,6 @@ void BrowserRenderProcessHost::PropogateBrowserCommandLineToRenderer(
switches::kSimpleDataSource,
switches::kEnableBenchmarking,
switches::kInternalNaCl,
- switches::kEnableDatabases,
switches::kDisableByteRangeSupport,
switches::kDisableWebSockets,
switches::kDisableLocalStorage,
@@ -562,12 +561,27 @@ void BrowserRenderProcessHost::PropogateBrowserCommandLineToRenderer(
#endif
};
+ // Propagate the following switches to the renderer command line (along
+ // with any associated values) only if we're not in incognito mode.
+ static const char* const not_otr_switch_names[] = {
+ switches::kEnableDatabases,
+ };
+
for (size_t i = 0; i < arraysize(switch_names); ++i) {
if (browser_cmd.HasSwitch(switch_names[i])) {
renderer_cmd->AppendSwitchWithValue(switch_names[i],
browser_cmd.GetSwitchValueASCII(switch_names[i]));
}
}
+
+ if (!profile()->IsOffTheRecord()) {
+ for (size_t i = 0; i < arraysize(not_otr_switch_names); ++i) {
+ if (browser_cmd.HasSwitch(not_otr_switch_names[i])) {
+ renderer_cmd->AppendSwitchWithValue(not_otr_switch_names[i],
+ browser_cmd.GetSwitchValueASCII(not_otr_switch_names[i]));
+ }
+ }
+ }
}
#if defined(OS_WIN)
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.cc b/chrome/browser/renderer_host/database_dispatcher_host.cc
index c13f8c7..171a0ad 100644
--- a/chrome/browser/renderer_host/database_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/database_dispatcher_host.cc
@@ -4,8 +4,8 @@
#include "chrome/browser/renderer_host/database_dispatcher_host.h"
-#if defined(OS_WIN)
-#include <windows.h>
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
#endif
#if defined(USE_SYSTEM_SQLITE)
@@ -14,262 +14,403 @@
#include "third_party/sqlite/preprocessed/sqlite3.h"
#endif
+#include "base/string_util.h"
+#include "base/thread.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/renderer_host/resource_message_filter.h"
+#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/common/render_messages.h"
#include "webkit/database/vfs_backend.h"
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#endif
-
+using webkit_database::DatabaseTracker;
using webkit_database::VfsBackend;
-const int kNumDeleteRetries = 3;
+const int kNumDeleteRetries = 2;
const int kDelayDeleteRetryMs = 100;
-namespace {
+DatabaseDispatcherHost::DatabaseDispatcherHost(
+ DatabaseTracker* db_tracker,
+ IPC::Message::Sender* message_sender,
+ base::ProcessHandle process_handle)
+ : db_tracker_(db_tracker),
+ message_sender_(message_sender),
+ process_handle_(process_handle),
+ observer_added_(false),
+ shutdown_(false) {
+ DCHECK(db_tracker_);
+ DCHECK(message_sender_);
+}
+
+void DatabaseDispatcherHost::Shutdown() {
+ shutdown_ = true;
+ message_sender_ = NULL;
+ if (observer_added_) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &DatabaseDispatcherHost::RemoveObserver));
+ }
+}
+
+void DatabaseDispatcherHost::AddObserver() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ db_tracker_->AddObserver(this);
+}
-struct OpenFileParams {
- FilePath db_dir;
- FilePath file_name;
- int desired_flags;
- base::ProcessHandle handle;
-};
+void DatabaseDispatcherHost::RemoveObserver() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ db_tracker_->RemoveObserver(this);
+}
+
+FilePath DatabaseDispatcherHost::GetDBFileFullPath(
+ const FilePath& vfs_file_name) {
+ // 'vfs_file_name' can be one of 3 things:
+ // 1. Empty string: It means the VFS wants to open a temp file. In this case
+ // we need to return the path to the directory that stores all databases.
+ // 2. origin_identifier/database_name: In this case, we need to extract
+ // 'origin_identifier' and 'database_name' and pass them to
+ // DatabaseTracker::GetFullDBFilePath().
+ // 3. origin_identifier/database_name-suffix: '-suffix' could be '-journal',
+ // for example. In this case, we need to extract 'origin_identifier' and
+ // 'database_name-suffix' and pass them to
+ // DatabaseTracker::GetFullDBFilePath(). 'database_name-suffix' is not
+ // a database name as expected by DatabaseTracker::GetFullDBFilePath(),
+ // but due to its implementation, it's OK to pass in 'database_name-suffix'
+ // too.
+ //
+ // We also check that the given string doesn't contain invalid characters
+ // that would result in a DB file stored outside of the directory where
+ // all DB files are supposed to be stored.
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ if (vfs_file_name.empty())
+ return db_tracker_->DatabaseDirectory();
+
+ std::wstring str = vfs_file_name.ToWStringHack();
+ size_t slashIndex = str.find('/');
+ if (slashIndex == std::wstring::npos)
+ return FilePath(); // incorrect format
+ std::wstring origin_identifier = str.substr(0, slashIndex);
+ std::wstring database_name =
+ str.substr(slashIndex + 1, str.length() - slashIndex);
+ if ((origin_identifier.find('\\') != std::wstring::npos) ||
+ (origin_identifier.find('/') != std::wstring::npos) ||
+ (origin_identifier.find(':') != std::wstring::npos) ||
+ (database_name.find('\\') != std::wstring::npos) ||
+ (database_name.find('/') != std::wstring::npos) ||
+ (database_name.find(':') != std::wstring::npos)) {
+ return FilePath();
+ }
+
+ return db_tracker_->GetFullDBFilePath(
+ WideToUTF16(origin_identifier), WideToUTF16(database_name));
+}
+
+bool DatabaseDispatcherHost::OnMessageReceived(
+ const IPC::Message& message, bool* message_was_ok) {
+ DCHECK(!shutdown_);
+ *message_was_ok = true;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(DatabaseDispatcherHost, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpenFile, OnDatabaseOpenFile)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseDeleteFile, OnDatabaseDeleteFile)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileAttributes,
+ OnDatabaseGetFileAttributes)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileSize,
+ OnDatabaseGetFileSize)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpened, OnDatabaseOpened)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseModified, OnDatabaseModified)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseClosed, OnDatabaseClosed)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+ return handled;
+}
-struct DeleteFileParams {
- FilePath db_dir;
- FilePath file_name;
- bool sync_dir;
-};
+void DatabaseDispatcherHost::ReceivedBadMessage(uint16 msg_type) {
+ BrowserRenderProcessHost::BadMessageTerminateProcess(
+ msg_type, process_handle_);
+}
-// Scheduled by the file Thread on the IO thread.
+// Scheduled by the file thread on the IO thread.
// Sends back to the renderer process the given message.
-static void SendMessage(ResourceMessageFilter* sender,
- IPC::Message* message) {
- sender->Send(message);
-
- // Every time we get a DB-related message, we AddRef() the resource
- // message filterto make sure it doesn't get destroyed before we have
- // a chance to send the reply back. So we need to Release() is here
- // and allow it to be destroyed if needed.
- sender->Release();
+void DatabaseDispatcherHost::SendMessage(IPC::Message* message) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ if (!shutdown_)
+ message_sender_->Send(message);
+ else
+ delete message;
+}
+
+void DatabaseDispatcherHost::OnDatabaseOpenFile(const FilePath& vfs_file_name,
+ int desired_flags,
+ int32 message_id) {
+ if (!observer_added_) {
+ observer_added_ = true;
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &DatabaseDispatcherHost::AddObserver));
+ }
+
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseOpenFile,
+ vfs_file_name,
+ desired_flags,
+ message_id));
+}
+
+static void SetOpenFileResponseParams(
+ ViewMsg_DatabaseOpenFileResponse_Params* params,
+ base::PlatformFile file_handle,
+ base::PlatformFile dir_handle) {
+#if defined(OS_WIN)
+ params->file_handle = file_handle;
+#elif defined(OS_POSIX)
+ params->file_handle = base::FileDescriptor(file_handle, true);
+ params->dir_handle = base::FileDescriptor(dir_handle, true);
+#endif
}
// Scheduled by the IO thread on the file thread.
// Opens the given database file, then schedules
// a task on the IO thread's message loop to send an IPC back to
// corresponding renderer process with the file handle.
-static void DatabaseOpenFile(const OpenFileParams& params,
- int32 message_id,
- ResourceMessageFilter* sender) {
+void DatabaseDispatcherHost::DatabaseOpenFile(const FilePath& vfs_file_name,
+ int desired_flags,
+ int32 message_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
base::PlatformFile target_handle = base::kInvalidPlatformFileValue;
base::PlatformFile target_dir_handle = base::kInvalidPlatformFileValue;
- VfsBackend::OpenFile(params.file_name, params.db_dir, params.desired_flags,
- params.handle, &target_handle, &target_dir_handle);
+ FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
+ if (!db_file_name.empty()) {
+ FilePath db_dir = db_tracker_->DatabaseDirectory();
+ VfsBackend::OpenFile(db_file_name, db_dir, desired_flags,
+ process_handle_, &target_handle, &target_dir_handle);
+ }
ViewMsg_DatabaseOpenFileResponse_Params response_params;
-#if defined(OS_WIN)
- response_params.file_handle = target_handle;
-#elif defined(OS_POSIX)
- response_params.file_handle = base::FileDescriptor(target_handle, true);
- response_params.dir_handle = base::FileDescriptor(target_dir_handle, true);
-#endif
+ SetOpenFileResponseParams(&response_params, target_handle, target_dir_handle);
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(SendMessage, sender,
- new ViewMsg_DatabaseOpenFileResponse(message_id, response_params)));
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::SendMessage,
+ new ViewMsg_DatabaseOpenFileResponse(
+ message_id, response_params)));
+}
+
+void DatabaseDispatcherHost::OnDatabaseDeleteFile(const FilePath& vfs_file_name,
+ const bool& sync_dir,
+ int32 message_id) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseDeleteFile,
+ vfs_file_name,
+ sync_dir,
+ message_id,
+ kNumDeleteRetries));
}
// Scheduled by the IO thread on the file thread.
// Deletes the given database file, then schedules
// a task on the IO thread's message loop to send an IPC back to
// corresponding renderer process with the error code.
-static void DatabaseDeleteFile(const DeleteFileParams& params,
- int32 message_id,
- int reschedule_count,
- ResourceMessageFilter* sender) {
- // Return an error if the file could not be deleted
- // after kNumDeleteRetries times.
- if (!reschedule_count) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(SendMessage, sender,
- new ViewMsg_DatabaseDeleteFileResponse(message_id,
- SQLITE_IOERR_DELETE)));
- return;
- }
-
- int error_code =
- VfsBackend::DeleteFile(params.file_name, params.db_dir, params.sync_dir);
- if (error_code == SQLITE_IOERR_DELETE) {
- // If the file could not be deleted, try again.
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- NewRunnableFunction(DatabaseDeleteFile, params, message_id,
- reschedule_count - 1, sender),
- kDelayDeleteRetryMs);
- return;
+void DatabaseDispatcherHost::DatabaseDeleteFile(const FilePath& vfs_file_name,
+ bool sync_dir,
+ int32 message_id,
+ int reschedule_count) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+
+ // Return an error if the file name is invalid or if the file could not
+ // be deleted after kNumDeleteRetries attempts.
+ int error_code = SQLITE_IOERR_DELETE;
+ FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
+ if (!db_file_name.empty()) {
+ FilePath db_dir = db_tracker_->DatabaseDirectory();
+ error_code = VfsBackend::DeleteFile(db_file_name, db_dir, sync_dir);
+ if ((error_code == SQLITE_IOERR_DELETE) && reschedule_count) {
+ // If the file could not be deleted, try again.
+ ChromeThread::PostDelayedTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseDeleteFile,
+ vfs_file_name,
+ sync_dir,
+ message_id,
+ reschedule_count - 1),
+ kDelayDeleteRetryMs);
+ return;
+ }
}
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(SendMessage, sender,
- new ViewMsg_DatabaseDeleteFileResponse(message_id, error_code)));
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::SendMessage,
+ new ViewMsg_DatabaseDeleteFileResponse(
+ message_id, error_code)));
+}
+
+void DatabaseDispatcherHost::OnDatabaseGetFileAttributes(
+ const FilePath& vfs_file_name,
+ int32 message_id) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseGetFileAttributes,
+ vfs_file_name,
+ message_id));
}
// Scheduled by the IO thread on the file thread.
// Gets the attributes of the given database file, then schedules
// a task on the IO thread's message loop to send an IPC back to
// corresponding renderer process.
-static void DatabaseGetFileAttributes(const FilePath& file_name,
- int32 message_id,
- ResourceMessageFilter* sender) {
- uint32 attributes = VfsBackend::GetFileAttributes(file_name);
+void DatabaseDispatcherHost::DatabaseGetFileAttributes(
+ const FilePath& vfs_file_name,
+ int32 message_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ int32 attributes = -1;
+ FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
+ if (!db_file_name.empty())
+ attributes = VfsBackend::GetFileAttributes(db_file_name);
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(SendMessage, sender,
- new ViewMsg_DatabaseGetFileAttributesResponse(
- message_id, attributes)));
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::SendMessage,
+ new ViewMsg_DatabaseGetFileAttributesResponse(
+ message_id, attributes)));
+}
+
+void DatabaseDispatcherHost::OnDatabaseGetFileSize(
+ const FilePath& vfs_file_name, int32 message_id) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseGetFileSize,
+ vfs_file_name,
+ message_id));
}
// Scheduled by the IO thread on the file thread.
// Gets the size of the given file, then schedules a task
// on the IO thread's message loop to send an IPC back to
// the corresponding renderer process.
-static void DatabaseGetFileSize(const FilePath& file_name,
- int32 message_id,
- ResourceMessageFilter* sender) {
- int64 size = VfsBackend::GetFileSize(file_name);
+void DatabaseDispatcherHost::DatabaseGetFileSize(const FilePath& vfs_file_name,
+ int32 message_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ int64 size = 0;
+ FilePath db_file_name = GetDBFileFullPath(vfs_file_name);
+ if (!db_file_name.empty())
+ size = VfsBackend::GetFileSize(db_file_name);
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(SendMessage, sender,
- new ViewMsg_DatabaseGetFileSizeResponse(message_id, size)));
-}
-
-} // namespace
-
-DatabaseDispatcherHost::DatabaseDispatcherHost(
- const FilePath& profile_path,
- ResourceMessageFilter* resource_message_filter)
- : profile_path_(profile_path),
- resource_message_filter_(resource_message_filter) {
-}
-
-bool DatabaseDispatcherHost::OnMessageReceived(
- const IPC::Message& message, bool* message_was_ok) {
- *message_was_ok = true;
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(DatabaseDispatcherHost, message, *message_was_ok)
- IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseOpenFile, OnDatabaseOpenFile);
- IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseDeleteFile, OnDatabaseDeleteFile);
- IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileAttributes,
- OnDatabaseGetFileAttributes);
- IPC_MESSAGE_HANDLER(ViewHostMsg_DatabaseGetFileSize,
- OnDatabaseGetFileSize);
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP_EX()
- return handled;
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::SendMessage,
+ new ViewMsg_DatabaseGetFileSizeResponse(
+ message_id, size)));
}
-FilePath DatabaseDispatcherHost::GetDBDir() {
- return profile_path_.Append(FILE_PATH_LITERAL("databases"));
+void DatabaseDispatcherHost::OnDatabaseOpened(const string16& origin_identifier,
+ const string16& database_name,
+ const string16& description,
+ int64 estimated_size) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseOpened,
+ origin_identifier,
+ database_name,
+ description,
+ estimated_size));
}
-FilePath DatabaseDispatcherHost::GetDBFileFullPath(const FilePath& file_name) {
- // Do not allow '\', '/' and ':' in file names.
- FilePath::StringType file = file_name.value();
- if ((file.find('\\') != std::wstring::npos) ||
- (file.find('/') != std::wstring::npos) ||
- (file.find(':') != std::wstring::npos)) {
- return FilePath();
- }
- return GetDBDir().Append(file_name);
+void DatabaseDispatcherHost::DatabaseOpened(const string16& origin_identifier,
+ const string16& database_name,
+ const string16& description,
+ int64 estimated_size) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ int64 database_size = 0;
+ int64 space_available = 0;
+ AddAccessedOrigin(origin_identifier);
+ db_tracker_->DatabaseOpened(origin_identifier, database_name, description,
+ estimated_size, &database_size, &space_available);
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::SendMessage,
+ new ViewMsg_DatabaseUpdateSize(
+ origin_identifier, database_name,
+ database_size, space_available)));
}
-void DatabaseDispatcherHost::OnDatabaseOpenFile(const FilePath& file_name,
- int desired_flags,
- int32 message_id) {
- FilePath db_file_name = GetDBFileFullPath(file_name);
-
- if (db_file_name.empty()) {
- ViewMsg_DatabaseOpenFileResponse_Params response_params;
-#if defined(OS_WIN)
- response_params.file_handle = base::kInvalidPlatformFileValue;
-#elif defined(OS_POSIX)
- response_params.file_handle =
- base::FileDescriptor(base::kInvalidPlatformFileValue, true);
- response_params.dir_handle =
- base::FileDescriptor(base::kInvalidPlatformFileValue, true);
-#endif
- resource_message_filter_->Send(new ViewMsg_DatabaseOpenFileResponse(
- message_id, response_params));
- return;
- }
-
- OpenFileParams params;
- params.db_dir = GetDBDir();
- params.file_name = db_file_name;
- params.desired_flags = desired_flags;
- params.handle = resource_message_filter_->handle();
- resource_message_filter_->AddRef();
+void DatabaseDispatcherHost::OnDatabaseModified(
+ const string16& origin_identifier,
+ const string16& database_name) {
ChromeThread::PostTask(
ChromeThread::FILE, FROM_HERE,
- NewRunnableFunction(
- DatabaseOpenFile, params, message_id, resource_message_filter_));
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseModified,
+ origin_identifier,
+ database_name));
}
-void DatabaseDispatcherHost::OnDatabaseDeleteFile(
- const FilePath& file_name, const bool& sync_dir, int32 message_id) {
- FilePath db_file_name = GetDBFileFullPath(file_name);
- if (db_file_name.empty()) {
- resource_message_filter_->Send(new ViewMsg_DatabaseDeleteFileResponse(
- message_id, SQLITE_IOERR_DELETE));
+void DatabaseDispatcherHost::DatabaseModified(const string16& origin_identifier,
+ const string16& database_name) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ if (!HasAccessedOrigin(origin_identifier)) {
+ ReceivedBadMessage(ViewHostMsg_DatabaseModified::ID);
return;
}
- DeleteFileParams params;
- params.db_dir = GetDBDir();
- params.file_name = db_file_name;
- params.sync_dir = sync_dir;
- resource_message_filter_->AddRef();
+ db_tracker_->DatabaseModified(origin_identifier, database_name);
+}
+
+void DatabaseDispatcherHost::OnDatabaseClosed(const string16& origin_identifier,
+ const string16& database_name) {
ChromeThread::PostTask(
ChromeThread::FILE, FROM_HERE,
- NewRunnableFunction(
- DatabaseDeleteFile, params, message_id, kNumDeleteRetries,
- resource_message_filter_));
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::DatabaseClosed,
+ origin_identifier,
+ database_name));
}
-void DatabaseDispatcherHost::OnDatabaseGetFileAttributes(
- const FilePath& file_name, int32 message_id) {
- FilePath db_file_name = GetDBFileFullPath(file_name);
- if (db_file_name.empty()) {
- resource_message_filter_->Send(
- new ViewMsg_DatabaseGetFileAttributesResponse(message_id, -1));
+void DatabaseDispatcherHost::DatabaseClosed(const string16& origin_identifier,
+ const string16& database_name) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ if (!HasAccessedOrigin(origin_identifier)) {
+ ReceivedBadMessage(ViewHostMsg_DatabaseClosed::ID);
return;
}
- resource_message_filter_->AddRef();
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- NewRunnableFunction(
- DatabaseGetFileAttributes, db_file_name, message_id,
- resource_message_filter_));
+ db_tracker_->DatabaseClosed(origin_identifier, database_name);
}
-void DatabaseDispatcherHost::OnDatabaseGetFileSize(
- const FilePath& file_name, int32 message_id) {
- FilePath db_file_name = GetDBFileFullPath(file_name);
- if (db_file_name.empty()) {
- resource_message_filter_->Send(new ViewMsg_DatabaseGetFileSizeResponse(
- message_id, 0));
- return;
+void DatabaseDispatcherHost::OnDatabaseSizeChanged(
+ const string16& origin_identifier,
+ const string16& database_name,
+ int64 database_size,
+ int64 space_available) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ if (HasAccessedOrigin(origin_identifier)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &DatabaseDispatcherHost::SendMessage,
+ new ViewMsg_DatabaseUpdateSize(
+ origin_identifier, database_name,
+ database_size, space_available)));
}
+}
- resource_message_filter_->AddRef();
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- NewRunnableFunction(
- DatabaseGetFileSize, db_file_name, message_id,
- resource_message_filter_));
+void DatabaseDispatcherHost::AddAccessedOrigin(
+ const string16& origin_identifier) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ accessed_origins_.insert(origin_identifier);
+}
+
+bool DatabaseDispatcherHost::HasAccessedOrigin(
+ const string16& origin_identifier) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ return (accessed_origins_.find(origin_identifier) != accessed_origins_.end());
}
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.h b/chrome/browser/renderer_host/database_dispatcher_host.h
index fd403d2..5053138 100644
--- a/chrome/browser/renderer_host/database_dispatcher_host.h
+++ b/chrome/browser/renderer_host/database_dispatcher_host.h
@@ -6,55 +6,105 @@
#define CHROME_BROWSER_RENDERER_HOST_DATABASE_DISPATCHER_HOST_H_
#include "base/file_path.h"
+#include "base/hash_tables.h"
+#include "base/process.h"
+#include "base/ref_counted.h"
+#include "base/string16.h"
+#include "ipc/ipc_message.h"
+#include "webkit/database/database_tracker.h"
-class ResourceMessageFilter;
-
-namespace IPC {
-class Message;
-}
-
-class DatabaseDispatcherHost {
+class DatabaseDispatcherHost
+ : public base::RefCountedThreadSafe<DatabaseDispatcherHost>,
+ public webkit_database::DatabaseTracker::Observer {
public:
- DatabaseDispatcherHost(const FilePath& profile_path,
- ResourceMessageFilter* resource_message_filter);
- ~DatabaseDispatcherHost() {}
+ DatabaseDispatcherHost(webkit_database::DatabaseTracker* db_tracker,
+ IPC::Message::Sender* message_sender,
+ base::ProcessHandle process_handle);
+ void Shutdown();
- // Returns true iff the message is HTML5 DB related and was processed.
bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok);
- private:
- // Message handlers.
- // Processes the request to return a handle to the given DB file.
- void OnDatabaseOpenFile(const FilePath& file_name,
+ // VFS message handlers (IO thread)
+ void OnDatabaseOpenFile(const FilePath& vfs_file_name,
int desired_flags,
int32 message_id);
-
- // Processes the request to delete the given DB file.
- void OnDatabaseDeleteFile(const FilePath& file_name,
+ void OnDatabaseDeleteFile(const FilePath& vfs_file_name,
const bool& sync_dir,
int32 message_id);
-
- // Processes the request to return the attributes of the given DB file.
- void OnDatabaseGetFileAttributes(const FilePath& file_name,
+ void OnDatabaseGetFileAttributes(const FilePath& vfs_file_name,
int32 message_id);
-
- // Processes the request to return the size of the given file.
- void OnDatabaseGetFileSize(const FilePath& file_name,
+ void OnDatabaseGetFileSize(const FilePath& vfs_file_name,
int32 message_id);
- // Returns the directory where all DB files are stored.
- FilePath GetDBDir();
+ // Database tracker message handlers (IO thread)
+ void OnDatabaseOpened(const string16& origin_identifier,
+ const string16& database_name,
+ const string16& description,
+ int64 estimated_size);
+ void OnDatabaseModified(const string16& origin_identifier,
+ const string16& database_name);
+ void OnDatabaseClosed(const string16& origin_identifier,
+ const string16& database_name);
+
+ // DatabaseTracker::Observer callback (file thread)
+ virtual void OnDatabaseSizeChanged(const string16& origin_identifier,
+ const string16& database_name,
+ int64 database_size,
+ int64 space_available);
+
+ private:
+ void AddObserver();
+ void RemoveObserver();
+ FilePath GetDBFileFullPath(const FilePath& vfs_file_name);
+
+ void ReceivedBadMessage(uint16 msg_type);
+ void SendMessage(IPC::Message* message);
+
+ // VFS message handlers (file thread)
+ void DatabaseOpenFile(const FilePath& vfs_file_name,
+ int desired_flags,
+ int32 message_id);
+ void DatabaseDeleteFile(const FilePath& vfs_file_name,
+ bool sync_dir,
+ int32 message_id,
+ int reschedule_count);
+ void DatabaseGetFileAttributes(const FilePath& vfs_file_name,
+ int32 message_id);
+ void DatabaseGetFileSize(const FilePath& vfs_file_name,
+ int32 message_id);
+
+ // Database tracker message handlers (file thread)
+ void DatabaseOpened(const string16& origin_identifier,
+ const string16& file_name,
+ const string16& description,
+ int64 estimated_size);
+ void DatabaseModified(const string16& origin_identifier,
+ const string16& database_name);
+ void DatabaseClosed(const string16& origin_identifier,
+ const string16& database_name);
+
+ void AddAccessedOrigin(const string16& origin_identifier);
+ bool HasAccessedOrigin(const string16& origin_identifier);
+
+ // The database tracker for the current profile.
+ scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;
+
+ // The sender to be used for sending out IPC messages.
+ IPC::Message::Sender* message_sender_;
+
+ // The handle of this process.
+ const base::ProcessHandle process_handle_;
- // Returns the absolute name of the given DB file.
- FilePath GetDBFileFullPath(const FilePath& file_name);
+ // True if and only if this instance was added as an observer
+ // to DatabaseTracker.
+ bool observer_added_;
- // The user data directory.
- FilePath profile_path_;
+ // If true, all messages that are normally processed by this class
+ // will be silently discarded. This field should be set to true
+ // only when the corresponding renderer process is about to go away.
+ bool shutdown_;
- // The ResourceMessageFilter instance of this renderer process. Can't keep
- // a refptr or else we'll get into a cycle. It's always ok to use this in
- // the IO thread since if the RMF goes away, this object is deleted.
- ResourceMessageFilter* resource_message_filter_;
+ base::hash_set<string16> accessed_origins_;
};
#endif // CHROME_BROWSER_RENDERER_HOST_DATABASE_DISPATCHER_HOST_H_
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index e386edc..2cf9b6c 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -171,7 +171,8 @@ ResourceMessageFilter::ResourceMessageFilter(
new DOMStorageDispatcherHost(this, profile->GetWebKitContext(),
resource_dispatcher_host->webkit_thread()))),
ALLOW_THIS_IN_INITIALIZER_LIST(db_dispatcher_host_(
- new DatabaseDispatcherHost(profile->GetPath(), this))),
+ new DatabaseDispatcherHost(profile->GetDatabaseTracker(),
+ this, handle()))),
notification_prefs_(
profile->GetDesktopNotificationService()->prefs_cache()),
socket_stream_dispatcher_host_(new SocketStreamDispatcherHost),
@@ -193,6 +194,9 @@ ResourceMessageFilter::~ResourceMessageFilter() {
// Tell the DOM Storage dispatcher host to stop sending messages via us.
dom_storage_dispatcher_host_->Shutdown();
+ // Shut down the database dispatcher host.
+ db_dispatcher_host_->Shutdown();
+
// Let interested observers know we are being deleted.
NotificationService::current()->Notify(
NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN,
@@ -540,8 +544,7 @@ void ResourceMessageFilter::OnGetRawCookies(
}
void ResourceMessageFilter::OnDeleteCookie(const GURL& url,
- const std::string& cookie_name)
-{
+ const std::string& cookie_name) {
URLRequestContext* context = GetRequestContextForURL(url);
net::CookieMonster* cookie_monster = context->cookie_store()->
GetCookieMonster();
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 9d21a4f..4971cdb 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_RENDERER_HOST_RESOURCE_MSG_FILTER_H_
-#define CHROME_BROWSER_RENDERER_HOST_RESOURCE_MSG_FILTER_H_
+#ifndef CHROME_BROWSER_RENDERER_HOST_RESOURCE_MESSAGE_FILTER_H_
+#define CHROME_BROWSER_RENDERER_HOST_RESOURCE_MESSAGE_FILTER_H_
#if defined(OS_WIN)
#include <windows.h>
@@ -376,7 +376,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
scoped_refptr<DOMStorageDispatcherHost> dom_storage_dispatcher_host_;
// Handles HTML5 DB related messages
- scoped_ptr<DatabaseDispatcherHost> db_dispatcher_host_;
+ scoped_refptr<DatabaseDispatcherHost> db_dispatcher_host_;
// A cache of notifications preferences which is used to handle
// Desktop Notifications permission messages.
@@ -394,4 +394,4 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter);
};
-#endif // CHROME_BROWSER_RENDERER_HOST_RESOURCE_MSG_FILTER_H_
+#endif // CHROME_BROWSER_RENDERER_HOST_RESOURCE_MESSAGE_FILTER_H_
diff --git a/chrome/common/db_message_filter.cc b/chrome/common/db_message_filter.cc
index 3ca841b..939c6e8 100644
--- a/chrome/common/db_message_filter.cc
+++ b/chrome/common/db_message_filter.cc
@@ -6,6 +6,7 @@
#include "chrome/common/child_process.h"
#include "chrome/common/render_messages.h"
+#include "webkit/api/public/WebDatabase.h"
DBMessageFilter* DBMessageFilter::instance_ = NULL;
@@ -64,7 +65,16 @@ bool DBMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_DatabaseGetFileAttributesResponse,
OnResponse<uint32>)
IPC_MESSAGE_HANDLER(ViewMsg_DatabaseGetFileSizeResponse, OnResponse<int64>)
+ IPC_MESSAGE_HANDLER(ViewMsg_DatabaseUpdateSize, OnDatabaseUpdateSize)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+
+void DBMessageFilter::OnDatabaseUpdateSize(const string16& origin_identifier,
+ const string16& database_name,
+ int64 database_size,
+ int64 space_available) {
+ WebKit::WebDatabase::updateDatabaseSize(
+ origin_identifier, database_name, database_size, space_available);
+}
diff --git a/chrome/common/db_message_filter.h b/chrome/common/db_message_filter.h
index 23035e9..f28ea4b 100644
--- a/chrome/common/db_message_filter.h
+++ b/chrome/common/db_message_filter.h
@@ -81,7 +81,7 @@ class DBMessageFilter : public IPC::ChannelProxy::MessageFilter {
// and not accept any more messages.
virtual void OnChannelClosing();
- // Processes the reply to a DB request.
+ // Processes the reply to a sync DB request.
template<class ResultType>
void OnResponse(int32 message_id, ResultType result) {
DBMessageState *state = messages_awaiting_replies_->Lookup(message_id);
@@ -92,6 +92,12 @@ class DBMessageFilter : public IPC::ChannelProxy::MessageFilter {
}
}
+ // Processes IPCs that indicate a change in the size of a DB file.
+ void OnDatabaseUpdateSize(const string16& origin_identifier,
+ const string16& database_name,
+ int64 database_size,
+ int64 space_available);
+
// The message loop for the IO thread.
MessageLoop* io_thread_message_loop_;
@@ -115,4 +121,4 @@ class DBMessageFilter : public IPC::ChannelProxy::MessageFilter {
static DBMessageFilter* instance_;
};
-#endif // CHROME_COMMON_DB_MESSAGE_FILTER_H_
+#endif // CHROME_COMMON_DB_MESSAGE_FILTER_H_
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index 86e7eab..b718773 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/common/chrome_constants.h"
+#include "webkit/database/database_tracker.h"
#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
#include "chrome/browser/gtk/gtk_theme_provider.h"
@@ -182,6 +183,12 @@ void TestingProfile::UseThemeProvider(BrowserThemeProvider* theme_provider) {
theme_provider_.reset(theme_provider);
}
+webkit_database::DatabaseTracker* TestingProfile::GetDatabaseTracker() {
+ if (!db_tracker_)
+ db_tracker_ = new webkit_database::DatabaseTracker(GetPath());
+ return db_tracker_;
+}
+
void TestingProfile::InitThemes() {
if (!created_theme_provider_) {
#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 0d13268..14b64da 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -18,7 +18,6 @@
#include "chrome/browser/sessions/session_service.h"
#include "chrome/common/pref_service.h"
-
class TestingProfile : public Profile {
public:
TestingProfile();
@@ -76,6 +75,7 @@ class TestingProfile : public Profile {
virtual void DestroyOffTheRecordProfile() {}
virtual Profile* GetOriginalProfile() { return this; }
+ virtual webkit_database::DatabaseTracker* GetDatabaseTracker();
virtual VisitedLinkMaster* GetVisitedLinkMaster() { return NULL; }
virtual ExtensionsService* GetExtensionsService() { return NULL; }
virtual UserScriptMaster* GetUserScriptMaster() { return NULL; }
@@ -241,6 +241,10 @@ class TestingProfile : public Profile {
// Did the last session exit cleanly? Default is true.
bool last_session_exited_cleanly_;
+
+ // The main database tracker for this profile.
+ // Should be used only on the file thread.
+ scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;
};
// A profile that derives from another profile. This does not actually
@@ -248,8 +252,8 @@ class TestingProfile : public Profile {
// site information.
class DerivedTestingProfile : public TestingProfile {
public:
- DerivedTestingProfile(Profile* profile) : original_profile_(profile) {
- }
+ explicit DerivedTestingProfile(Profile* profile)
+ : original_profile_(profile) {}
virtual ProfileId GetRuntimeId() {
return original_profile_->GetRuntimeId();