summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-18 13:54:59 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-18 13:54:59 +0000
commit67a7851692243892bb2d7253d2f1974833e57432 (patch)
tree98bdc05f9af985cbcc8b9cc6ea0ccf472a85b588
parente40cc399bd7e438579d6fcfa208103c12caf9052 (diff)
downloadchromium_src-67a7851692243892bb2d7253d2f1974833e57432.zip
chromium_src-67a7851692243892bb2d7253d2f1974833e57432.tar.gz
chromium_src-67a7851692243892bb2d7253d2f1974833e57432.tar.bz2
Adds IDBKeyPath parser / extractor, and provides a mechanism to call it sandboxed.
TEST=idbkeypathextractor_browsertests.cc Review URL: http://codereview.chromium.org/3043037 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56524 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/idbbindingutilities_browsertest.cc269
-rw-r--r--chrome/browser/utility_process_host.cc34
-rw-r--r--chrome/browser/utility_process_host.h37
-rw-r--r--chrome/chrome_common.gypi1
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/indexed_db_param_traits.h102
-rw-r--r--chrome/common/render_messages.cc83
-rw-r--r--chrome/common/render_messages.h18
-rw-r--r--chrome/common/render_messages_internal.h1
-rw-r--r--chrome/common/utility_messages.h1
-rw-r--r--chrome/common/utility_messages_internal.h25
-rw-r--r--chrome/utility/utility_thread.cc63
-rw-r--r--chrome/utility/utility_thread.h20
-rw-r--r--webkit/glue/idb_bindings.cc69
-rw-r--r--webkit/glue/idb_bindings.h25
-rw-r--r--webkit/glue/webkit_glue.gypi2
16 files changed, 644 insertions, 107 deletions
diff --git a/chrome/browser/idbbindingutilities_browsertest.cc b/chrome/browser/idbbindingutilities_browsertest.cc
new file mode 100644
index 0000000..3172012
--- /dev/null
+++ b/chrome/browser/idbbindingutilities_browsertest.cc
@@ -0,0 +1,269 @@
+// 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 "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/browser/utility_process_host.h"
+#include "chrome/common/indexed_db_key.h"
+#include "chrome/common/serialized_script_value.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/idb_bindings.h"
+
+using WebKit::WebSerializedScriptValue;
+
+// Sanity test, check the function call directly outside the sandbox.
+TEST(IDBKeyPathWithoutSandbox, Value) {
+ char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
+ std::vector<WebSerializedScriptValue> serialized_values;
+ serialized_values.push_back(
+ WebSerializedScriptValue::fromString(string16(data, arraysize(data))));
+ serialized_values.push_back(
+ WebSerializedScriptValue::fromString(string16()));
+
+ std::vector<WebKit::WebIDBKey> values;
+ string16 key_path(UTF8ToUTF16("foo"));
+ bool error = webkit_glue::IDBKeysFromValuesAndKeyPath(
+ serialized_values, key_path, &values);
+
+ ASSERT_EQ(size_t(2), values.size());
+ ASSERT_EQ(WebKit::WebIDBKey::StringType, values[0].type());
+ ASSERT_EQ(UTF8ToUTF16("zoo"), values[0].string());
+ ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[1].type());
+ ASSERT_FALSE(error);
+
+ values.clear();
+ key_path = UTF8ToUTF16("PropertyNotAvailable");
+ error = webkit_glue::IDBKeysFromValuesAndKeyPath(
+ serialized_values, key_path, &values);
+
+ ASSERT_EQ(size_t(2), values.size());
+ ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[0].type());
+ ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[1].type());
+ ASSERT_FALSE(error);
+
+ values.clear();
+ key_path = UTF8ToUTF16("!+Invalid[KeyPath[[[");
+ error = webkit_glue::IDBKeysFromValuesAndKeyPath(
+ serialized_values, key_path, &values);
+
+ ASSERT_TRUE(error);
+ ASSERT_EQ(size_t(2), values.size());
+ ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[0].type());
+ ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[1].type());
+}
+
+class IDBKeyPathHelper : public UtilityProcessHost::Client {
+ public:
+ IDBKeyPathHelper()
+ : expected_id_(0),
+ utility_process_host_(NULL),
+ value_for_key_path_failed_(false) {
+ }
+
+ void CreateUtilityProcess(ResourceDispatcherHost* resource_dispatcher_host) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &IDBKeyPathHelper::CreateUtilityProcess,
+ resource_dispatcher_host));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ utility_process_host_ =
+ new UtilityProcessHost(resource_dispatcher_host, this,
+ ChromeThread::IO);
+ utility_process_host_->StartBatchMode();
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ new MessageLoop::QuitTask());
+ }
+
+ void DestroyUtilityProcess() {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &IDBKeyPathHelper::DestroyUtilityProcess));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ utility_process_host_->EndBatchMode();
+ utility_process_host_ = NULL;
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ new MessageLoop::QuitTask());
+ }
+
+ void SetExpected(int expected_id,
+ const std::vector<IndexedDBKey>& expected_values,
+ bool failed) {
+ expected_id_ = expected_id;
+ expected_values_ = expected_values;
+ value_for_key_path_failed_ = failed;
+ }
+
+ void CheckValuesForKeyPath(
+ int id, const std::vector<SerializedScriptValue>& serialized_values,
+ const string16& key_path) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &IDBKeyPathHelper::CheckValuesForKeyPath,
+ id, serialized_values, key_path));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ bool ret =
+ utility_process_host_->StartIDBKeysFromValuesAndKeyPath(
+ id, serialized_values, key_path);
+ ASSERT_TRUE(ret);
+ }
+
+ // UtilityProcessHost::Client
+ virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
+ int id, const std::vector<IndexedDBKey>& values) {
+ EXPECT_EQ(expected_id_, id);
+ EXPECT_FALSE(value_for_key_path_failed_);
+ ASSERT_EQ(expected_values_.size(), values.size());
+ size_t pos = 0;
+ for (std::vector<IndexedDBKey>::const_iterator i(values.begin());
+ i != values.end(); ++i, ++pos) {
+ ASSERT_EQ(expected_values_[pos].type(), i->type());
+ if (i->type() == WebKit::WebIDBKey::StringType) {
+ ASSERT_EQ(expected_values_[pos].string(), i->string());
+ } else if (i->type() == WebKit::WebIDBKey::NumberType) {
+ ASSERT_EQ(expected_values_[pos].number(), i->number());
+ }
+ }
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ new MessageLoop::QuitTask());
+ }
+
+ virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id) {
+ EXPECT_TRUE(value_for_key_path_failed_);
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ new MessageLoop::QuitTask());
+ }
+
+ private:
+ int expected_id_;
+ std::vector<IndexedDBKey> expected_values_;
+ UtilityProcessHost* utility_process_host_;
+ bool value_for_key_path_failed_;
+};
+
+// This test fixture runs in the UI thread. However, most of the work done by
+// UtilityProcessHost (and wrapped by IDBKeyPathHelper above) happens on the IO
+// thread. This fixture delegates to IDBKeyPathHelper and blocks via
+// "ui_test_utils::RunMessageLoop()", until IDBKeyPathHelper posts a quit
+// message the MessageLoop.
+class ScopedIDBKeyPathHelper {
+ public:
+ ScopedIDBKeyPathHelper() {
+ key_path_helper_ = new IDBKeyPathHelper();
+ key_path_helper_->CreateUtilityProcess(
+ g_browser_process->resource_dispatcher_host());
+ ui_test_utils::RunMessageLoop();
+ }
+
+ ~ScopedIDBKeyPathHelper() {
+ key_path_helper_->DestroyUtilityProcess();
+ ui_test_utils::RunMessageLoop();
+ }
+
+ void SetExpected(int id, const std::vector<IndexedDBKey>& expected_values,
+ bool failed) {
+ key_path_helper_->SetExpected(id, expected_values, failed);
+ }
+
+ void CheckValuesForKeyPath(
+ int id,
+ const std::vector<SerializedScriptValue>& serialized_script_values,
+ const string16& key_path) {
+ key_path_helper_->CheckValuesForKeyPath(id, serialized_script_values,
+ key_path);
+ ui_test_utils::RunMessageLoop();
+ }
+
+ private:
+ scoped_refptr<IDBKeyPathHelper> key_path_helper_;
+};
+
+IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, IDBKeyPathExtract) {
+ ScopedIDBKeyPathHelper scoped_helper;
+ const int kId = 7;
+ std::vector<IndexedDBKey> expected_values;
+ IndexedDBKey value;
+ value.Set(UTF8ToUTF16("zoo"));
+ expected_values.push_back(value);
+
+ IndexedDBKey invalid_value;
+ invalid_value.SetInvalid();
+ expected_values.push_back(invalid_value);
+
+ scoped_helper.SetExpected(kId, expected_values, false);
+
+ char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
+ std::vector<SerializedScriptValue> serialized_values;
+ serialized_values.push_back(
+ SerializedScriptValue(false, false, string16(data, arraysize(data))));
+ serialized_values.push_back(
+ SerializedScriptValue(true, false, string16()));
+ scoped_helper.CheckValuesForKeyPath(
+ kId, serialized_values, UTF8ToUTF16("foo"));
+}
+
+IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, IDBKeyPathPropertyNotAvailable) {
+ ScopedIDBKeyPathHelper scoped_helper;
+ const int kId = 7;
+ std::vector<IndexedDBKey> expected_values;
+ IndexedDBKey invalid_value;
+ invalid_value.SetInvalid();
+ expected_values.push_back(invalid_value);
+ expected_values.push_back(invalid_value);
+
+ scoped_helper.SetExpected(kId, expected_values, false);
+
+ char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
+ std::vector<SerializedScriptValue> serialized_values;
+ serialized_values.push_back(
+ SerializedScriptValue(false, false, string16(data, arraysize(data))));
+ serialized_values.push_back(
+ SerializedScriptValue(true, false, string16()));
+ scoped_helper.CheckValuesForKeyPath(kId, serialized_values,
+ UTF8ToUTF16("PropertyNotAvailable"));
+}
+
+IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, IDBKeyPathMultipleCalls) {
+ ScopedIDBKeyPathHelper scoped_helper;
+ const int kId = 7;
+ std::vector<IndexedDBKey> expected_values;
+ IndexedDBKey invalid_value;
+ invalid_value.SetInvalid();
+ expected_values.push_back(invalid_value);
+ expected_values.push_back(invalid_value);
+
+ scoped_helper.SetExpected(kId, expected_values, true);
+
+ char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
+ std::vector<SerializedScriptValue> serialized_values;
+ serialized_values.push_back(
+ SerializedScriptValue(false, false, string16(data, arraysize(data))));
+ serialized_values.push_back(
+ SerializedScriptValue(true, false, string16()));
+ scoped_helper.CheckValuesForKeyPath(kId, serialized_values,
+ UTF8ToUTF16("!+Invalid[KeyPath[[["));
+
+ // Call again with the Utility process in batch mode and with valid keys.
+ expected_values.clear();
+ IndexedDBKey value;
+ value.Set(UTF8ToUTF16("zoo"));
+ expected_values.push_back(value);
+ expected_values.push_back(invalid_value);
+ scoped_helper.SetExpected(kId + 1, expected_values, false);
+ scoped_helper.CheckValuesForKeyPath(kId + 1, serialized_values,
+ UTF8ToUTF16("foo"));
+}
diff --git a/chrome/browser/utility_process_host.cc b/chrome/browser/utility_process_host.cc
index e49df71..6014f22 100644
--- a/chrome/browser/utility_process_host.cc
+++ b/chrome/browser/utility_process_host.cc
@@ -18,10 +18,12 @@ UtilityProcessHost::UtilityProcessHost(ResourceDispatcherHost* rdh,
ChromeThread::ID client_thread_id)
: BrowserChildProcessHost(UTILITY_PROCESS, rdh),
client_(client),
- client_thread_id_(client_thread_id) {
+ client_thread_id_(client_thread_id),
+ is_batch_mode_(false) {
}
UtilityProcessHost::~UtilityProcessHost() {
+ DCHECK(!is_batch_mode_);
}
bool UtilityProcessHost::StartExtensionUnpacker(const FilePath& extension) {
@@ -59,11 +61,37 @@ bool UtilityProcessHost::StartImageDecoding(
return true;
}
+bool UtilityProcessHost::StartIDBKeysFromValuesAndKeyPath(
+ int id, const std::vector<SerializedScriptValue>& serialized_values,
+ const string16& key_path) {
+ if (!StartProcess(FilePath()))
+ return false;
+
+ Send(new UtilityMsg_IDBKeysFromValuesAndKeyPath(
+ id, serialized_values, key_path));
+ return true;
+}
+
+bool UtilityProcessHost::StartBatchMode() {
+ CHECK(!is_batch_mode_);
+ is_batch_mode_ = StartProcess(FilePath());
+ Send(new UtilityMsg_BatchMode_Started());
+ return is_batch_mode_;
+}
+
+void UtilityProcessHost::EndBatchMode() {
+ CHECK(is_batch_mode_);
+ is_batch_mode_ = false;
+ Send(new UtilityMsg_BatchMode_Finished());
+}
+
FilePath UtilityProcessHost::GetUtilityProcessCmd() {
return GetChildPath(true);
}
bool UtilityProcessHost::StartProcess(const FilePath& exposed_dir) {
+ if (is_batch_mode_)
+ return true;
// Name must be set or metrics_service will crash in any test which
// launches a UtilityProcessHost.
set_name(L"utility process");
@@ -159,5 +187,9 @@ void UtilityProcessHost::Client::OnMessageReceived(
Client::OnDecodeImageSucceeded)
IPC_MESSAGE_HANDLER(UtilityHostMsg_DecodeImage_Failed,
Client::OnDecodeImageFailed)
+ IPC_MESSAGE_HANDLER(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded,
+ Client::OnIDBKeysFromValuesAndKeyPathSucceeded)
+ IPC_MESSAGE_HANDLER(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Failed,
+ Client::OnIDBKeysFromValuesAndKeyPathFailed)
IPC_END_MESSAGE_MAP_EX()
}
diff --git a/chrome/browser/utility_process_host.h b/chrome/browser/utility_process_host.h
index 8dfee5e..8aadf35 100644
--- a/chrome/browser/utility_process_host.h
+++ b/chrome/browser/utility_process_host.h
@@ -18,11 +18,17 @@
#include "ipc/ipc_channel.h"
class DictionaryValue;
+class IndexedDBKey;
+class SerializedScriptValue;
class SkBitmap;
// This class acts as the browser-side host to a utility child process. A
// utility process is a short-lived sandboxed process that is created to run
// a specific task. This class lives solely on the IO thread.
+// If you need a single method call in the sandbox, use StartFooBar(p).
+// If you need multiple batches of work to be done in the sandboxed process,
+// use StartBatchMode(), then multiple calls to StartFooBar(p),
+// then finish with EndBatchMode().
class UtilityProcessHost : public BrowserChildProcessHost {
public:
// An interface to be implemented by consumers of the utility process to
@@ -72,6 +78,18 @@ class UtilityProcessHost : public BrowserChildProcessHost {
// Called when image data decoding failed.
virtual void OnDecodeImageFailed() {}
+ // Called when we have successfully obtained the IndexedDBKey after
+ // a call to StartIDBKeysFromValuesAndKeyPath.
+ // |id| is the corresponding identifier.
+ // |keys| the corresponding IndexedDBKey.
+ virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
+ int id, const std::vector<IndexedDBKey>& keys) {}
+
+ // Called when IDBKeyPath has failed.
+ // |id| is the corresponding identifier passed on
+ // StartIDBKeysFromValuesAndKeyPath.
+ virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id) {}
+
protected:
friend class base::RefCountedThreadSafe<Client>;
@@ -109,12 +127,26 @@ class UtilityProcessHost : public BrowserChildProcessHost {
// Start image decoding.
bool StartImageDecoding(const std::vector<unsigned char>& encoded_data);
+ // Starts extracting |key_path| from |serialized_values|, and replies with the
+ // corresponding IndexedDBKeys via OnIDBKeysFromValuesAndKeyPathSucceeded.
+ bool StartIDBKeysFromValuesAndKeyPath(
+ int id, const std::vector<SerializedScriptValue>& serialized_values,
+ const string16& key_path);
+
+ // Starts utility process in batch mode. Caller must call EndBatchMode()
+ // to finish the utility process.
+ bool StartBatchMode();
+
+ // Ends the utility process. Must be called after StartBatchMode().
+ void EndBatchMode();
+
protected:
// Allow these methods to be overridden for tests.
virtual FilePath GetUtilityProcessCmd();
private:
- // Starts a process. Returns true iff it succeeded.
+ // Starts a process if necessary. Returns true if it succeeded or a process
+ // has already been started via StartBatchMode().
bool StartProcess(const FilePath& exposed_dir);
// IPC messages:
@@ -132,6 +164,9 @@ class UtilityProcessHost : public BrowserChildProcessHost {
// A pointer to our client interface, who will be informed of progress.
scoped_refptr<Client> client_;
ChromeThread::ID client_thread_id_;
+ // True when running in batch mode, i.e., StartBatchMode() has been called
+ // and the utility process will run until EndBatchMode().
+ bool is_batch_mode_;
DISALLOW_COPY_AND_ASSIGN(UtilityProcessHost);
};
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 3c6eb5a..f2c3886 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -65,6 +65,7 @@
'common/gpu_video_common.h',
'common/indexed_db_key.cc',
'common/indexed_db_key.h',
+ 'common/indexed_param_traits.h',
'common/logging_chrome.cc',
'common/logging_chrome.h',
'common/main_function_params.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 93c1c7d..0df8ea7 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1630,6 +1630,7 @@
'browser/first_run/first_run_browsertest.cc',
'browser/geolocation/access_token_store_browsertest.cc',
'browser/geolocation/geolocation_browsertest.cc',
+ 'browser/idbbindingutilities_browsertest.cc',
'browser/gtk/view_id_util_browsertest.cc',
'browser/in_process_webkit/indexed_db_browsertest.cc',
'browser/net/cookie_policy_browsertest.cc',
diff --git a/chrome/common/indexed_db_param_traits.h b/chrome/common/indexed_db_param_traits.h
new file mode 100644
index 0000000..11d2050
--- /dev/null
+++ b/chrome/common/indexed_db_param_traits.h
@@ -0,0 +1,102 @@
+// 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 CHROME_COMMON_INDEXED_DB_PARAM_TRAITS_H_
+#define CHROME_COMMON_INDEXED_DB_PARAM_TRAITS_H_
+#pragma once
+
+#include "chrome/common/indexed_db_key.h"
+#include "chrome/common/serialized_script_value.h"
+
+namespace IPC {
+
+// These datatypes are used by utility_messages.h and render_messages.h.
+// Unfortunately we can't move it to common: MSVC linker complains about
+// WebKit datatypes that are not linked on npchrome_frame (even though it's
+// never actually used by that target).
+
+template <>
+struct ParamTraits<SerializedScriptValue> {
+ typedef SerializedScriptValue param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.is_null());
+ WriteParam(m, p.is_invalid());
+ WriteParam(m, p.data());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ bool is_null;
+ bool is_invalid;
+ string16 data;
+ bool ok =
+ ReadParam(m, iter, &is_null) &&
+ ReadParam(m, iter, &is_invalid) &&
+ ReadParam(m, iter, &data);
+ if (!ok)
+ return false;
+ r->set_is_null(is_null);
+ r->set_is_invalid(is_invalid);
+ r->set_data(data);
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<SerializedScriptValue>(");
+ LogParam(p.is_null(), l);
+ l->append(L", ");
+ LogParam(p.is_invalid(), l);
+ l->append(L", ");
+ LogParam(p.data(), l);
+ l->append(L")");
+ }
+};
+
+template <>
+struct ParamTraits<IndexedDBKey> {
+ typedef IndexedDBKey param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, int(p.type()));
+ // TODO(jorlow): Technically, we only need to pack the type being used.
+ WriteParam(m, p.string());
+ WriteParam(m, p.number());
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ int type;
+ string16 string;
+ int32 number;
+ bool ok =
+ ReadParam(m, iter, &type) &&
+ ReadParam(m, iter, &string) &&
+ ReadParam(m, iter, &number);
+ if (!ok)
+ return false;
+ switch (type) {
+ case WebKit::WebIDBKey::NullType:
+ r->SetNull();
+ return true;
+ case WebKit::WebIDBKey::StringType:
+ r->Set(string);
+ return true;
+ case WebKit::WebIDBKey::NumberType:
+ r->Set(number);
+ return true;
+ case WebKit::WebIDBKey::InvalidType:
+ r->SetInvalid();
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<IndexedDBKey>(");
+ LogParam(int(p.type()), l);
+ l->append(L", ");
+ LogParam(p.string(), l);
+ l->append(L", ");
+ LogParam(p.number(), l);
+ l->append(L")");
+ }
+};
+
+} // namespace IPC
+
+#endif // CHROME_COMMON_INDEXED_DB_PARAM_TRAITS_H_
diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc
index e3aec79..cb13959 100644
--- a/chrome/common/render_messages.cc
+++ b/chrome/common/render_messages.cc
@@ -8,8 +8,7 @@
#include "chrome/common/edit_command.h"
#include "chrome/common/extensions/extension_extent.h"
#include "chrome/common/extensions/url_pattern.h"
-#include "chrome/common/indexed_db_key.h"
-#include "chrome/common/serialized_script_value.h"
+#include "chrome/common/indexed_db_param_traits.h"
#include "chrome/common/thumbnail_score.h"
#include "gfx/rect.h"
#include "ipc/ipc_channel_handle.h"
@@ -377,86 +376,6 @@ void ParamTraits<scoped_refptr<net::HttpResponseHeaders> >::Log(
l->append(L"<HttpResponseHeaders>");
}
-void ParamTraits<SerializedScriptValue>::Write(Message* m, const param_type& p) {
- WriteParam(m, p.is_null());
- WriteParam(m, p.is_invalid());
- WriteParam(m, p.data());
-}
-
-bool ParamTraits<SerializedScriptValue>::Read(const Message* m, void** iter,
- param_type* r) {
- bool is_null;
- bool is_invalid;
- string16 data;
- bool ok =
- ReadParam(m, iter, &is_null) &&
- ReadParam(m, iter, &is_invalid) &&
- ReadParam(m, iter, &data);
- if (!ok)
- return false;
- r->set_is_null(is_null);
- r->set_is_invalid(is_invalid);
- r->set_data(data);
- return true;
-}
-
-void ParamTraits<SerializedScriptValue>::Log(const param_type& p,
- std::wstring* l) {
- l->append(L"<SerializedScriptValue>(");
- LogParam(p.is_null(), l);
- l->append(L", ");
- LogParam(p.is_invalid(), l);
- l->append(L", ");
- LogParam(p.data(), l);
- l->append(L")");
-}
-
-void ParamTraits<IndexedDBKey>::Write(Message* m, const param_type& p) {
- WriteParam(m, int(p.type()));
- // TODO(jorlow): Technically, we only need to pack the type being used.
- WriteParam(m, p.string());
- WriteParam(m, p.number());
-}
-
-bool ParamTraits<IndexedDBKey>::Read(const Message* m, void** iter,
- param_type* r) {
- int type;
- string16 string;
- int32 number;
- bool ok =
- ReadParam(m, iter, &type) &&
- ReadParam(m, iter, &string) &&
- ReadParam(m, iter, &number);
- if (!ok)
- return false;
- switch (type) {
- case WebKit::WebIDBKey::NullType:
- r->SetNull();
- return true;
- case WebKit::WebIDBKey::StringType:
- r->Set(string);
- return true;
- case WebKit::WebIDBKey::NumberType:
- r->Set(number);
- return true;
- case WebKit::WebIDBKey::InvalidType:
- r->SetInvalid();
- return true;
- }
- NOTREACHED();
- return false;
-}
-
-void ParamTraits<IndexedDBKey>::Log(const param_type& p, std::wstring* l) {
- l->append(L"<IndexedDBKey>(");
- LogParam(int(p.type()), l);
- l->append(L", ");
- LogParam(p.string(), l);
- l->append(L", ");
- LogParam(p.number(), l);
- l->append(L")");
-}
-
void ParamTraits<webkit_glue::FormData>::Write(Message* m,
const param_type& p) {
WriteParam(m, p.name);
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 2a516ed..9d082bc 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -23,7 +23,7 @@
#include "chrome/common/dom_storage_common.h"
#include "chrome/common/extensions/extension_extent.h" // used in struct
#include "chrome/common/font_descriptor_mac.h"
-#include "chrome/common/indexed_db_key.h" // used in struct
+#include "chrome/common/indexed_db_param_traits.h"
#include "chrome/common/navigation_gesture.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/common/renderer_preferences.h" // used in struct
@@ -75,8 +75,6 @@ struct WebAccessibility;
struct EditCommand;
class ExtensionExtent;
-class IndexedDBKey;
-class SerializedScriptValue;
class SkBitmap;
class URLPattern;
@@ -1497,21 +1495,7 @@ struct ParamTraits<SyncLoadResult> {
}
};
-template <>
-struct ParamTraits<SerializedScriptValue> {
- typedef SerializedScriptValue param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, void** iter, param_type* r);
- static void Log(const param_type& p, std::wstring* l);
-};
-template <>
-struct ParamTraits<IndexedDBKey> {
- typedef IndexedDBKey param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, void** iter, param_type* r);
- static void Log(const param_type& p, std::wstring* l);
-};
// Traits for FormData structure to pack/unpack.
template <>
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index ba858bf..fb9e939 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -41,6 +41,7 @@
// Substitution map for l10n messages.
typedef std::map<std::string, std::string> SubstitutionMap;
+class SerializedScriptValue;
class SkBitmap;
struct ThumbnailScore;
class WebCursor;
diff --git a/chrome/common/utility_messages.h b/chrome/common/utility_messages.h
index 03e0d0a..516081c 100644
--- a/chrome/common/utility_messages.h
+++ b/chrome/common/utility_messages.h
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "chrome/common/common_param_traits.h"
#include "chrome/common/extensions/update_manifest.h"
+#include "chrome/common/indexed_db_param_traits.h"
#include "ipc/ipc_message_utils.h"
namespace IPC {
diff --git a/chrome/common/utility_messages_internal.h b/chrome/common/utility_messages_internal.h
index 9231501..08dd347 100644
--- a/chrome/common/utility_messages_internal.h
+++ b/chrome/common/utility_messages_internal.h
@@ -48,6 +48,20 @@ IPC_BEGIN_MESSAGES(Utility)
gfx::Rect, // Render Area
int, // DPI
std::vector<printing::PageRange>)
+
+ // Tell the utility process to extract the given IDBKeyPath from the
+ // SerializedScriptValue vector and reply with the corresponding IDBKeys.
+ IPC_MESSAGE_CONTROL3(UtilityMsg_IDBKeysFromValuesAndKeyPath,
+ int, // id
+ std::vector<SerializedScriptValue>,
+ string16) // IDBKeyPath
+
+ // Tells the utility process that it's running in batch mode.
+ IPC_MESSAGE_CONTROL0(UtilityMsg_BatchMode_Started)
+
+ // Tells the utility process that it can shutdown.
+ IPC_MESSAGE_CONTROL0(UtilityMsg_BatchMode_Finished)
+
IPC_END_MESSAGES(Utility)
//------------------------------------------------------------------------------
@@ -111,4 +125,15 @@ IPC_BEGIN_MESSAGES(UtilityHost)
LOGFONT /* font data */)
#endif // defined(OS_WIN)
+ // Reply when the utility process has succeeded in obtaining the value for
+ // IDBKeyPath.
+ IPC_MESSAGE_CONTROL2(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded,
+ int /* id */,
+ std::vector<IndexedDBKey> /* value */)
+
+ // Reply when the utility process has failed in obtaining the value for
+ // IDBKeyPath.
+ IPC_MESSAGE_CONTROL1(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Failed,
+ int /* id */)
+
IPC_END_MESSAGES(UtilityHost)
diff --git a/chrome/utility/utility_thread.cc b/chrome/utility/utility_thread.cc
index 420df28..c759c0d 100644
--- a/chrome/utility/utility_thread.cc
+++ b/chrome/utility/utility_thread.cc
@@ -15,6 +15,7 @@
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_unpacker.h"
#include "chrome/common/extensions/update_manifest.h"
+#include "chrome/common/indexed_db_key.h"
#include "chrome/common/utility_messages.h"
#include "chrome/common/web_resource/web_resource_unpacker.h"
#include "gfx/rect.h"
@@ -22,10 +23,24 @@
#include "printing/page_range.h"
#include "printing/units.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "webkit/glue/idb_bindings.h"
#include "webkit/glue/image_decoder.h"
-UtilityThread::UtilityThread() {
+namespace {
+
+template<typename SRC, typename DEST>
+void ConvertVector(const SRC& src, DEST* dest) {
+ dest->reserve(src.size());
+ for (typename SRC::const_iterator i = src.begin(); i != src.end(); ++i)
+ dest->push_back(typename DEST::value_type(*i));
+}
+
+} // namespace
+
+
+UtilityThread::UtilityThread()
+ : batch_mode_(false) {
ChildProcess::current()->AddRefProcess();
}
@@ -40,6 +55,10 @@ void UtilityThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(UtilityMsg_DecodeImage, OnDecodeImage)
IPC_MESSAGE_HANDLER(UtilityMsg_RenderPDFPagesToMetafile,
OnRenderPDFPagesToMetafile)
+ IPC_MESSAGE_HANDLER(UtilityMsg_IDBKeysFromValuesAndKeyPath,
+ OnIDBKeysFromValuesAndKeyPath)
+ IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Started, OnBatchModeStarted)
+ IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Finished, OnBatchModeFinished)
IPC_END_MESSAGE_MAP()
}
@@ -53,7 +72,7 @@ void UtilityThread::OnUnpackExtension(const FilePath& extension_path) {
Send(new UtilityHostMsg_UnpackExtension_Failed(unpacker.error_message()));
}
- ChildProcess::current()->ReleaseProcess();
+ ReleaseProcessIfNeeded();
}
void UtilityThread::OnUnpackWebResource(const std::string& resource_data) {
@@ -69,7 +88,7 @@ void UtilityThread::OnUnpackWebResource(const std::string& resource_data) {
unpacker.error_message()));
}
- ChildProcess::current()->ReleaseProcess();
+ ReleaseProcessIfNeeded();
}
void UtilityThread::OnParseUpdateManifest(const std::string& xml) {
@@ -79,7 +98,7 @@ void UtilityThread::OnParseUpdateManifest(const std::string& xml) {
} else {
Send(new UtilityHostMsg_ParseUpdateManifest_Succeeded(manifest.results()));
}
- ChildProcess::current()->ReleaseProcess();
+ ReleaseProcessIfNeeded();
}
void UtilityThread::OnDecodeImage(
@@ -92,7 +111,7 @@ void UtilityThread::OnDecodeImage(
} else {
Send(new UtilityHostMsg_DecodeImage_Succeeded(decoded_image));
}
- ChildProcess::current()->ReleaseProcess();
+ ReleaseProcessIfNeeded();
}
@@ -116,7 +135,7 @@ void UtilityThread::OnRenderPDFPagesToMetafile(
if (!succeeded) {
Send(new UtilityHostMsg_RenderPDFPagesToMetafile_Failed());
}
- ChildProcess::current()->ReleaseProcess();
+ ReleaseProcessIfNeeded();
}
#if defined(OS_WIN)
@@ -253,3 +272,35 @@ bool UtilityThread::RenderPDFToWinMetafile(
return ret;
}
#endif // defined(OS_WIN)
+
+void UtilityThread::OnIDBKeysFromValuesAndKeyPath(
+ int id,
+ const std::vector<SerializedScriptValue>& serialized_script_values,
+ const string16& idb_key_path) {
+ std::vector<WebKit::WebSerializedScriptValue> web_values;
+ ConvertVector(serialized_script_values, &web_values);
+ std::vector<WebKit::WebIDBKey> web_keys;
+ bool error = webkit_glue::IDBKeysFromValuesAndKeyPath(
+ web_values, idb_key_path, &web_keys);
+ if (error) {
+ Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Failed(id));
+ return;
+ }
+ std::vector<IndexedDBKey> keys;
+ ConvertVector(web_keys, &keys);
+ Send(new UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded(id, keys));
+ ReleaseProcessIfNeeded();
+}
+
+void UtilityThread::OnBatchModeStarted() {
+ batch_mode_ = true;
+}
+
+void UtilityThread::OnBatchModeFinished() {
+ ChildProcess::current()->ReleaseProcess();
+}
+
+void UtilityThread::ReleaseProcessIfNeeded() {
+ if (!batch_mode_)
+ ChildProcess::current()->ReleaseProcess();
+}
diff --git a/chrome/utility/utility_thread.h b/chrome/utility/utility_thread.h
index 1f86cdc..a92c08b 100644
--- a/chrome/utility/utility_thread.h
+++ b/chrome/utility/utility_thread.h
@@ -14,6 +14,7 @@
#include "printing/native_metafile.h"
class GURL;
+class SerializedScriptValue;
class SkBitmap;
namespace gfx {
@@ -68,6 +69,25 @@ class UtilityThread : public ChildThread {
int* highest_rendered_page_number);
#endif // defined(OS_WIN)
+ // IPC for extracting IDBKeys from SerializedScriptValues, used by IndexedDB.
+ void OnIDBKeysFromValuesAndKeyPath(
+ int id,
+ const std::vector<SerializedScriptValue>& serialized_script_values,
+ const string16& idb_key_path);
+
+ // IPC to notify we'll be running in batch mode instead of quitting after
+ // any of the IPCs above, we'll only quit during OnBatchModeFinished().
+ void OnBatchModeStarted();
+
+ // IPC to notify batch mode has finished and we should now quit.
+ void OnBatchModeFinished();
+
+ // Releases the process if we are not (or no longer) in batch mode.
+ void ReleaseProcessIfNeeded();
+
+ // True when we're running in batch mode.
+ bool batch_mode_;
+
DISALLOW_COPY_AND_ASSIGN(UtilityThread);
};
diff --git a/webkit/glue/idb_bindings.cc b/webkit/glue/idb_bindings.cc
new file mode 100644
index 0000000..fd26130
--- /dev/null
+++ b/webkit/glue/idb_bindings.cc
@@ -0,0 +1,69 @@
+// 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/glue/idb_bindings.h"
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebIDBKey.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebIDBKeyPath.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "v8/include/v8.h"
+
+namespace webkit_glue {
+
+using WebKit::WebIDBKey;
+using WebKit::WebIDBKeyPath;
+using WebKit::WebSerializedScriptValue;
+
+namespace {
+
+class LocalContext {
+ public:
+ LocalContext()
+ : context_(v8::Context::New()) {
+ context_->Enter();
+ }
+
+ virtual ~LocalContext() {
+ context_->Exit();
+ context_.Dispose();
+ }
+
+ private:
+ v8::Locker lock_;
+ v8::HandleScope scope_;
+ v8::Persistent<v8::Context> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalContext);
+};
+
+} // namespace
+
+bool IDBKeysFromValuesAndKeyPath(
+ const std::vector<WebSerializedScriptValue>& serialized_script_values,
+ const string16& idb_key_path,
+ std::vector<WebIDBKey>* values) {
+ LocalContext env;
+ WebIDBKeyPath web_idb_key_path = WebIDBKeyPath::create(idb_key_path);
+ bool error = web_idb_key_path.parseError() != 0;
+ // TODO(bulach): what to do when we have a parse error? For now, setting
+ // all values back as invalid and returning a boolean.
+ for (std::vector<WebSerializedScriptValue>::const_iterator i =
+ serialized_script_values.begin();
+ i != serialized_script_values.end(); ++i) {
+ if (error) {
+ values->push_back(WebIDBKey::createInvalid());
+ } else {
+ values->push_back(
+ WebIDBKey::createFromValueAndKeyPath(*i, web_idb_key_path));
+ }
+ }
+ return error;
+}
+
+} // namespace webkit_glue
diff --git a/webkit/glue/idb_bindings.h b/webkit/glue/idb_bindings.h
new file mode 100644
index 0000000..074595d
--- /dev/null
+++ b/webkit/glue/idb_bindings.h
@@ -0,0 +1,25 @@
+// 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 <vector>
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+
+namespace WebKit {
+class WebIDBKey;
+class WebSerializedScriptValue;
+}
+
+namespace webkit_glue {
+
+// Warning: this method holds a V8 lock, it should only be called within a
+// sandbox.
+bool IDBKeysFromValuesAndKeyPath(
+ const std::vector<WebKit::WebSerializedScriptValue>&
+ serialized_script_values,
+ const string16& idb_key_path,
+ std::vector<WebKit::WebIDBKey>* values);
+
+} // namespace webkit_glue
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 035ed6d..02efafd 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -279,6 +279,8 @@
'ftp_directory_listing_response_delegate.h',
'glue_serialize.cc',
'glue_serialize.h',
+ 'idb_bindings.cc',
+ 'idb_bindings.h',
'image_decoder.cc',
'image_decoder.h',
'image_resource_fetcher.cc',