summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host
diff options
context:
space:
mode:
authordumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-27 23:06:34 +0000
committerdumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-27 23:06:34 +0000
commit017022b726b9e1b7ceb022c3b046b0cadb0302f9 (patch)
tree7fb115ea6421413029ae4f35ca7b6d09fc66fc95 /chrome/browser/renderer_host
parent0f9813550e8055faab81e77a9e134b3cff3aa3b3 (diff)
downloadchromium_src-017022b726b9e1b7ceb022c3b046b0cadb0302f9.zip
chromium_src-017022b726b9e1b7ceb022c3b046b0cadb0302f9.tar.gz
chromium_src-017022b726b9e1b7ceb022c3b046b0cadb0302f9.tar.bz2
Adding HTML5 DB support to Chromium: Chromium changes
BUG=none TEST=none Review URL: http://codereview.chromium.org/74001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21736 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host')
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc1
-rw-r--r--chrome/browser/renderer_host/database_dispatcher_host.cc291
-rw-r--r--chrome/browser/renderer_host/database_dispatcher_host.h59
-rw-r--r--chrome/browser/renderer_host/render_sandbox_host_linux.cc15
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc7
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h4
6 files changed, 376 insertions, 1 deletions
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 26e7f92..345416d 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -340,6 +340,7 @@ bool BrowserRenderProcessHost::Init() {
switches::kDisableAudio,
switches::kSimpleDataSource,
switches::kEnableBenchmarking,
+ switches::kEnableDatabases,
};
for (size_t i = 0; i < arraysize(switch_names); ++i) {
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.cc b/chrome/browser/renderer_host/database_dispatcher_host.cc
new file mode 100644
index 0000000..0e182da
--- /dev/null
+++ b/chrome/browser/renderer_host/database_dispatcher_host.cc
@@ -0,0 +1,291 @@
+// 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.
+
+#include "chrome/browser/renderer_host/database_dispatcher_host.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/platform_file.h"
+#include "base/process.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "base/thread.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/renderer_host/resource_message_filter.h"
+#include "chrome/common/render_messages.h"
+#include "ipc/ipc_message.h"
+#include "third_party/sqlite/preprocessed/sqlite3.h"
+
+const int kNumDeleteRetries = 5;
+const int kDelayDeleteRetryMs = 100;
+
+namespace {
+
+struct OpenFileParams {
+ FilePath db_dir; // directory where all DB files are stored
+ FilePath file_name; // DB file
+ int desired_flags; // flags to be used to open the file
+ base::ProcessHandle handle; // the handle of the renderer process
+};
+
+// 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();
+}
+
+// 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(MessageLoop* io_thread_message_loop,
+ const OpenFileParams& params,
+ int32 message_id,
+ ResourceMessageFilter* sender) {
+ base::PlatformFile target_handle = base::kInvalidPlatformFileValue;
+ // Create the database directory if it doesn't exist.
+ if (file_util::CreateDirectory(params.db_dir)) {
+ int flags = 0;
+ flags |= base::PLATFORM_FILE_READ;
+ if (params.desired_flags & SQLITE_OPEN_READWRITE) {
+ flags |= base::PLATFORM_FILE_WRITE;
+ }
+
+ if (!(params.desired_flags & SQLITE_OPEN_MAIN_DB)) {
+ flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
+ base::PLATFORM_FILE_EXCLUSIVE_WRITE;
+ }
+
+ if (params.desired_flags & SQLITE_OPEN_CREATE) {
+ flags |= base::PLATFORM_FILE_OPEN_ALWAYS;
+ } else {
+ flags |= base::PLATFORM_FILE_OPEN;
+ }
+
+ if (params.desired_flags & SQLITE_OPEN_DELETEONCLOSE) {
+ flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN |
+ base::PLATFORM_FILE_DELETE_ON_CLOSE;
+ }
+
+ // Try to open/create the DB file.
+#if defined(OS_WIN)
+ base::PlatformFile file_handle =
+ base::CreatePlatformFile(params.file_name.value(), flags, NULL);
+ if (file_handle != base::kInvalidPlatformFileValue) {
+ // Duplicate the file handle.
+ if (!DuplicateHandle(GetCurrentProcess(), file_handle,
+ params.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;
+ }
+ }
+#endif
+ }
+
+ io_thread_message_loop->PostTask(FROM_HERE,
+ NewRunnableFunction(SendMessage, sender,
+ new ViewMsg_DatabaseOpenFileResponse(message_id, target_handle)));
+}
+
+// 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(
+ MessageLoop* io_thread_message_loop,
+ const FilePath& file_name,
+ int32 message_id,
+ int reschedule_count,
+ ResourceMessageFilter* sender) {
+ if (reschedule_count > 0 && file_util::PathExists(file_name) &&
+ !file_util::Delete(file_name, false)) {
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ NewRunnableFunction(DatabaseDeleteFile, io_thread_message_loop,
+ file_name, message_id, reschedule_count - 1, sender),
+ kDelayDeleteRetryMs);
+ } else {
+ io_thread_message_loop->PostTask(FROM_HERE,
+ NewRunnableFunction(SendMessage, sender,
+ new ViewMsg_DatabaseDeleteFileResponse(
+ message_id, reschedule_count > 0)));
+ }
+}
+
+// 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(
+ MessageLoop* io_thread_message_loop,
+ const FilePath& file_name,
+ int32 message_id,
+ ResourceMessageFilter* sender) {
+#if defined(OS_WIN)
+ uint32 attributes = GetFileAttributes(file_name.value().c_str());
+#else
+ uint32 attributes = -1L;
+#endif
+
+ io_thread_message_loop->PostTask(FROM_HERE,
+ NewRunnableFunction(SendMessage, sender,
+ new ViewMsg_DatabaseGetFileAttributesResponse(message_id, attributes)));
+}
+
+// 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(
+ MessageLoop* io_thread_message_loop,
+ const FilePath& file_name,
+ int32 message_id,
+ ResourceMessageFilter* sender) {
+ int64 size = 0;
+ if (!file_util::GetFileSize(file_name, &size)) {
+ size = 0;
+ }
+
+ io_thread_message_loop->PostTask(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),
+ file_thread_message_loop_(
+ g_browser_process->file_thread()->message_loop()) {
+}
+
+DatabaseDispatcherHost::~DatabaseDispatcherHost() {
+}
+
+bool DatabaseDispatcherHost::IsDBMessage(const IPC::Message& message) {
+ switch (message.type()) {
+ case ViewHostMsg_DatabaseOpenFile::ID:
+ case ViewHostMsg_DatabaseDeleteFile::ID:
+ case ViewHostMsg_DatabaseGetFileAttributes::ID:
+ case ViewHostMsg_DatabaseGetFileSize::ID:
+ return true;
+ }
+ return false;
+}
+
+bool DatabaseDispatcherHost::OnMessageReceived(
+ const IPC::Message& message, bool* message_was_ok) {
+ if (!IsDBMessage(message)) {
+ return false;
+ }
+ *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;
+}
+
+FilePath DatabaseDispatcherHost::GetDBDir() {
+ return profile_path_.Append(FILE_PATH_LITERAL("databases"));
+}
+
+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::OnDatabaseOpenFile(
+ const FilePath& file_name, int desired_flags,
+ int32 message_id) {
+ FilePath db_dir = GetDBDir();
+ FilePath db_file_name = GetDBFileFullPath(file_name);
+
+ if (db_file_name.empty()) {
+ resource_message_filter_->Send(new ViewMsg_DatabaseOpenFileResponse(
+ message_id, base::kInvalidPlatformFileValue));
+ return;
+ }
+
+ OpenFileParams params = { db_dir, db_file_name, desired_flags,
+ resource_message_filter_->handle() };
+ resource_message_filter_->AddRef();
+ file_thread_message_loop_->PostTask(FROM_HERE,
+ NewRunnableFunction(DatabaseOpenFile, MessageLoop::current(),
+ params, message_id, resource_message_filter_));
+}
+
+void DatabaseDispatcherHost::OnDatabaseDeleteFile(
+ 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_DatabaseDeleteFileResponse(
+ message_id, false));
+ return;
+ }
+
+ resource_message_filter_->AddRef();
+ file_thread_message_loop_->PostTask(FROM_HERE,
+ NewRunnableFunction(DatabaseDeleteFile, MessageLoop::current(),
+ db_file_name, message_id, kNumDeleteRetries, resource_message_filter_));
+}
+
+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));
+ return;
+ }
+
+ resource_message_filter_->AddRef();
+ file_thread_message_loop_->PostTask(FROM_HERE,
+ NewRunnableFunction(DatabaseGetFileAttributes, MessageLoop::current(),
+ db_file_name, message_id, resource_message_filter_));
+}
+
+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;
+ }
+
+ resource_message_filter_->AddRef();
+ file_thread_message_loop_->PostTask(FROM_HERE,
+ NewRunnableFunction(DatabaseGetFileSize, MessageLoop::current(),
+ db_file_name, message_id, resource_message_filter_));
+}
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.h b/chrome/browser/renderer_host/database_dispatcher_host.h
new file mode 100644
index 0000000..90dc00d
--- /dev/null
+++ b/chrome/browser/renderer_host/database_dispatcher_host.h
@@ -0,0 +1,59 @@
+// 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.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_DATABASE_DISPATCHER_HOST_H_
+#define CHROME_BROWSER_RENDERER_HOST_DATABASE_DISPATCHER_HOST_H_
+
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+
+class MessageLoop;
+class ResourceMessageFilter;
+
+namespace IPC {
+class Message;
+}
+
+class DatabaseDispatcherHost {
+ public:
+ DatabaseDispatcherHost(const FilePath& profile_path,
+ ResourceMessageFilter* resource_message_filter);
+ ~DatabaseDispatcherHost();
+
+ // Returns true iff the message is HTML5 DB related and was processed.
+ bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok);
+
+ // Processes the request to return a handle to the given DB file.
+ void OnDatabaseOpenFile(const FilePath& file_name,
+ int desired_flags, int32 message_id);
+ // Processes the request to delete the given DB file.
+ void OnDatabaseDeleteFile(const FilePath& file_name,
+ int32 message_id);
+ // Processes the request to return the attributes of the given DB file.
+ void OnDatabaseGetFileAttributes(const FilePath& file_name,
+ int32 message_id);
+ // Processes the request to return the size of the given file.
+ void OnDatabaseGetFileSize(const FilePath& file_name,
+ int32 message_id);
+
+ private:
+ // Determines if the message is HTML5 DB related.
+ bool IsDBMessage(const IPC::Message& message);
+
+ // Returns the directory where all DB files are stored.
+ FilePath GetDBDir();
+ // Returns the absolute name of the given DB file.
+ FilePath GetDBFileFullPath(const FilePath& file_name);
+
+ // The user data directory.
+ FilePath profile_path_;
+
+ // The ResourceMessageFilter instance of this renderer process.
+ ResourceMessageFilter* resource_message_filter_;
+
+ // The message loop of the file thread.
+ MessageLoop* file_thread_message_loop_;
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_DATABASE_DISPATCHER_HOST_H_
diff --git a/chrome/browser/renderer_host/render_sandbox_host_linux.cc b/chrome/browser/renderer_host/render_sandbox_host_linux.cc
index 31f6631..6b274f1 100644
--- a/chrome/browser/renderer_host/render_sandbox_host_linux.cc
+++ b/chrome/browser/renderer_host/render_sandbox_host_linux.cc
@@ -12,6 +12,7 @@
#include <time.h>
#include "base/eintr_wrapper.h"
+#include "base/platform_file.h"
#include "base/process_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
@@ -158,6 +159,20 @@ class SandboxIPCProcess : public WebKitClient {
virtual void callOnMainThread(void (*)()) { }
+ virtual base::PlatformFile databaseOpenFile(
+ const WebString& fileName, int desiredFlags) {
+ return base::kInvalidPlatformFileValue;
+ }
+ virtual bool databaseDeleteFile(const WebString& fileName) {
+ return false;
+ }
+ virtual long databaseGetFileAttributes(const WebString& fileName) {
+ return -1;
+ }
+ virtual long long databaseGetFileSize(const WebString& fileName) {
+ return 0;
+ }
+
private:
// ---------------------------------------------------------------------------
// Requests from the renderer...
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index f369191..ff376aa 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/privacy_blacklist/blacklist.h"
#include "chrome/browser/renderer_host/audio_renderer_host.h"
#include "chrome/browser/renderer_host/browser_render_process_host.h"
+#include "chrome/browser/renderer_host/database_dispatcher_host.h"
#include "chrome/browser/renderer_host/file_system_accessor.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/browser/spellchecker.h"
@@ -155,6 +156,8 @@ ResourceMessageFilter::ResourceMessageFilter(
ALLOW_THIS_IN_INITIALIZER_LIST(dom_storage_dispatcher_host_(
new DOMStorageDispatcherHost(this, profile->GetWebKitContext(),
resource_dispatcher_host->webkit_thread()))),
+ db_dispatcher_host_(
+ new DatabaseDispatcherHost(profile->GetPath(), this)),
off_the_record_(profile->IsOffTheRecord()) {
DCHECK(request_context_.get());
DCHECK(request_context_->cookie_store());
@@ -249,7 +252,9 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
message, &msg_is_ok) ||
dom_storage_dispatcher_host_->OnMessageReceived(
message, &msg_is_ok) ||
- audio_renderer_host_->OnMessageReceived(message, &msg_is_ok);
+ audio_renderer_host_->OnMessageReceived(
+ message, &msg_is_ok) ||
+ db_dispatcher_host_->OnMessageReceived(message, &msg_is_ok);
if (!handled) {
DCHECK(msg_is_ok); // It should have been marked handled if it wasn't OK.
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 379cfdb..ee92565 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -32,6 +32,7 @@
class AppCacheDispatcherHost;
class AudioRendererHost;
class Clipboard;
+class DatabaseDispatcherHost;
class DOMStorageDispatcherHost;
class ExtensionMessageService;
class Profile;
@@ -310,6 +311,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// Handles DOM Storage related messages.
scoped_refptr<DOMStorageDispatcherHost> dom_storage_dispatcher_host_;
+ // Handles HTML5 DB related messages
+ scoped_ptr<DatabaseDispatcherHost> db_dispatcher_host_;
+
// Whether this process is used for off the record tabs.
bool off_the_record_;