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