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 |