diff options
author | andreip@chromium.org <andreip@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-26 09:50:39 +0000 |
---|---|---|
committer | andreip@chromium.org <andreip@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-26 09:50:39 +0000 |
commit | 50114e88843a1d3e0b18e7c50943d170005ab4e4 (patch) | |
tree | 45dcf92f4dc9acc46fdb69b727350c50eb0d1c85 /chrome | |
parent | c4ba2a1ffa260fbdfdf91adc13c3b0cbd4b9af1f (diff) | |
download | chromium_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')
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; |