Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: content/browser/in_process_webkit/indexed_db_key_utility_client.cc

Issue 10834350: Remove all the indexeddb-related utility process code (Closed) Base URL: http://git.chromium.org/chromium/src.git@opencursor-cleanup
Patch Set: Rebase, attempt to reland Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/in_process_webkit/indexed_db_key_utility_client.h"
6
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "content/browser/utility_process_host_impl.h"
11 #include "content/common/indexed_db/indexed_db_key.h"
12 #include "content/common/indexed_db/indexed_db_key_path.h"
13 #include "content/common/indexed_db/indexed_db_messages.h"
14 #include "content/common/utility_messages.h"
15 #include "content/public/browser/utility_process_host_client.h"
16 #include "content/public/common/serialized_script_value.h"
17
18 using content::BrowserThread;
19 using content::IndexedDBKey;
20 using content::IndexedDBKeyPath;
21 using content::UtilityProcessHostClient;
22 using content::SerializedScriptValue;
23
24 // This class is used to obtain IndexedDBKeys from SerializedScriptValues
25 // given an IDBKeyPath. It uses UtilityProcess to do this inside a sandbox
26 // (a V8 lock is required there). At this level, all methods are synchronous
27 // as required by the caller. The public API is used on WEBKIT thread,
28 // but internally it moves around to UI and IO as needed.
29 class KeyUtilityClientImpl
30 : public base::RefCountedThreadSafe<KeyUtilityClientImpl> {
31 public:
32 KeyUtilityClientImpl();
33
34 // Starts the UtilityProcess. Must be called before any other method.
35 void StartUtilityProcess();
36
37 // Stops the UtilityProcess. No further keys can be created after this.
38 void Shutdown();
39
40 // Synchronously obtain the |keys| from |values| for the given |key_path|.
41 void CreateIDBKeysFromSerializedValuesAndKeyPath(
42 const std::vector<SerializedScriptValue>& values,
43 const IndexedDBKeyPath& key_path,
44 std::vector<IndexedDBKey>* keys);
45
46 // Synchronously inject |key| into |value| using the given |key_path|,
47 // returning the new value.
48 SerializedScriptValue InjectIDBKeyIntoSerializedValue(
49 const IndexedDBKey& key,
50 const SerializedScriptValue& value,
51 const IndexedDBKeyPath& key_path);
52
53 private:
54 class Client : public UtilityProcessHostClient {
55 public:
56 explicit Client(KeyUtilityClientImpl* parent);
57
58 // UtilityProcessHostClient
59 virtual void OnProcessCrashed(int exit_code);
60 virtual bool OnMessageReceived(const IPC::Message& message);
61
62 // IPC message handlers
63 void OnIDBKeysFromValuesAndKeyPathSucceeded(
64 int id, const std::vector<IndexedDBKey>& keys);
65 void OnIDBKeysFromValuesAndKeyPathFailed(int id);
66 void OnInjectIDBKeyFinished(const SerializedScriptValue& value);
67
68 private:
69 virtual ~Client() {}
70
71 KeyUtilityClientImpl* parent_;
72
73 DISALLOW_COPY_AND_ASSIGN(Client);
74 };
75
76 friend class base::RefCountedThreadSafe<KeyUtilityClientImpl>;
77 ~KeyUtilityClientImpl();
78
79 void GetRDHAndStartUtilityProcess();
80 void StartUtilityProcessInternal();
81 void EndUtilityProcessInternal();
82 void CallStartIDBKeyFromValueAndKeyPathFromIOThread(
83 const std::vector<SerializedScriptValue>& values,
84 const IndexedDBKeyPath& key_path);
85 void CallStartInjectIDBKeyFromIOThread(
86 const IndexedDBKey& key,
87 const SerializedScriptValue& value,
88 const IndexedDBKeyPath& key_path);
89
90 void SetKeys(const std::vector<IndexedDBKey>& keys);
91 void FinishCreatingKeys();
92 void SetValueAfterInjection(const SerializedScriptValue& value);
93 void FinishInjectingKey();
94
95 base::WaitableEvent waitable_event_;
96
97 // Used in both IO and WEBKIT threads, but guarded by WaitableEvent, i.e.,
98 // these members are only set / read when the other thread is blocked.
99 enum State {
100 STATE_UNINITIALIZED,
101 STATE_INITIALIZED,
102 STATE_CREATING_KEYS,
103 STATE_INJECTING_KEY,
104 STATE_SHUTDOWN,
105 };
106 State state_;
107 std::vector<IndexedDBKey> keys_;
108 SerializedScriptValue value_after_injection_;
109
110 // Used in the IO thread.
111 base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
112 scoped_refptr<Client> client_;
113
114 DISALLOW_COPY_AND_ASSIGN(KeyUtilityClientImpl);
115 };
116
117 // IndexedDBKeyUtilityClient definitions.
118
119 static base::LazyInstance<IndexedDBKeyUtilityClient> client_instance =
120 LAZY_INSTANCE_INITIALIZER;
121
122 IndexedDBKeyUtilityClient::IndexedDBKeyUtilityClient()
123 : is_shutdown_(false) {
124 // Note that creating the impl_ object is deferred until it is first needed,
125 // as this class can be constructed even though it never gets used.
126 }
127
128 IndexedDBKeyUtilityClient::~IndexedDBKeyUtilityClient() {
129 DCHECK(!impl_ || is_shutdown_);
130 }
131
132 // static
133 void IndexedDBKeyUtilityClient::Shutdown() {
134 IndexedDBKeyUtilityClient* instance = client_instance.Pointer();
135 if (!instance->impl_)
136 return;
137
138 instance->is_shutdown_ = true;
139 instance->impl_->Shutdown();
140 }
141
142 // static
143 void IndexedDBKeyUtilityClient::CreateIDBKeysFromSerializedValuesAndKeyPath(
144 const std::vector<SerializedScriptValue>& values,
145 const IndexedDBKeyPath& key_path,
146 std::vector<IndexedDBKey>* keys) {
147 IndexedDBKeyUtilityClient* instance = client_instance.Pointer();
148
149 if (instance->is_shutdown_) {
150 keys->clear();
151 return;
152 }
153
154 if (!instance->impl_) {
155 instance->impl_ = new KeyUtilityClientImpl();
156 instance->impl_->StartUtilityProcess();
157 }
158
159 instance->impl_->CreateIDBKeysFromSerializedValuesAndKeyPath(values, key_path,
160 keys);
161 }
162
163 // static
164 SerializedScriptValue
165 IndexedDBKeyUtilityClient::InjectIDBKeyIntoSerializedValue(
166 const IndexedDBKey& key, const SerializedScriptValue& value,
167 const IndexedDBKeyPath& key_path) {
168 IndexedDBKeyUtilityClient* instance = client_instance.Pointer();
169
170 if (instance->is_shutdown_)
171 return SerializedScriptValue();
172
173 if (!instance->impl_) {
174 instance->impl_ = new KeyUtilityClientImpl();
175 instance->impl_->StartUtilityProcess();
176 }
177
178 return instance->impl_->InjectIDBKeyIntoSerializedValue(key, value, key_path);
179 }
180
181
182
183 // KeyUtilityClientImpl definitions.
184
185 void KeyUtilityClientImpl::Shutdown() {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
187
188 if (utility_process_host_) {
189 utility_process_host_->EndBatchMode();
190 utility_process_host_.reset();
191 }
192 client_ = NULL;
193 state_ = STATE_SHUTDOWN;
194 }
195
196 KeyUtilityClientImpl::KeyUtilityClientImpl()
197 : waitable_event_(false, false),
198 state_(STATE_UNINITIALIZED) {
199 }
200
201 KeyUtilityClientImpl::~KeyUtilityClientImpl() {
202 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_SHUTDOWN);
203 DCHECK(!utility_process_host_);
204 DCHECK(!client_.get());
205 }
206
207 void KeyUtilityClientImpl::StartUtilityProcess() {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
209 DCHECK(state_ == STATE_UNINITIALIZED);
210
211 GetRDHAndStartUtilityProcess();
212 waitable_event_.Wait();
213
214 DCHECK(state_ == STATE_INITIALIZED);
215 }
216
217 void KeyUtilityClientImpl::CreateIDBKeysFromSerializedValuesAndKeyPath(
218 const std::vector<SerializedScriptValue>& values,
219 const IndexedDBKeyPath& key_path,
220 std::vector<IndexedDBKey>* keys) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
222 if (state_ == STATE_SHUTDOWN) {
223 keys->clear();
224 return;
225 }
226
227 DCHECK(state_ == STATE_INITIALIZED);
228
229 state_ = STATE_CREATING_KEYS;
230 CallStartIDBKeyFromValueAndKeyPathFromIOThread(values, key_path);
231 waitable_event_.Wait();
232 DCHECK(state_ == STATE_INITIALIZED);
233
234 *keys = keys_;
235 }
236
237 SerializedScriptValue KeyUtilityClientImpl::InjectIDBKeyIntoSerializedValue(
238 const IndexedDBKey& key,
239 const SerializedScriptValue& value,
240 const IndexedDBKeyPath& key_path) {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
242 if (state_ == STATE_SHUTDOWN)
243 return SerializedScriptValue();
244
245 DCHECK(state_ == STATE_INITIALIZED);
246
247 state_ = STATE_INJECTING_KEY;
248 CallStartInjectIDBKeyFromIOThread(key, value, key_path);
249
250 waitable_event_.Wait();
251 DCHECK(state_ == STATE_INITIALIZED);
252
253 return value_after_injection_;
254 }
255
256
257 void KeyUtilityClientImpl::GetRDHAndStartUtilityProcess() {
258 // In order to start the UtilityProcess, we need to grab
259 // a pointer to the ResourceDispatcherHost. This can only
260 // be done on the UI thread. See the comment at the top of
261 // browser_process.h
262 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
263 BrowserThread::PostTask(
264 BrowserThread::UI, FROM_HERE,
265 base::Bind(&KeyUtilityClientImpl::GetRDHAndStartUtilityProcess, this));
266 return;
267 }
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
269 StartUtilityProcessInternal();
270 }
271
272 void KeyUtilityClientImpl::StartUtilityProcessInternal() {
273 // The ResourceDispatcherHost can only be used on the IO thread.
274 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
276 BrowserThread::PostTask(
277 BrowserThread::IO, FROM_HERE,
278 base::Bind(&KeyUtilityClientImpl::StartUtilityProcessInternal, this));
279 return;
280 }
281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
282 DCHECK(state_ == STATE_UNINITIALIZED);
283
284 client_ = new KeyUtilityClientImpl::Client(this);
285 utility_process_host_ = (new UtilityProcessHostImpl(
286 client_.get(), BrowserThread::IO))->AsWeakPtr();
287 utility_process_host_->EnableZygote();
288 utility_process_host_->StartBatchMode();
289 state_ = STATE_INITIALIZED;
290 waitable_event_.Signal();
291 }
292
293 void KeyUtilityClientImpl::EndUtilityProcessInternal() {
294 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
295 BrowserThread::PostTask(
296 BrowserThread::IO, FROM_HERE,
297 base::Bind(&KeyUtilityClientImpl::EndUtilityProcessInternal, this));
298 return;
299 }
300
301 if (utility_process_host_) {
302 utility_process_host_->EndBatchMode();
303 utility_process_host_.reset();
304 }
305 client_ = NULL;
306 state_ = STATE_SHUTDOWN;
307 waitable_event_.Signal();
308 }
309
310 void KeyUtilityClientImpl::CallStartIDBKeyFromValueAndKeyPathFromIOThread(
311 const std::vector<SerializedScriptValue>& values,
312 const IndexedDBKeyPath& key_path) {
313 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
314 BrowserThread::PostTask(
315 BrowserThread::IO, FROM_HERE,
316 base::Bind(&KeyUtilityClientImpl::
317 CallStartIDBKeyFromValueAndKeyPathFromIOThread,
318 this, values, key_path));
319 return;
320 }
321
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
323 if (utility_process_host_) {
324 utility_process_host_->Send(new UtilityMsg_IDBKeysFromValuesAndKeyPath(
325 0, values, key_path));
326 }
327 }
328
329 void KeyUtilityClientImpl::CallStartInjectIDBKeyFromIOThread(
330 const IndexedDBKey& key,
331 const SerializedScriptValue& value,
332 const IndexedDBKeyPath& key_path) {
333 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
334 BrowserThread::PostTask(
335 BrowserThread::IO, FROM_HERE,
336 base::Bind(&KeyUtilityClientImpl::CallStartInjectIDBKeyFromIOThread,
337 this, key, value, key_path));
338 return;
339 }
340
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
342 if (utility_process_host_)
343 utility_process_host_->Send(new UtilityMsg_InjectIDBKey(
344 key, value, key_path));
345 }
346
347 void KeyUtilityClientImpl::SetKeys(const std::vector<IndexedDBKey>& keys) {
348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
349 keys_ = keys;
350 }
351
352 void KeyUtilityClientImpl::FinishCreatingKeys() {
353 DCHECK(state_ == STATE_CREATING_KEYS);
354 state_ = STATE_INITIALIZED;
355 waitable_event_.Signal();
356 }
357
358 void KeyUtilityClientImpl::SetValueAfterInjection(
359 const SerializedScriptValue& value) {
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
361 value_after_injection_ = value;
362 }
363
364 void KeyUtilityClientImpl::FinishInjectingKey() {
365 DCHECK(state_ == STATE_INJECTING_KEY);
366 state_ = STATE_INITIALIZED;
367 waitable_event_.Signal();
368 }
369
370 KeyUtilityClientImpl::Client::Client(KeyUtilityClientImpl* parent)
371 : parent_(parent) {
372 }
373
374 void KeyUtilityClientImpl::Client::OnProcessCrashed(int exit_code) {
375 if (parent_->state_ == STATE_CREATING_KEYS)
376 parent_->FinishCreatingKeys();
377 parent_->Shutdown();
378 }
379
380 bool KeyUtilityClientImpl::Client::OnMessageReceived(
381 const IPC::Message& message) {
382 bool handled = true;
383 IPC_BEGIN_MESSAGE_MAP(KeyUtilityClientImpl::Client, message)
384 IPC_MESSAGE_HANDLER(UtilityHostMsg_IDBKeysFromValuesAndKeyPath_Succeeded,
385 OnIDBKeysFromValuesAndKeyPathSucceeded)
386 IPC_MESSAGE_HANDLER(UtilityHostMsg_InjectIDBKey_Finished,
387 OnInjectIDBKeyFinished)
388 IPC_MESSAGE_UNHANDLED(handled = false)
389 IPC_END_MESSAGE_MAP()
390 return handled;
391 }
392
393 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathSucceeded(
394 int id, const std::vector<IndexedDBKey>& keys) {
395 parent_->SetKeys(keys);
396 parent_->FinishCreatingKeys();
397 }
398
399 void KeyUtilityClientImpl::Client::OnInjectIDBKeyFinished(
400 const SerializedScriptValue& value) {
401 parent_->SetValueAfterInjection(value);
402 parent_->FinishInjectingKey();
403 }
404
405 void KeyUtilityClientImpl::Client::OnIDBKeysFromValuesAndKeyPathFailed(
406 int id) {
407 parent_->FinishCreatingKeys();
408 }
OLDNEW
« no previous file with comments | « content/browser/in_process_webkit/indexed_db_key_utility_client.h ('k') | content/browser/indexed_db/OWNERS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698