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