Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h" | 5 #include "chrome/browser/in_process_webkit/indexed_db_key_utility_client.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include "base/synchronization/waitable_event.h" |
| 8 | |
| 9 #include "chrome/browser/browser_process.h" | 8 #include "chrome/browser/browser_process.h" |
| 9 #include "chrome/browser/utility_process_host.h" | |
| 10 #include "chrome/common/indexed_db_key.h" | 10 #include "chrome/common/indexed_db_key.h" |
| 11 #include "chrome/common/serialized_script_value.h" | 11 #include "chrome/common/serialized_script_value.h" |
| 12 | 12 |
| 13 // 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.
| |
| 14 // given an IDBKeyPath. It uses UtilityProcess to do this inside a sandbox | |
| 15 // (a V8 lock is required there). At this level, all methods are synchronous | |
| 16 // as required by the caller. The public API is used on WEBKIT thread, | |
| 17 // but internally it moves around to UI and IO as needed. | |
| 18 class KeyUtilityClientImpl | |
| 19 : public base::RefCountedThreadSafe<KeyUtilityClientImpl> { | |
| 20 public: | |
| 21 KeyUtilityClientImpl(); | |
| 22 | |
| 23 // Starts the UtilityProcess. Must be called before any other method. | |
| 24 void StartUtilityProcess(); | |
| 25 | |
| 26 // Stops the UtilityProcess. No further keys can be created after this. | |
| 27 void Shutdown(); | |
| 28 | |
| 29 // Synchronously obtain the |keys| from |values| for the given |key_path|. | |
| 30 void CreateIDBKeysFromSerializedValuesAndKeyPath( | |
| 31 const std::vector<SerializedScriptValue>& values, | |
| 32 const string16& key_path, | |
| 33 std::vector<IndexedDBKey>* keys); | |
| 34 | |
| 35 private: | |
| 36 class Client : public UtilityProcessHost::Client { | |
| 37 public: | |
| 38 explicit Client(KeyUtilityClientImpl* parent); | |
| 39 | |
| 40 // UtilityProcessHost::Client | |
| 41 virtual void OnProcessCrashed(int exit_code); | |
| 42 virtual void OnIDBKeysFromValuesAndKeyPathSucceeded( | |
| 43 int id, const std::vector<IndexedDBKey>& keys); | |
| 44 virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id); | |
| 45 | |
| 46 private: | |
| 47 KeyUtilityClientImpl* parent_; | |
| 48 | |
| 49 DISALLOW_COPY_AND_ASSIGN(Client); | |
| 50 }; | |
| 51 | |
| 52 friend class base::RefCountedThreadSafe<KeyUtilityClientImpl>; | |
| 53 | |
|
jorlow1
2011/01/21 09:33:00
extra space?
hans
2011/01/21 11:27:55
Done.
| |
| 54 ~KeyUtilityClientImpl(); | |
| 55 | |
|
jorlow1
2011/01/21 09:33:00
extra space
hans
2011/01/21 11:27:55
Done.
| |
| 56 | |
| 57 void GetRDHAndStartUtilityProcess(); | |
| 58 void StartUtilityProcessInternal(ResourceDispatcherHost* rdh); | |
| 59 void EndUtilityProcessInternal(); | |
| 60 void CallStartIDBKeyFromValueAndKeyPathFromIOThread( | |
| 61 const std::vector<SerializedScriptValue>& values, | |
| 62 const string16& key_path); | |
| 63 | |
| 64 void SetKeys(const std::vector<IndexedDBKey>& keys); | |
| 65 void FinishCreatingKeys(); | |
| 66 | |
| 67 base::WaitableEvent waitable_event_; | |
| 68 | |
| 69 // Used in both IO and WEBKIT threads, but guarded by WaitableEvent, i.e., | |
| 70 // these members are only set / read when the other thread is blocked. | |
| 71 enum State { | |
| 72 STATE_UNINITIALIZED, | |
| 73 STATE_INITIALIZED, | |
| 74 STATE_CREATING_KEYS, | |
| 75 STATE_SHUTDOWN, | |
| 76 }; | |
| 77 State state_; | |
| 78 std::vector<IndexedDBKey> keys_; | |
| 79 | |
| 80 // Used in the IO thread. | |
| 81 UtilityProcessHost* utility_process_host_; | |
| 82 scoped_refptr<Client> client_; | |
| 83 | |
| 84 DISALLOW_COPY_AND_ASSIGN(KeyUtilityClientImpl); | |
| 85 }; | |
| 86 | |
| 87 // IndexedDBKeyUtilityClient definitions. | |
| 88 | |
| 13 IndexedDBKeyUtilityClient::IndexedDBKeyUtilityClient() | 89 IndexedDBKeyUtilityClient::IndexedDBKeyUtilityClient() |
| 90 : is_shutdown_(false) { | |
| 91 // Note that creating the impl_ object is deferred until it is first needed, | |
| 92 // as this class can be constructed even though it never gets used. | |
| 93 } | |
| 94 | |
| 95 IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() { } | |
|
jorlow1
2011/01/21 09:33:00
Assert we've been shutdown?
hans
2011/01/21 11:27:55
Done.
| |
| 96 | |
| 97 IndexedDBKeyUtilityClient* IndexedDBKeyUtilityClient::GetInstance() { | |
| 98 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
| |
| 99 } | |
| 100 | |
| 101 void IndexedDBKeyUtilityClient::Shutdown() { | |
| 102 if (!impl_) | |
| 103 return; | |
| 104 | |
| 105 is_shutdown_ = true; | |
| 106 impl_->Shutdown(); | |
| 107 } | |
| 108 | |
| 109 void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath( | |
| 110 const std::vector<SerializedScriptValue>& values, | |
| 111 const string16& key_path, | |
| 112 std::vector<IndexedDBKey>* keys) { | |
| 113 if (is_shutdown_) { | |
| 114 keys->clear(); | |
| 115 return; | |
| 116 } | |
| 117 | |
| 118 if (!impl_) { | |
| 119 impl_ = new KeyUtilityClientImpl(); | |
| 120 impl_->StartUtilityProcess(); | |
| 121 } | |
| 122 | |
| 123 return impl_->CreateIDBKeysFromSerializedValuesAndKeyPath(values, key_path, | |
| 124 keys); | |
| 125 } | |
| 126 | |
| 127 // KeyUtilityClientImpl definitions. | |
| 128 | |
| 129 void KeyUtilityClientImpl::Shutdown() { | |
| 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 131 | |
| 132 utility_process_host_->EndBatchMode(); | |
| 133 utility_process_host_ = NULL; | |
| 134 client_ = NULL; | |
| 135 state_ = STATE_SHUTDOWN; | |
| 136 } | |
| 137 | |
| 138 KeyUtilityClientImpl::KeyUtilityClientImpl() | |
| 14 : waitable_event_(false, false), | 139 : waitable_event_(false, false), |
| 15 state_(STATE_UNINITIALIZED), | 140 state_(STATE_UNINITIALIZED), |
| 16 utility_process_host_(NULL) { | 141 utility_process_host_(NULL) { |
| 17 } | 142 } |
| 18 | 143 |
| 19 IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() { | 144 KeyUtilityClientImpl::~KeyUtilityClientImpl() { |
| 20 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_SHUTDOWN); | 145 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_SHUTDOWN); |
| 21 DCHECK(!utility_process_host_); | 146 DCHECK(!utility_process_host_); |
| 22 DCHECK(!client_.get()); | 147 DCHECK(!client_.get()); |
| 23 } | 148 } |
| 24 | 149 |
| 25 void IndexedDBKeyUtilityClient::StartUtilityProcess() { | 150 void KeyUtilityClientImpl::StartUtilityProcess() { |
| 26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); | 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
| 27 DCHECK(state_ == STATE_UNINITIALIZED); | 152 DCHECK(state_ == STATE_UNINITIALIZED); |
| 28 | 153 |
| 29 GetRDHAndStartUtilityProcess(); | 154 GetRDHAndStartUtilityProcess(); |
| 30 bool ret = waitable_event_.Wait(); | 155 bool ret = waitable_event_.Wait(); |
| 31 | 156 |
| 32 DCHECK(ret && state_ == STATE_INITIALIZED); | 157 DCHECK(ret && state_ == STATE_INITIALIZED); |
| 33 } | 158 } |
| 34 | 159 |
| 35 void IndexedDBKeyUtilityClient::EndUtilityProcess() { | 160 void KeyUtilityClientImpl::CreateIDBKeysFromSerializedValuesAndKeyPath( |
| 36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); | |
| 37 DCHECK(state_ == STATE_INITIALIZED); | |
| 38 | |
| 39 EndUtilityProcessInternal(); | |
| 40 bool ret = waitable_event_.Wait(); | |
| 41 | |
| 42 DCHECK(ret && state_ == STATE_SHUTDOWN); | |
| 43 } | |
| 44 | |
| 45 void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath( | |
| 46 const std::vector<SerializedScriptValue>& values, | 161 const std::vector<SerializedScriptValue>& values, |
| 47 const string16& key_path, | 162 const string16& key_path, |
| 48 std::vector<IndexedDBKey>* keys) { | 163 std::vector<IndexedDBKey>* keys) { |
| 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); | 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
| 165 if (state_ == STATE_SHUTDOWN) { | |
| 166 keys->clear(); | |
| 167 return; | |
| 168 } | |
| 169 | |
| 50 DCHECK(state_ == STATE_INITIALIZED); | 170 DCHECK(state_ == STATE_INITIALIZED); |
| 51 | 171 |
| 52 state_ = STATE_CREATING_KEYS; | 172 state_ = STATE_CREATING_KEYS; |
| 53 CallStartIDBKeyFromValueAndKeyPathFromIOThread(values, key_path); | 173 CallStartIDBKeyFromValueAndKeyPathFromIOThread(values, key_path); |
| 54 bool ret = waitable_event_.Wait(); | 174 bool ret = waitable_event_.Wait(); |
| 55 DCHECK(ret && state_ == STATE_INITIALIZED); | 175 DCHECK(ret && state_ == STATE_INITIALIZED); |
| 56 | 176 |
| 57 *keys = keys_; | 177 *keys = keys_; |
| 58 } | 178 } |
| 59 | 179 |
| 60 void IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess() { | 180 void KeyUtilityClientImpl::GetRDHAndStartUtilityProcess() { |
| 61 // In order to start the UtilityProcess, we need to grab | 181 // In order to start the UtilityProcess, we need to grab |
| 62 // a pointer to the ResourceDispatcherHost. This can only | 182 // a pointer to the ResourceDispatcherHost. This can only |
| 63 // be done on the UI thread. See the comment at the top of | 183 // be done on the UI thread. See the comment at the top of |
| 64 // browser_process.h | 184 // browser_process.h |
| 65 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 185 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 66 BrowserThread::PostTask( | 186 BrowserThread::PostTask( |
| 67 BrowserThread::UI, FROM_HERE, | 187 BrowserThread::UI, FROM_HERE, |
| 68 NewRunnableMethod( | 188 NewRunnableMethod( |
| 69 this, | 189 this, |
| 70 &IndexedDBKeyUtilityClient::GetRDHAndStartUtilityProcess)); | 190 &KeyUtilityClientImpl::GetRDHAndStartUtilityProcess)); |
| 71 return; | 191 return; |
| 72 } | 192 } |
| 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 74 StartUtilityProcessInternal(g_browser_process->resource_dispatcher_host()); | 194 StartUtilityProcessInternal(g_browser_process->resource_dispatcher_host()); |
| 75 } | 195 } |
| 76 | 196 |
| 77 void IndexedDBKeyUtilityClient::StartUtilityProcessInternal( | 197 void KeyUtilityClientImpl::StartUtilityProcessInternal( |
| 78 ResourceDispatcherHost* rdh) { | 198 ResourceDispatcherHost* rdh) { |
| 79 DCHECK(rdh); | 199 DCHECK(rdh); |
| 80 // The ResourceDispatcherHost can only be used on the IO thread. | 200 // The ResourceDispatcherHost can only be used on the IO thread. |
| 81 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 201 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 83 BrowserThread::PostTask( | 203 BrowserThread::PostTask( |
| 84 BrowserThread::IO, FROM_HERE, | 204 BrowserThread::IO, FROM_HERE, |
| 85 NewRunnableMethod( | 205 NewRunnableMethod( |
| 86 this, | 206 this, |
| 87 &IndexedDBKeyUtilityClient::StartUtilityProcessInternal, | 207 &KeyUtilityClientImpl::StartUtilityProcessInternal, |
| 88 rdh)); | 208 rdh)); |
| 89 return; | 209 return; |
| 90 } | 210 } |
| 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 92 DCHECK(state_ == STATE_UNINITIALIZED); | 212 DCHECK(state_ == STATE_UNINITIALIZED); |
| 93 | 213 |
| 94 client_ = new IndexedDBKeyUtilityClient::Client(this); | 214 client_ = new KeyUtilityClientImpl::Client(this); |
| 95 utility_process_host_ = new UtilityProcessHost( | 215 utility_process_host_ = new UtilityProcessHost( |
| 96 rdh, client_.get(), BrowserThread::IO); | 216 rdh, client_.get(), BrowserThread::IO); |
| 97 utility_process_host_->StartBatchMode(); | 217 utility_process_host_->StartBatchMode(); |
| 98 state_ = STATE_INITIALIZED; | 218 state_ = STATE_INITIALIZED; |
| 99 waitable_event_.Signal(); | 219 waitable_event_.Signal(); |
| 100 } | 220 } |
| 101 | 221 |
| 102 void IndexedDBKeyUtilityClient::EndUtilityProcessInternal() { | 222 void KeyUtilityClientImpl::EndUtilityProcessInternal() { |
| 103 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 223 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 104 BrowserThread::PostTask( | 224 BrowserThread::PostTask( |
| 105 BrowserThread::IO, FROM_HERE, | 225 BrowserThread::IO, FROM_HERE, |
| 106 NewRunnableMethod( | 226 NewRunnableMethod( |
| 107 this, | 227 this, |
| 108 &IndexedDBKeyUtilityClient::EndUtilityProcessInternal)); | 228 &KeyUtilityClientImpl::EndUtilityProcessInternal)); |
| 109 return; | 229 return; |
| 110 } | 230 } |
| 111 | 231 |
| 112 utility_process_host_->EndBatchMode(); | 232 utility_process_host_->EndBatchMode(); |
| 113 utility_process_host_ = NULL; | 233 utility_process_host_ = NULL; |
| 114 client_ = NULL; | 234 client_ = NULL; |
| 115 state_ = STATE_SHUTDOWN; | 235 state_ = STATE_SHUTDOWN; |
| 116 waitable_event_.Signal(); | 236 waitable_event_.Signal(); |
| 117 } | 237 } |
| 118 | 238 |
| 119 void IndexedDBKeyUtilityClient::CallStartIDBKeyFromValueAndKeyPathFromIOThread( | 239 void KeyUtilityClientImpl::CallStartIDBKeyFromValueAndKeyPathFromIOThread( |
| 120 const std::vector<SerializedScriptValue>& values, | 240 const std::vector<SerializedScriptValue>& values, |
| 121 const string16& key_path) { | 241 const string16& key_path) { |
| 122 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 242 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 123 BrowserThread::PostTask( | 243 BrowserThread::PostTask( |
| 124 BrowserThread::IO, FROM_HERE, | 244 BrowserThread::IO, FROM_HERE, |
| 125 NewRunnableMethod(this, | 245 NewRunnableMethod(this, |
| 126 &IndexedDBKeyUtilityClient:: | 246 &KeyUtilityClientImpl:: |
| 127 CallStartIDBKeyFromValueAndKeyPathFromIOThread, | 247 CallStartIDBKeyFromValueAndKeyPathFromIOThread, |
| 128 values, key_path)); | 248 values, key_path)); |
| 129 return; | 249 return; |
| 130 } | 250 } |
| 131 | 251 |
| 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 133 utility_process_host_->StartIDBKeysFromValuesAndKeyPath( | 253 utility_process_host_->StartIDBKeysFromValuesAndKeyPath( |
| 134 0, values, key_path); | 254 0, values, key_path); |
| 135 } | 255 } |
| 136 | 256 |
| 137 void IndexedDBKeyUtilityClient::SetKeys(const std::vector<IndexedDBKey>& keys) { | 257 void KeyUtilityClientImpl::SetKeys(const std::vector<IndexedDBKey>& keys) { |
| 138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 139 keys_ = keys; | 259 keys_ = keys; |
| 140 } | 260 } |
| 141 | 261 |
| 142 void IndexedDBKeyUtilityClient::FinishCreatingKeys() { | 262 void KeyUtilityClientImpl::FinishCreatingKeys() { |
| 143 DCHECK(state_ == STATE_CREATING_KEYS); | 263 DCHECK(state_ == STATE_CREATING_KEYS); |
| 144 state_ = STATE_INITIALIZED; | 264 state_ = STATE_INITIALIZED; |
| 145 waitable_event_.Signal(); | 265 waitable_event_.Signal(); |
| 146 } | 266 } |
| 147 | 267 |
| 148 IndexedDBKeyUtilityClient::Client::Client(IndexedDBKeyUtilityClient* parent) | 268 KeyUtilityClientImpl::Client::Client(KeyUtilityClientImpl* parent) |
| 149 : parent_(parent) { | 269 : parent_(parent) { |
| 150 } | 270 } |
| 151 | 271 |
| 152 void IndexedDBKeyUtilityClient::Client::OnProcessCrashed(int exit_code) { | 272 void KeyUtilityClientImpl::Client::OnProcessCrashed(int exit_code) { |
| 153 if (parent_->state_ == STATE_CREATING_KEYS) | 273 if (parent_->state_ == STATE_CREATING_KEYS) |
| 154 parent_->FinishCreatingKeys(); | 274 parent_->FinishCreatingKeys(); |
| 155 } | 275 } |
| 156 | 276 |
| 157 void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathSucceeded( | 277 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathSucceeded( |
| 158 int id, const std::vector<IndexedDBKey>& keys) { | 278 int id, const std::vector<IndexedDBKey>& keys) { |
| 159 parent_->SetKeys(keys); | 279 parent_->SetKeys(keys); |
| 160 parent_->FinishCreatingKeys(); | 280 parent_->FinishCreatingKeys(); |
| 161 } | 281 } |
| 162 | 282 |
| 163 void IndexedDBKeyUtilityClient::Client::OnIDBKeysFromValuesAndKeyPathFailed( | 283 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathFailed( |
| 164 int id) { | 284 int id) { |
| 165 parent_->FinishCreatingKeys(); | 285 parent_->FinishCreatingKeys(); |
| 166 } | 286 } |
| OLD | NEW |