| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/in_process_webkit/indexed_db_key_utility_client.h" | 5 #include "content/browser/in_process_webkit/indexed_db_key_utility_client.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
| 9 #include "base/synchronization/waitable_event.h" | 9 #include "base/synchronization/waitable_event.h" |
| 10 #include "content/browser/utility_process_host_impl.h" | 10 #include "content/browser/utility_process_host_impl.h" |
| 11 #include "content/common/indexed_db/indexed_db_key.h" | 11 #include "content/common/indexed_db/indexed_db_key.h" |
| 12 #include "content/common/indexed_db/indexed_db_key_path.h" |
| 12 #include "content/common/indexed_db/indexed_db_messages.h" | 13 #include "content/common/indexed_db/indexed_db_messages.h" |
| 13 #include "content/common/utility_messages.h" | 14 #include "content/common/utility_messages.h" |
| 14 #include "content/public/browser/utility_process_host_client.h" | 15 #include "content/public/browser/utility_process_host_client.h" |
| 15 #include "content/public/common/serialized_script_value.h" | 16 #include "content/public/common/serialized_script_value.h" |
| 16 | 17 |
| 17 using content::BrowserThread; | 18 using content::BrowserThread; |
| 18 using content::UtilityProcessHostClient; | 19 using content::UtilityProcessHostClient; |
| 19 | 20 |
| 20 // This class is used to obtain IndexedDBKeys from SerializedScriptValues | 21 // This class is used to obtain IndexedDBKeys from SerializedScriptValues |
| 21 // given an IDBKeyPath. It uses UtilityProcess to do this inside a sandbox | 22 // given an IDBKeyPath. It uses UtilityProcess to do this inside a sandbox |
| 22 // (a V8 lock is required there). At this level, all methods are synchronous | 23 // (a V8 lock is required there). At this level, all methods are synchronous |
| 23 // as required by the caller. The public API is used on WEBKIT thread, | 24 // as required by the caller. The public API is used on WEBKIT thread, |
| 24 // but internally it moves around to UI and IO as needed. | 25 // but internally it moves around to UI and IO as needed. |
| 25 class KeyUtilityClientImpl | 26 class KeyUtilityClientImpl |
| 26 : public base::RefCountedThreadSafe<KeyUtilityClientImpl> { | 27 : public base::RefCountedThreadSafe<KeyUtilityClientImpl> { |
| 27 public: | 28 public: |
| 28 KeyUtilityClientImpl(); | 29 KeyUtilityClientImpl(); |
| 29 | 30 |
| 30 // Starts the UtilityProcess. Must be called before any other method. | 31 // Starts the UtilityProcess. Must be called before any other method. |
| 31 void StartUtilityProcess(); | 32 void StartUtilityProcess(); |
| 32 | 33 |
| 33 // Stops the UtilityProcess. No further keys can be created after this. | 34 // Stops the UtilityProcess. No further keys can be created after this. |
| 34 void Shutdown(); | 35 void Shutdown(); |
| 35 | 36 |
| 36 // Synchronously obtain the |keys| from |values| for the given |key_path|. | 37 // Synchronously obtain the |keys| from |values| for the given |key_path|. |
| 37 void CreateIDBKeysFromSerializedValuesAndKeyPath( | 38 void CreateIDBKeysFromSerializedValuesAndKeyPath( |
| 38 const std::vector<content::SerializedScriptValue>& values, | 39 const std::vector<content::SerializedScriptValue>& values, |
| 39 const string16& key_path, | 40 const IndexedDBKeyPath& key_path, |
| 40 std::vector<IndexedDBKey>* keys); | 41 std::vector<IndexedDBKey>* keys); |
| 41 | 42 |
| 42 // Synchronously inject |key| into |value| using the given |key_path|, | 43 // Synchronously inject |key| into |value| using the given |key_path|, |
| 43 // returning the new value. | 44 // returning the new value. |
| 44 content::SerializedScriptValue InjectIDBKeyIntoSerializedValue( | 45 content::SerializedScriptValue InjectIDBKeyIntoSerializedValue( |
| 45 const IndexedDBKey& key, | 46 const IndexedDBKey& key, |
| 46 const content::SerializedScriptValue& value, | 47 const content::SerializedScriptValue& value, |
| 47 const string16& key_path); | 48 const IndexedDBKeyPath& key_path); |
| 48 | 49 |
| 49 private: | 50 private: |
| 50 class Client : public UtilityProcessHostClient { | 51 class Client : public UtilityProcessHostClient { |
| 51 public: | 52 public: |
| 52 explicit Client(KeyUtilityClientImpl* parent); | 53 explicit Client(KeyUtilityClientImpl* parent); |
| 53 | 54 |
| 54 // UtilityProcessHostClient | 55 // UtilityProcessHostClient |
| 55 virtual void OnProcessCrashed(int exit_code); | 56 virtual void OnProcessCrashed(int exit_code); |
| 56 virtual bool OnMessageReceived(const IPC::Message& message); | 57 virtual bool OnMessageReceived(const IPC::Message& message); |
| 57 | 58 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 68 }; | 69 }; |
| 69 | 70 |
| 70 friend class base::RefCountedThreadSafe<KeyUtilityClientImpl>; | 71 friend class base::RefCountedThreadSafe<KeyUtilityClientImpl>; |
| 71 ~KeyUtilityClientImpl(); | 72 ~KeyUtilityClientImpl(); |
| 72 | 73 |
| 73 void GetRDHAndStartUtilityProcess(); | 74 void GetRDHAndStartUtilityProcess(); |
| 74 void StartUtilityProcessInternal(); | 75 void StartUtilityProcessInternal(); |
| 75 void EndUtilityProcessInternal(); | 76 void EndUtilityProcessInternal(); |
| 76 void CallStartIDBKeyFromValueAndKeyPathFromIOThread( | 77 void CallStartIDBKeyFromValueAndKeyPathFromIOThread( |
| 77 const std::vector<content::SerializedScriptValue>& values, | 78 const std::vector<content::SerializedScriptValue>& values, |
| 78 const string16& key_path); | 79 const IndexedDBKeyPath& key_path); |
| 79 void CallStartInjectIDBKeyFromIOThread( | 80 void CallStartInjectIDBKeyFromIOThread( |
| 80 const IndexedDBKey& key, | 81 const IndexedDBKey& key, |
| 81 const content::SerializedScriptValue& value, | 82 const content::SerializedScriptValue& value, |
| 82 const string16& key_path); | 83 const IndexedDBKeyPath& key_path); |
| 83 | 84 |
| 84 void SetKeys(const std::vector<IndexedDBKey>& keys); | 85 void SetKeys(const std::vector<IndexedDBKey>& keys); |
| 85 void FinishCreatingKeys(); | 86 void FinishCreatingKeys(); |
| 86 void SetValueAfterInjection(const content::SerializedScriptValue& value); | 87 void SetValueAfterInjection(const content::SerializedScriptValue& value); |
| 87 void FinishInjectingKey(); | 88 void FinishInjectingKey(); |
| 88 | 89 |
| 89 base::WaitableEvent waitable_event_; | 90 base::WaitableEvent waitable_event_; |
| 90 | 91 |
| 91 // Used in both IO and WEBKIT threads, but guarded by WaitableEvent, i.e., | 92 // Used in both IO and WEBKIT threads, but guarded by WaitableEvent, i.e., |
| 92 // these members are only set / read when the other thread is blocked. | 93 // these members are only set / read when the other thread is blocked. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 if (!instance->impl_) | 130 if (!instance->impl_) |
| 130 return; | 131 return; |
| 131 | 132 |
| 132 instance->is_shutdown_ = true; | 133 instance->is_shutdown_ = true; |
| 133 instance->impl_->Shutdown(); | 134 instance->impl_->Shutdown(); |
| 134 } | 135 } |
| 135 | 136 |
| 136 // static | 137 // static |
| 137 void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath( | 138 void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath( |
| 138 const std::vector<content::SerializedScriptValue>& values, | 139 const std::vector<content::SerializedScriptValue>& values, |
| 139 const string16& key_path, | 140 const IndexedDBKeyPath& key_path, |
| 140 std::vector<IndexedDBKey>* keys) { | 141 std::vector<IndexedDBKey>* keys) { |
| 141 IndexedDBKeyUtilityClient* instance = client_instance.Pointer(); | 142 IndexedDBKeyUtilityClient* instance = client_instance.Pointer(); |
| 142 | 143 |
| 143 if (instance->is_shutdown_) { | 144 if (instance->is_shutdown_) { |
| 144 keys->clear(); | 145 keys->clear(); |
| 145 return; | 146 return; |
| 146 } | 147 } |
| 147 | 148 |
| 148 if (!instance->impl_) { | 149 if (!instance->impl_) { |
| 149 instance->impl_ = new KeyUtilityClientImpl(); | 150 instance->impl_ = new KeyUtilityClientImpl(); |
| 150 instance->impl_->StartUtilityProcess(); | 151 instance->impl_->StartUtilityProcess(); |
| 151 } | 152 } |
| 152 | 153 |
| 153 instance->impl_->CreateIDBKeysFromSerializedValuesAndKeyPath(values, key_path, | 154 instance->impl_->CreateIDBKeysFromSerializedValuesAndKeyPath(values, key_path, |
| 154 keys); | 155 keys); |
| 155 } | 156 } |
| 156 | 157 |
| 157 // static | 158 // static |
| 158 content::SerializedScriptValue | 159 content::SerializedScriptValue |
| 159 IndexedDBKeyUtilityClient::InjectIDBKeyIntoSerializedValue( | 160 IndexedDBKeyUtilityClient::InjectIDBKeyIntoSerializedValue( |
| 160 const IndexedDBKey& key, const content::SerializedScriptValue& value, | 161 const IndexedDBKey& key, const content::SerializedScriptValue& value, |
| 161 const string16& key_path) { | 162 const IndexedDBKeyPath& key_path) { |
| 162 IndexedDBKeyUtilityClient* instance = client_instance.Pointer(); | 163 IndexedDBKeyUtilityClient* instance = client_instance.Pointer(); |
| 163 | 164 |
| 164 if (instance->is_shutdown_) | 165 if (instance->is_shutdown_) |
| 165 return content::SerializedScriptValue(); | 166 return content::SerializedScriptValue(); |
| 166 | 167 |
| 167 if (!instance->impl_) { | 168 if (!instance->impl_) { |
| 168 instance->impl_ = new KeyUtilityClientImpl(); | 169 instance->impl_ = new KeyUtilityClientImpl(); |
| 169 instance->impl_->StartUtilityProcess(); | 170 instance->impl_->StartUtilityProcess(); |
| 170 } | 171 } |
| 171 | 172 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 DCHECK(state_ == STATE_UNINITIALIZED); | 204 DCHECK(state_ == STATE_UNINITIALIZED); |
| 204 | 205 |
| 205 GetRDHAndStartUtilityProcess(); | 206 GetRDHAndStartUtilityProcess(); |
| 206 waitable_event_.Wait(); | 207 waitable_event_.Wait(); |
| 207 | 208 |
| 208 DCHECK(state_ == STATE_INITIALIZED); | 209 DCHECK(state_ == STATE_INITIALIZED); |
| 209 } | 210 } |
| 210 | 211 |
| 211 void KeyUtilityClientImpl::CreateIDBKeysFromSerializedValuesAndKeyPath( | 212 void KeyUtilityClientImpl::CreateIDBKeysFromSerializedValuesAndKeyPath( |
| 212 const std::vector<content::SerializedScriptValue>& values, | 213 const std::vector<content::SerializedScriptValue>& values, |
| 213 const string16& key_path, | 214 const IndexedDBKeyPath& key_path, |
| 214 std::vector<IndexedDBKey>* keys) { | 215 std::vector<IndexedDBKey>* keys) { |
| 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | 216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); |
| 216 if (state_ == STATE_SHUTDOWN) { | 217 if (state_ == STATE_SHUTDOWN) { |
| 217 keys->clear(); | 218 keys->clear(); |
| 218 return; | 219 return; |
| 219 } | 220 } |
| 220 | 221 |
| 221 DCHECK(state_ == STATE_INITIALIZED); | 222 DCHECK(state_ == STATE_INITIALIZED); |
| 222 | 223 |
| 223 state_ = STATE_CREATING_KEYS; | 224 state_ = STATE_CREATING_KEYS; |
| 224 CallStartIDBKeyFromValueAndKeyPathFromIOThread(values, key_path); | 225 CallStartIDBKeyFromValueAndKeyPathFromIOThread(values, key_path); |
| 225 waitable_event_.Wait(); | 226 waitable_event_.Wait(); |
| 226 DCHECK(state_ == STATE_INITIALIZED); | 227 DCHECK(state_ == STATE_INITIALIZED); |
| 227 | 228 |
| 228 *keys = keys_; | 229 *keys = keys_; |
| 229 } | 230 } |
| 230 | 231 |
| 231 content::SerializedScriptValue | 232 content::SerializedScriptValue |
| 232 KeyUtilityClientImpl::InjectIDBKeyIntoSerializedValue( | 233 KeyUtilityClientImpl::InjectIDBKeyIntoSerializedValue( |
| 233 const IndexedDBKey& key, | 234 const IndexedDBKey& key, |
| 234 const content::SerializedScriptValue& value, | 235 const content::SerializedScriptValue& value, |
| 235 const string16& key_path) { | 236 const IndexedDBKeyPath& key_path) { |
| 236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); |
| 237 if (state_ == STATE_SHUTDOWN) | 238 if (state_ == STATE_SHUTDOWN) |
| 238 return content::SerializedScriptValue(); | 239 return content::SerializedScriptValue(); |
| 239 | 240 |
| 240 DCHECK(state_ == STATE_INITIALIZED); | 241 DCHECK(state_ == STATE_INITIALIZED); |
| 241 | 242 |
| 242 state_ = STATE_INJECTING_KEY; | 243 state_ = STATE_INJECTING_KEY; |
| 243 CallStartInjectIDBKeyFromIOThread(key, value, key_path); | 244 CallStartInjectIDBKeyFromIOThread(key, value, key_path); |
| 244 | 245 |
| 245 waitable_event_.Wait(); | 246 waitable_event_.Wait(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 utility_process_host_->EndBatchMode(); | 298 utility_process_host_->EndBatchMode(); |
| 298 utility_process_host_.reset(); | 299 utility_process_host_.reset(); |
| 299 } | 300 } |
| 300 client_ = NULL; | 301 client_ = NULL; |
| 301 state_ = STATE_SHUTDOWN; | 302 state_ = STATE_SHUTDOWN; |
| 302 waitable_event_.Signal(); | 303 waitable_event_.Signal(); |
| 303 } | 304 } |
| 304 | 305 |
| 305 void KeyUtilityClientImpl::CallStartIDBKeyFromValueAndKeyPathFromIOThread( | 306 void KeyUtilityClientImpl::CallStartIDBKeyFromValueAndKeyPathFromIOThread( |
| 306 const std::vector<content::SerializedScriptValue>& values, | 307 const std::vector<content::SerializedScriptValue>& values, |
| 307 const string16& key_path) { | 308 const IndexedDBKeyPath& key_path) { |
| 308 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 309 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 309 BrowserThread::PostTask( | 310 BrowserThread::PostTask( |
| 310 BrowserThread::IO, FROM_HERE, | 311 BrowserThread::IO, FROM_HERE, |
| 311 base::Bind(&KeyUtilityClientImpl:: | 312 base::Bind(&KeyUtilityClientImpl:: |
| 312 CallStartIDBKeyFromValueAndKeyPathFromIOThread, | 313 CallStartIDBKeyFromValueAndKeyPathFromIOThread, |
| 313 this, values, key_path)); | 314 this, values, key_path)); |
| 314 return; | 315 return; |
| 315 } | 316 } |
| 316 | 317 |
| 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 318 if (utility_process_host_) { | 319 if (utility_process_host_) { |
| 319 utility_process_host_->Send(new UtilityMsg_IDBKeysFromValuesAndKeyPath( | 320 utility_process_host_->Send(new UtilityMsg_IDBKeysFromValuesAndKeyPath( |
| 320 0, values, key_path)); | 321 0, values, key_path)); |
| 321 } | 322 } |
| 322 } | 323 } |
| 323 | 324 |
| 324 void KeyUtilityClientImpl::CallStartInjectIDBKeyFromIOThread( | 325 void KeyUtilityClientImpl::CallStartInjectIDBKeyFromIOThread( |
| 325 const IndexedDBKey& key, | 326 const IndexedDBKey& key, |
| 326 const content::SerializedScriptValue& value, | 327 const content::SerializedScriptValue& value, |
| 327 const string16& key_path) { | 328 const IndexedDBKeyPath& key_path) { |
| 328 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 329 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 329 BrowserThread::PostTask( | 330 BrowserThread::PostTask( |
| 330 BrowserThread::IO, FROM_HERE, | 331 BrowserThread::IO, FROM_HERE, |
| 331 base::Bind(&KeyUtilityClientImpl::CallStartInjectIDBKeyFromIOThread, | 332 base::Bind(&KeyUtilityClientImpl::CallStartInjectIDBKeyFromIOThread, |
| 332 this, key, value, key_path)); | 333 this, key, value, key_path)); |
| 333 return; | 334 return; |
| 334 } | 335 } |
| 335 | 336 |
| 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 337 if (utility_process_host_) | 338 if (utility_process_host_) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 parent_->FinishCreatingKeys(); | 372 parent_->FinishCreatingKeys(); |
| 372 parent_->Shutdown(); | 373 parent_->Shutdown(); |
| 373 } | 374 } |
| 374 | 375 |
| 375 bool KeyUtilityClientImpl::Client::OnMessageReceived( | 376 bool KeyUtilityClientImpl::Client::OnMessageReceived( |
| 376 const IPC::Message& message) { | 377 const IPC::Message& message) { |
| 377 bool handled = true; | 378 bool handled = true; |
| 378 IPC_BEGIN_MESSAGE_MAP(KeyUtilityClientImpl::Client, message) | 379 IPC_BEGIN_MESSAGE_MAP(KeyUtilityClientImpl::Client, message) |
| 379 IPC_MESSAGE_HANDLER(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded, | 380 IPC_MESSAGE_HANDLER(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded, |
| 380 OnIDBKeysFromValuesAndKeyPathSucceeded) | 381 OnIDBKeysFromValuesAndKeyPathSucceeded) |
| 381 IPC_MESSAGE_HANDLER(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Failed, | |
| 382 OnIDBKeysFromValuesAndKeyPathFailed) | |
| 383 IPC_MESSAGE_HANDLER(UtilityHostMsg_InjectIDBKey_Finished, | 382 IPC_MESSAGE_HANDLER(UtilityHostMsg_InjectIDBKey_Finished, |
| 384 OnInjectIDBKeyFinished) | 383 OnInjectIDBKeyFinished) |
| 385 IPC_MESSAGE_UNHANDLED(handled = false) | 384 IPC_MESSAGE_UNHANDLED(handled = false) |
| 386 IPC_END_MESSAGE_MAP() | 385 IPC_END_MESSAGE_MAP() |
| 387 return handled; | 386 return handled; |
| 388 } | 387 } |
| 389 | 388 |
| 390 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathSucceeded( | 389 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathSucceeded( |
| 391 int id, const std::vector<IndexedDBKey>& keys) { | 390 int id, const std::vector<IndexedDBKey>& keys) { |
| 392 parent_->SetKeys(keys); | 391 parent_->SetKeys(keys); |
| 393 parent_->FinishCreatingKeys(); | 392 parent_->FinishCreatingKeys(); |
| 394 } | 393 } |
| 395 | 394 |
| 396 void KeyUtilityClientImpl::Client::OnInjectIDBKeyFinished( | 395 void KeyUtilityClientImpl::Client::OnInjectIDBKeyFinished( |
| 397 const content::SerializedScriptValue& value) { | 396 const content::SerializedScriptValue& value) { |
| 398 parent_->SetValueAfterInjection(value); | 397 parent_->SetValueAfterInjection(value); |
| 399 parent_->FinishInjectingKey(); | 398 parent_->FinishInjectingKey(); |
| 400 } | 399 } |
| 401 | 400 |
| 402 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathFailed( | 401 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathFailed( |
| 403 int id) { | 402 int id) { |
| 404 parent_->FinishCreatingKeys(); | 403 parent_->FinishCreatingKeys(); |
| 405 } | 404 } |
| OLD | NEW |