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