diff options
author | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-18 13:54:59 +0000 |
---|---|---|
committer | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-18 13:54:59 +0000 |
commit | 67a7851692243892bb2d7253d2f1974833e57432 (patch) | |
tree | 98bdc05f9af985cbcc8b9cc6ea0ccf472a85b588 | |
parent | e40cc399bd7e438579d6fcfa208103c12caf9052 (diff) | |
download | chromium_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.cc | 269 | ||||
-rw-r--r-- | chrome/browser/utility_process_host.cc | 34 | ||||
-rw-r--r-- | chrome/browser/utility_process_host.h | 37 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 1 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/indexed_db_param_traits.h | 102 | ||||
-rw-r--r-- | chrome/common/render_messages.cc | 83 | ||||
-rw-r--r-- | chrome/common/render_messages.h | 18 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 1 | ||||
-rw-r--r-- | chrome/common/utility_messages.h | 1 | ||||
-rw-r--r-- | chrome/common/utility_messages_internal.h | 25 | ||||
-rw-r--r-- | chrome/utility/utility_thread.cc | 63 | ||||
-rw-r--r-- | chrome/utility/utility_thread.h | 20 | ||||
-rw-r--r-- | webkit/glue/idb_bindings.cc | 69 | ||||
-rw-r--r-- | webkit/glue/idb_bindings.h | 25 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 2 |
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', |