summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorandreip@chromium.org <andreip@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-26 09:50:39 +0000
committerandreip@chromium.org <andreip@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-26 09:50:39 +0000
commit50114e88843a1d3e0b18e7c50943d170005ab4e4 (patch)
tree45dcf92f4dc9acc46fdb69b727350c50eb0d1c85 /chrome
parentc4ba2a1ffa260fbdfdf91adc13c3b0cbd4b9af1f (diff)
downloadchromium_src-50114e88843a1d3e0b18e7c50943d170005ab4e4.zip
chromium_src-50114e88843a1d3e0b18e7c50943d170005ab4e4.tar.gz
chromium_src-50114e88843a1d3e0b18e7c50943d170005ab4e4.tar.bz2
Hooks IDBKeyPath with IDBObjectStorage::put.
This is a clone of Marcus' change: http://codereview.chromium.org/3120019/show I have also filed http://code.google.com/p/chromium/issues/detail?id=53317 about resolving Brett's concerns with the header dependencies introduced by 3120019 and 3043037. Review URL: http://codereview.chromium.org/3140029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57502 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/in_process_webkit/browser_webkitclient_impl.cc31
-rw-r--r--chrome/browser/in_process_webkit/browser_webkitclient_impl.h4
-rw-r--r--chrome/browser/in_process_webkit/indexed_db_browsertest.cc4
-rw-r--r--chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc148
-rw-r--r--chrome/browser/in_process_webkit/indexed_db_key_utility_client.h89
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/test/data/indexeddb/key_path_test.html10
-rw-r--r--chrome/test/data/indexeddb/key_path_test.js64
8 files changed, 352 insertions, 0 deletions
diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc
index f364bfd..6c190ea 100644
--- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc
+++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.cc
@@ -7,7 +7,11 @@
#include "base/file_util.h"
#include "base/logging.h"
#include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h"
+#include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h"
+#include "chrome/common/indexed_db_key.h"
+#include "chrome/common/serialized_script_value.h"
#include "third_party/WebKit/WebKit/chromium/public/WebData.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSerializedScriptValue.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
#include "webkit/glue/webkit_glue.h"
@@ -138,3 +142,30 @@ int BrowserWebKitClientImpl::databaseDeleteFile(
const FilePath path = webkit_glue::WebStringToFilePath(vfs_file_name);
return file_util::Delete(path, false) ? 0 : 1;
}
+
+void BrowserWebKitClientImpl::createIDBKeysFromSerializedValuesAndKeyPath(
+ const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values,
+ const WebKit::WebString& keyPath,
+ WebKit::WebVector<WebKit::WebIDBKey>& keys) {
+ // TODO(bulach): we need to figure out a way to keep the utility process
+ // running for longer, and shut it down when no longer used.
+ scoped_refptr<IndexedDBKeyUtilityClient> indexed_db_key_utility_client =
+ new IndexedDBKeyUtilityClient();
+ indexed_db_key_utility_client->StartUtilityProcess();
+
+ std::vector<SerializedScriptValue> std_values;
+ size_t size = values.size();
+ std_values.reserve(size);
+ for (size_t i = 0; i < size; ++i) {
+ SerializedScriptValue std_value(values[i]);
+ std_values.push_back(std_value);
+ }
+
+ std::vector<IndexedDBKey> std_keys;
+ indexed_db_key_utility_client->CreateIDBKeysFromSerializedValuesAndKeyPath(
+ std_values, keyPath, &std_keys);
+
+ indexed_db_key_utility_client->EndUtilityProcess();
+
+ keys = std_keys;
+}
diff --git a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h
index d65fbd6a..dd291c8 100644
--- a/chrome/browser/in_process_webkit/browser_webkitclient_impl.h
+++ b/chrome/browser/in_process_webkit/browser_webkitclient_impl.h
@@ -45,6 +45,10 @@ class BrowserWebKitClientImpl : public webkit_glue::WebKitClientImpl {
virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository();
virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name,
bool sync_dir);
+ virtual void createIDBKeysFromSerializedValuesAndKeyPath(
+ const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values,
+ const WebKit::WebString& keyPath,
+ WebKit::WebVector<WebKit::WebIDBKey>& keys);
private:
webkit_glue::WebFileUtilitiesImpl file_utilities_;
diff --git a/chrome/browser/in_process_webkit/indexed_db_browsertest.cc b/chrome/browser/in_process_webkit/indexed_db_browsertest.cc
index 12c381b..8785b80 100644
--- a/chrome/browser/in_process_webkit/indexed_db_browsertest.cc
+++ b/chrome/browser/in_process_webkit/indexed_db_browsertest.cc
@@ -59,3 +59,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) {
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, IndexTest) {
SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
}
+
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, KeyPathTest) {
+ SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
+}
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
new file mode 100644
index 0000000..b6a4eb8
--- /dev/null
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
@@ -0,0 +1,148 @@
+// 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/in_process_webkit/indexed_db_key_utility_client.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/indexed_db_key.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/serialized_script_value.h"
+
+IndexedDBKeyUtilityClient::IndexedDBKeyUtilityClient()
+ : waitable_event_(false, false),
+ state_(STATE_UNINITIALIZED),
+ utility_process_host_(NULL) {
+}
+
+IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() {
+ DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_SHUTDOWN);
+ DCHECK(!utility_process_host_);
+ DCHECK(!client_.get());
+}
+
+void IndexedDBKeyUtilityClient::StartUtilityProcess() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ DCHECK(state_ == STATE_UNINITIALIZED);
+
+ GetRDHAndStartUtilityProcess();
+ bool ret = waitable_event_.Wait();
+
+ DCHECK(ret && state_ == STATE_INITIALIZED);
+}
+
+void IndexedDBKeyUtilityClient::EndUtilityProcess() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ DCHECK(state_ == STATE_INITIALIZED);
+
+ EndUtilityProcessInternal();
+ bool ret = waitable_event_.Wait();
+
+ DCHECK(ret && state_ == STATE_SHUTDOWN);
+}
+
+void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath(
+ const std::vector<SerializedScriptValue>& values,
+ const string16& key_path,
+ std::vector<IndexedDBKey>* keys) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::WEBKIT));
+ DCHECK(state_ == STATE_INITIALIZED);
+
+ state_ = STATE_CREATING_KEYS;
+ utility_process_host_->StartIDBKeysFromValuesAndKeyPath(
+ 0, values, key_path);
+ bool ret = waitable_event_.Wait();
+ DCHECK(ret && state_ == STATE_INITIALIZED);
+
+ *keys = keys_;
+}
+
+void IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess() {
+ // In order to start the UtilityProcess, we need to grab
+ // a pointer to the ResourceDispatcherHost. This can only
+ // be done on the UI thread. See the comment at the top of
+ // browser_process.h
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ StartUtilityProcessInternal(g_browser_process->resource_dispatcher_host());
+}
+
+void IndexedDBKeyUtilityClient::StartUtilityProcessInternal(
+ ResourceDispatcherHost* rdh) {
+ DCHECK(rdh);
+ // The ResourceDispatcherHost can only be used on the IO thread.
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &IndexedDBKeyUtilityClient::StartUtilityProcessInternal,
+ rdh));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ DCHECK(state_ == STATE_UNINITIALIZED);
+
+ client_ = new IndexedDBKeyUtilityClient::Client(this);
+ utility_process_host_ = new UtilityProcessHost(
+ rdh, client_.get(), ChromeThread::IO);
+ utility_process_host_->StartBatchMode();
+ state_ = STATE_INITIALIZED;
+ waitable_event_.Signal();
+}
+
+void IndexedDBKeyUtilityClient::EndUtilityProcessInternal() {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &IndexedDBKeyUtilityClient::EndUtilityProcessInternal));
+ return;
+ }
+
+ utility_process_host_->EndBatchMode();
+ utility_process_host_ = NULL;
+ client_ = NULL;
+ state_ = STATE_SHUTDOWN;
+ waitable_event_.Signal();
+}
+
+void IndexedDBKeyUtilityClient::SetKeys(const std::vector<IndexedDBKey>& keys) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ keys_ = keys;
+}
+
+void IndexedDBKeyUtilityClient::FinishCreatingKeys() {
+ DCHECK(state_ == STATE_CREATING_KEYS);
+ state_ = STATE_INITIALIZED;
+ waitable_event_.Signal();
+}
+
+IndexedDBKeyUtilityClient::Client::Client(IndexedDBKeyUtilityClient* parent)
+ : parent_(parent) {
+}
+
+void IndexedDBKeyUtilityClient::Client::OnProcessCrashed() {
+ if (parent_->state_ == STATE_CREATING_KEYS)
+ parent_->FinishCreatingKeys();
+}
+
+void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathSucceeded(
+ int id, const std::vector<IndexedDBKey>& keys) {
+ parent_->SetKeys(keys);
+ parent_->FinishCreatingKeys();
+}
+
+void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathFailed(
+ int id) {
+ parent_->FinishCreatingKeys();
+}
diff --git a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
new file mode 100644
index 0000000..d2a74ff
--- /dev/null
+++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.h
@@ -0,0 +1,89 @@
+// 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_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_KEY_UTILITY_CLIENT_H_
+#define CHROME_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_KEY_UTILITY_CLIENT_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "base/waitable_event.h"
+#include "chrome/browser/utility_process_host.h"
+
+class IndexedDBKey;
+class SerializedScriptValue;
+
+// This class is responsible to obtain IndexedDBKeys from the
+// SerializedScriptValues given an IDBKeyPath. It uses UtilityProcess to do this
+// inside a sandbox (a V8 lock is required there). At this level, all methods
+// are synchronous as required by the caller. The public API is used on
+// WEBKIT thread, but internally it moves around to UI and IO as needed.
+class IndexedDBKeyUtilityClient
+ : public base::RefCountedThreadSafe<IndexedDBKeyUtilityClient> {
+ public:
+ IndexedDBKeyUtilityClient();
+
+ // Starts the UtilityProcess. Must be called before any other method.
+ void StartUtilityProcess();
+
+ // Ends the UtilityProcess. Must be called after StartUtilityProcess() and
+ // before destruction.
+ // TODO(bulach): figure out an appropriate hook so that we can keep the
+ // UtilityProcess running for a longer period of time and avoid spinning it
+ // on every IDBObjectStore::Put call.
+ void EndUtilityProcess();
+
+ // Synchronously obtain the |keys| from |values| for the given |key_path|.
+ void CreateIDBKeysFromSerializedValuesAndKeyPath(
+ const std::vector<SerializedScriptValue>& values,
+ const string16& key_path,
+ std::vector<IndexedDBKey>* keys);
+
+ private:
+ class Client : public UtilityProcessHost::Client {
+ public:
+ explicit Client(IndexedDBKeyUtilityClient* parent);
+
+ // UtilityProcessHost::Client
+ virtual void OnProcessCrashed();
+ virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
+ int id, const std::vector<IndexedDBKey>& keys);
+ virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id);
+
+ private:
+ IndexedDBKeyUtilityClient* parent_;
+
+ DISALLOW_COPY_AND_ASSIGN(Client);
+ };
+
+ friend class base::RefCountedThreadSafe<IndexedDBKeyUtilityClient>;
+ ~IndexedDBKeyUtilityClient();
+
+ void GetRDHAndStartUtilityProcess();
+ void StartUtilityProcessInternal(ResourceDispatcherHost* rdh);
+ void EndUtilityProcessInternal();
+
+ void SetKeys(const std::vector<IndexedDBKey>& keys);
+ void FinishCreatingKeys();
+
+ base::WaitableEvent waitable_event_;
+
+ // Used in both IO and WEBKIT threads, but guarded by WaitableEvent, i.e.,
+ // these members are only set / read when the other thread is blocked.
+ enum State {
+ STATE_UNINITIALIZED,
+ STATE_INITIALIZED,
+ STATE_CREATING_KEYS,
+ STATE_SHUTDOWN,
+ };
+ State state_;
+ std::vector<IndexedDBKey> keys_;
+
+ // Used in the IO thread.
+ UtilityProcessHost* utility_process_host_;
+ scoped_refptr<Client> client_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyUtilityClient);
+};
+
+#endif // CHROME_BROWSER_IN_PROCESS_WEBKIT_INDEXED_DB_KEY_UTILITY_CLIENT_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 20410de..5f84a90 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1934,6 +1934,8 @@
'browser/in_process_webkit/indexed_db_context.h',
'browser/in_process_webkit/indexed_db_dispatcher_host.cc',
'browser/in_process_webkit/indexed_db_dispatcher_host.h',
+ 'browser/in_process_webkit/indexed_db_key_utility_client.cc',
+ 'browser/in_process_webkit/indexed_db_key_utility_client.h',
'browser/in_process_webkit/webkit_context.cc',
'browser/in_process_webkit/webkit_context.h',
'browser/in_process_webkit/webkit_thread.cc',
diff --git a/chrome/test/data/indexeddb/key_path_test.html b/chrome/test/data/indexeddb/key_path_test.html
new file mode 100644
index 0000000..6c03e3f
--- /dev/null
+++ b/chrome/test/data/indexeddb/key_path_test.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <title>IndexedDB cursor test</title>
+ <script type="text/javascript" src="common.js"></script>
+ <script type="text/javascript" src="key_path_test.js"></script>
+ </head>
+ <body onLoad="test()">
+ <div id="status">Starting...</div>
+ </body>
+</html>
diff --git a/chrome/test/data/indexeddb/key_path_test.js b/chrome/test/data/indexeddb/key_path_test.js
new file mode 100644
index 0000000..2a328fa
--- /dev/null
+++ b/chrome/test/data/indexeddb/key_path_test.js
@@ -0,0 +1,64 @@
+debug("Test IndexedDB's KeyPath.");
+
+function cursorSuccess()
+{
+ debug("Cursor opened successfully.")
+ // FIXME: check that we can iterate the cursor.
+ shouldBe("event.result.direction", "0");
+ shouldBe("event.result.key", "'myKey' + count");
+ shouldBe("event.result.value.keyPath", "'myKey' + count");
+ shouldBe("event.result.value.value", "'myValue' + count");
+ if (++count >= 5)
+ done();
+ else
+ openCursor();
+}
+
+function openCursor()
+{
+ debug("Opening cursor #" + count);
+ keyRange = IDBKeyRange.leftBound("myKey" + count);
+ result = objectStore.openCursor(keyRange);
+ result.onsuccess = cursorSuccess;
+ result.onerror = unexpectedErrorCallback;
+}
+
+function populateObjectStore()
+{
+ debug("Populating object store #" + count);
+ obj = {'keyPath': 'myKey' + count, 'value': 'myValue' + count};
+ result = objectStore.add(obj);
+ result.onerror = unexpectedErrorCallback;
+ if (++count >= 5) {
+ count = 0;
+ result.onsuccess = openCursor;
+ } else {
+ result.onsuccess = populateObjectStore;
+ }
+}
+
+function createObjectStoreSuccess()
+{
+ objectStore = event.result;
+ count = 0;
+ populateObjectStore();
+}
+
+function openSuccess()
+{
+ debug("Creating object store");
+ var db = event.result;
+ result = db.createObjectStore('test', 'keyPath');
+ result.onsuccess = createObjectStoreSuccess;
+ result.onerror = unexpectedErrorCallback;
+}
+
+function test()
+{
+ debug("Opening IndexedDB");
+ result = indexedDB.open('name', 'description');
+ result.onsuccess = openSuccess;
+ result.onerror = unexpectedErrorCallback;
+}
+
+var successfullyParsed = true;