| Index: chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
|
| 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
|
| index f708b43dbf0a670e034299b422838af32ac75437..e70b2a3cbad6403c76f159e24a9197a1cba3319c 100644
|
| --- a/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
|
| +++ b/chrome/browser/in_process_webkit/indexed_db_key_utility_client.cc
|
| @@ -4,25 +4,155 @@
|
|
|
| #include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h"
|
|
|
| -#include <vector>
|
| -
|
| +#include "base/lazy_instance.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| #include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/utility_process_host.h"
|
| #include "chrome/common/indexed_db_key.h"
|
| #include "chrome/common/serialized_script_value.h"
|
|
|
| +// This class is used to obtain IndexedDBKeys from 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 KeyUtilityClientImpl
|
| + : public base::RefCountedThreadSafe<KeyUtilityClientImpl> {
|
| + public:
|
| + KeyUtilityClientImpl();
|
| +
|
| + // Starts the UtilityProcess. Must be called before any other method.
|
| + void StartUtilityProcess();
|
| +
|
| + // Stops the UtilityProcess. No further keys can be created after this.
|
| + void Shutdown();
|
| +
|
| + // 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(KeyUtilityClientImpl* parent);
|
| +
|
| + // UtilityProcessHost::Client
|
| + virtual void OnProcessCrashed(int exit_code);
|
| + virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
|
| + int id, const std::vector<IndexedDBKey>& keys);
|
| + virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id);
|
| +
|
| + private:
|
| + KeyUtilityClientImpl* parent_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Client);
|
| + };
|
| +
|
| + friend class base::RefCountedThreadSafe<KeyUtilityClientImpl>;
|
| + ~KeyUtilityClientImpl();
|
| +
|
| + void GetRDHAndStartUtilityProcess();
|
| + void StartUtilityProcessInternal(ResourceDispatcherHost* rdh);
|
| + void EndUtilityProcessInternal();
|
| + void CallStartIDBKeyFromValueAndKeyPathFromIOThread(
|
| + const std::vector<SerializedScriptValue>& values,
|
| + const string16& key_path);
|
| +
|
| + 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(KeyUtilityClientImpl);
|
| +};
|
| +
|
| +// IndexedDBKeyUtilityClient definitions.
|
| +
|
| +static base::LazyInstance<IndexedDBKeyUtilityClient> client_instance(
|
| + base::LINKER_INITIALIZED);
|
| +
|
| IndexedDBKeyUtilityClient::IndexedDBKeyUtilityClient()
|
| + : is_shutdown_(false) {
|
| + // Note that creating the impl_ object is deferred until it is first needed,
|
| + // as this class can be constructed even though it never gets used.
|
| +}
|
| +
|
| +IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() {
|
| + DCHECK(!impl_ || is_shutdown_);
|
| +}
|
| +
|
| +// static
|
| +void IndexedDBKeyUtilityClient::Shutdown() {
|
| + IndexedDBKeyUtilityClient* instance = client_instance.Pointer();
|
| + if (!instance->impl_)
|
| + return;
|
| +
|
| + instance->is_shutdown_ = true;
|
| + instance->impl_->Shutdown();
|
| +}
|
| +
|
| +// static
|
| +void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath(
|
| + const std::vector<SerializedScriptValue>& values,
|
| + const string16& key_path,
|
| + std::vector<IndexedDBKey>* keys) {
|
| + IndexedDBKeyUtilityClient* instance = client_instance.Pointer();
|
| +
|
| + if (instance->is_shutdown_) {
|
| + keys->clear();
|
| + return;
|
| + }
|
| +
|
| + if (!instance->impl_) {
|
| + instance->impl_ = new KeyUtilityClientImpl();
|
| + instance->impl_->StartUtilityProcess();
|
| + }
|
| +
|
| + instance->impl_->CreateIDBKeysFromSerializedValuesAndKeyPath(values, key_path,
|
| + keys);
|
| +}
|
| +
|
| +// KeyUtilityClientImpl definitions.
|
| +
|
| +void KeyUtilityClientImpl::Shutdown() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + utility_process_host_->EndBatchMode();
|
| + utility_process_host_ = NULL;
|
| + client_ = NULL;
|
| + state_ = STATE_SHUTDOWN;
|
| +}
|
| +
|
| +KeyUtilityClientImpl::KeyUtilityClientImpl()
|
| : waitable_event_(false, false),
|
| state_(STATE_UNINITIALIZED),
|
| utility_process_host_(NULL) {
|
| }
|
|
|
| -IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() {
|
| +KeyUtilityClientImpl::~KeyUtilityClientImpl() {
|
| DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_SHUTDOWN);
|
| DCHECK(!utility_process_host_);
|
| DCHECK(!client_.get());
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::StartUtilityProcess() {
|
| +void KeyUtilityClientImpl::StartUtilityProcess() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
|
| DCHECK(state_ == STATE_UNINITIALIZED);
|
|
|
| @@ -32,21 +162,16 @@ void IndexedDBKeyUtilityClient::StartUtilityProcess() {
|
| DCHECK(ret && state_ == STATE_INITIALIZED);
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::EndUtilityProcess() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
|
| - DCHECK(state_ == STATE_INITIALIZED);
|
| -
|
| - EndUtilityProcessInternal();
|
| - bool ret = waitable_event_.Wait();
|
| -
|
| - DCHECK(ret && state_ == STATE_SHUTDOWN);
|
| -}
|
| -
|
| -void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath(
|
| +void KeyUtilityClientImpl::CreateIDBKeysFromSerializedValuesAndKeyPath(
|
| const std::vector<SerializedScriptValue>& values,
|
| const string16& key_path,
|
| std::vector<IndexedDBKey>* keys) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
|
| + if (state_ == STATE_SHUTDOWN) {
|
| + keys->clear();
|
| + return;
|
| + }
|
| +
|
| DCHECK(state_ == STATE_INITIALIZED);
|
|
|
| state_ = STATE_CREATING_KEYS;
|
| @@ -57,7 +182,7 @@ void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath(
|
| *keys = keys_;
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess() {
|
| +void KeyUtilityClientImpl::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
|
| @@ -67,14 +192,14 @@ void IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess() {
|
| BrowserThread::UI, FROM_HERE,
|
| NewRunnableMethod(
|
| this,
|
| - &IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess));
|
| + &KeyUtilityClientImpl::GetRDHAndStartUtilityProcess));
|
| return;
|
| }
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| StartUtilityProcessInternal(g_browser_process->resource_dispatcher_host());
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::StartUtilityProcessInternal(
|
| +void KeyUtilityClientImpl::StartUtilityProcessInternal(
|
| ResourceDispatcherHost* rdh) {
|
| DCHECK(rdh);
|
| // The ResourceDispatcherHost can only be used on the IO thread.
|
| @@ -84,14 +209,14 @@ void IndexedDBKeyUtilityClient::StartUtilityProcessInternal(
|
| BrowserThread::IO, FROM_HERE,
|
| NewRunnableMethod(
|
| this,
|
| - &IndexedDBKeyUtilityClient::StartUtilityProcessInternal,
|
| + &KeyUtilityClientImpl::StartUtilityProcessInternal,
|
| rdh));
|
| return;
|
| }
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| DCHECK(state_ == STATE_UNINITIALIZED);
|
|
|
| - client_ = new IndexedDBKeyUtilityClient::Client(this);
|
| + client_ = new KeyUtilityClientImpl::Client(this);
|
| utility_process_host_ = new UtilityProcessHost(
|
| rdh, client_.get(), BrowserThread::IO);
|
| utility_process_host_->StartBatchMode();
|
| @@ -99,13 +224,13 @@ void IndexedDBKeyUtilityClient::StartUtilityProcessInternal(
|
| waitable_event_.Signal();
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::EndUtilityProcessInternal() {
|
| +void KeyUtilityClientImpl::EndUtilityProcessInternal() {
|
| if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| NewRunnableMethod(
|
| this,
|
| - &IndexedDBKeyUtilityClient::EndUtilityProcessInternal));
|
| + &KeyUtilityClientImpl::EndUtilityProcessInternal));
|
| return;
|
| }
|
|
|
| @@ -116,14 +241,14 @@ void IndexedDBKeyUtilityClient::EndUtilityProcessInternal() {
|
| waitable_event_.Signal();
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::CallStartIDBKeyFromValueAndKeyPathFromIOThread(
|
| +void KeyUtilityClientImpl::CallStartIDBKeyFromValueAndKeyPathFromIOThread(
|
| const std::vector<SerializedScriptValue>& values,
|
| const string16& key_path) {
|
| if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| NewRunnableMethod(this,
|
| - &IndexedDBKeyUtilityClient::
|
| + &KeyUtilityClientImpl::
|
| CallStartIDBKeyFromValueAndKeyPathFromIOThread,
|
| values, key_path));
|
| return;
|
| @@ -134,33 +259,33 @@ void IndexedDBKeyUtilityClient::CallStartIDBKeyFromValueAndKeyPathFromIOThread(
|
| 0, values, key_path);
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::SetKeys(const std::vector<IndexedDBKey>& keys) {
|
| +void KeyUtilityClientImpl::SetKeys(const std::vector<IndexedDBKey>& keys) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| keys_ = keys;
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::FinishCreatingKeys() {
|
| +void KeyUtilityClientImpl::FinishCreatingKeys() {
|
| DCHECK(state_ == STATE_CREATING_KEYS);
|
| state_ = STATE_INITIALIZED;
|
| waitable_event_.Signal();
|
| }
|
|
|
| -IndexedDBKeyUtilityClient::Client::Client(IndexedDBKeyUtilityClient* parent)
|
| +KeyUtilityClientImpl::Client::Client(KeyUtilityClientImpl* parent)
|
| : parent_(parent) {
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::Client::OnProcessCrashed(int exit_code) {
|
| +void KeyUtilityClientImpl::Client::OnProcessCrashed(int exit_code) {
|
| if (parent_->state_ == STATE_CREATING_KEYS)
|
| parent_->FinishCreatingKeys();
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathSucceeded(
|
| +void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathSucceeded(
|
| int id, const std::vector<IndexedDBKey>& keys) {
|
| parent_->SetKeys(keys);
|
| parent_->FinishCreatingKeys();
|
| }
|
|
|
| -void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathFailed(
|
| +void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathFailed(
|
| int id) {
|
| parent_->FinishCreatingKeys();
|
| }
|
|
|