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..895b8f34dab8b811b969ae855c7ec56dfce6ebe6 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,150 @@ |
#include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h" |
-#include <vector> |
- |
+#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 the SerializedScriptValues |
jorlow1
2011/01/21 09:33:00
no the
hans
2011/01/21 11:27:55
Done.
|
+// 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>; |
+ |
jorlow1
2011/01/21 09:33:00
extra space?
hans
2011/01/21 11:27:55
Done.
|
+ ~KeyUtilityClientImpl(); |
+ |
jorlow1
2011/01/21 09:33:00
extra space
hans
2011/01/21 11:27:55
Done.
|
+ |
+ 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. |
+ |
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() { } |
jorlow1
2011/01/21 09:33:00
Assert we've been shutdown?
hans
2011/01/21 11:27:55
Done.
|
+ |
+IndexedDBKeyUtilityClient* IndexedDBKeyUtilityClient::GetInstance() { |
+ return Singleton<IndexedDBKeyUtilityClient>::get(); |
jorlow1
2011/01/21 09:33:00
What if we've been shutdown...should we allow this
hans
2011/01/21 11:27:55
Well, we need to somehow get to the instance to ch
jorlow1
2011/01/21 11:39:34
If the io thread is done, the transaction will be
|
+} |
+ |
+void IndexedDBKeyUtilityClient::Shutdown() { |
+ if (!impl_) |
+ return; |
+ |
+ is_shutdown_ = true; |
+ impl_->Shutdown(); |
+} |
+ |
+void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath( |
+ const std::vector<SerializedScriptValue>& values, |
+ const string16& key_path, |
+ std::vector<IndexedDBKey>* keys) { |
+ if (is_shutdown_) { |
+ keys->clear(); |
+ return; |
+ } |
+ |
+ if (!impl_) { |
+ impl_ = new KeyUtilityClientImpl(); |
+ impl_->StartUtilityProcess(); |
+ } |
+ |
+ return 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 +157,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 +177,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 +187,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 +204,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 +219,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 +236,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 +254,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(); |
} |