OLD | NEW |
| (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_dispatcher_host.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/command_line.h" | |
11 #include "base/files/file_path.h" | |
12 #include "base/process.h" | |
13 #include "base/process_util.h" | |
14 #include "base/strings/utf_string_conversions.h" | |
15 #include "content/browser/in_process_webkit/indexed_db_callbacks.h" | |
16 #include "content/browser/in_process_webkit/indexed_db_database_callbacks.h" | |
17 #include "content/browser/indexed_db/indexed_db_context_impl.h" | |
18 #include "content/browser/indexed_db/indexed_db_metadata.h" | |
19 #include "content/browser/indexed_db/webidbcursor_impl.h" | |
20 #include "content/browser/indexed_db/webidbcursor_impl.h" | |
21 #include "content/browser/indexed_db/webidbdatabase_impl.h" | |
22 #include "content/browser/renderer_host/render_message_filter.h" | |
23 #include "content/common/indexed_db/indexed_db_messages.h" | |
24 #include "content/public/browser/browser_thread.h" | |
25 #include "content/public/browser/user_metrics.h" | |
26 #include "content/public/common/content_switches.h" | |
27 #include "content/public/common/result_codes.h" | |
28 #include "googleurl/src/gurl.h" | |
29 #include "third_party/WebKit/public/platform/WebIDBDatabase.h" | |
30 #include "third_party/WebKit/public/platform/WebIDBDatabaseError.h" | |
31 #include "third_party/WebKit/public/platform/WebIDBDatabaseException.h" | |
32 #include "webkit/browser/database/database_util.h" | |
33 #include "webkit/common/database/database_identifier.h" | |
34 | |
35 using webkit_database::DatabaseUtil; | |
36 using WebKit::WebIDBDatabaseError; | |
37 using WebKit::WebIDBKey; | |
38 | |
39 namespace content { | |
40 | |
41 IndexedDBDispatcherHost::IndexedDBDispatcherHost( | |
42 int ipc_process_id, | |
43 IndexedDBContextImpl* indexed_db_context) | |
44 : indexed_db_context_(indexed_db_context), | |
45 database_dispatcher_host_(new DatabaseDispatcherHost(this)), | |
46 cursor_dispatcher_host_(new CursorDispatcherHost(this)), | |
47 ipc_process_id_(ipc_process_id) { | |
48 DCHECK(indexed_db_context_.get()); | |
49 } | |
50 | |
51 IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {} | |
52 | |
53 void IndexedDBDispatcherHost::OnChannelClosing() { | |
54 BrowserMessageFilter::OnChannelClosing(); | |
55 | |
56 bool success = indexed_db_context_->TaskRunner()->PostTask( | |
57 FROM_HERE, | |
58 base::Bind(&IndexedDBDispatcherHost::ResetDispatcherHosts, this)); | |
59 | |
60 if (!success) | |
61 ResetDispatcherHosts(); | |
62 } | |
63 | |
64 void IndexedDBDispatcherHost::OnDestruct() const { | |
65 // The last reference to the dispatcher may be a posted task, which would | |
66 // be destructed on the IndexedDB thread. Without this override, that would | |
67 // take the dispatcher with it. Since the dispatcher may be keeping the | |
68 // IndexedDBContext alive, it might be destructed to on its own thread, | |
69 // which is not supported. Ensure destruction runs on the IO thread instead. | |
70 BrowserThread::DeleteOnIOThread::Destruct(this); | |
71 } | |
72 | |
73 void IndexedDBDispatcherHost::ResetDispatcherHosts() { | |
74 // It is important that the various *_dispatcher_host_ members are reset | |
75 // on the IndexedDB thread, since there might be incoming messages on that | |
76 // thread, and we must not reset the dispatcher hosts until after those | |
77 // messages are processed. | |
78 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
79 | |
80 // Note that we explicitly separate CloseAll() from destruction of the | |
81 // DatabaseDispatcherHost, since CloseAll() can invoke callbacks which need to | |
82 // be dispatched through database_dispatcher_host_. | |
83 database_dispatcher_host_->CloseAll(); | |
84 database_dispatcher_host_.reset(); | |
85 cursor_dispatcher_host_.reset(); | |
86 } | |
87 | |
88 base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage( | |
89 const IPC::Message& message) { | |
90 if (IPC_MESSAGE_CLASS(message) == IndexedDBMsgStart) | |
91 return indexed_db_context_->TaskRunner(); | |
92 return NULL; | |
93 } | |
94 | |
95 bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message, | |
96 bool* message_was_ok) { | |
97 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart) | |
98 return false; | |
99 | |
100 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
101 | |
102 bool handled = | |
103 database_dispatcher_host_->OnMessageReceived(message, message_was_ok) || | |
104 cursor_dispatcher_host_->OnMessageReceived(message, message_was_ok); | |
105 | |
106 if (!handled) { | |
107 handled = true; | |
108 IPC_BEGIN_MESSAGE_MAP_EX(IndexedDBDispatcherHost, message, *message_was_ok) | |
109 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryGetDatabaseNames, | |
110 OnIDBFactoryGetDatabaseNames) | |
111 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryOpen, OnIDBFactoryOpen) | |
112 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryDeleteDatabase, | |
113 OnIDBFactoryDeleteDatabase) | |
114 IPC_MESSAGE_UNHANDLED(handled = false) | |
115 IPC_END_MESSAGE_MAP() | |
116 } | |
117 return handled; | |
118 } | |
119 | |
120 int32 IndexedDBDispatcherHost::Add(WebIDBCursorImpl* idb_cursor) { | |
121 if (!cursor_dispatcher_host_) { | |
122 delete idb_cursor; | |
123 return 0; | |
124 } | |
125 return cursor_dispatcher_host_->map_.Add(idb_cursor); | |
126 } | |
127 | |
128 int32 IndexedDBDispatcherHost::Add(WebIDBDatabaseImpl* idb_database, | |
129 int32 ipc_thread_id, | |
130 const GURL& origin_url) { | |
131 if (!database_dispatcher_host_) { | |
132 delete idb_database; | |
133 return 0; | |
134 } | |
135 int32 ipc_database_id = database_dispatcher_host_->map_.Add(idb_database); | |
136 Context()->ConnectionOpened(origin_url, idb_database); | |
137 database_dispatcher_host_->database_url_map_[ipc_database_id] = origin_url; | |
138 return ipc_database_id; | |
139 } | |
140 | |
141 void IndexedDBDispatcherHost::RegisterTransactionId(int64 host_transaction_id, | |
142 const GURL& url) { | |
143 if (!database_dispatcher_host_) | |
144 return; | |
145 database_dispatcher_host_->transaction_url_map_[host_transaction_id] = url; | |
146 } | |
147 | |
148 int64 IndexedDBDispatcherHost::HostTransactionId(int64 transaction_id) { | |
149 // Inject the renderer process id into the transaction id, to | |
150 // uniquely identify this transaction, and effectively bind it to | |
151 // the renderer that initiated it. The lower 32 bits of | |
152 // transaction_id are guaranteed to be unique within that renderer. | |
153 base::ProcessId pid = base::GetProcId(peer_handle()); | |
154 DCHECK(!(transaction_id >> 32)) << "Transaction ids can only be 32 bits"; | |
155 COMPILE_ASSERT(sizeof(base::ProcessId) <= sizeof(int32), | |
156 Process_ID_must_fit_in_32_bits); | |
157 | |
158 return transaction_id | (static_cast<uint64>(pid) << 32); | |
159 } | |
160 | |
161 int64 IndexedDBDispatcherHost::RendererTransactionId( | |
162 int64 host_transaction_id) { | |
163 DCHECK(host_transaction_id >> 32 == base::GetProcId(peer_handle())) | |
164 << "Invalid renderer target for transaction id"; | |
165 return host_transaction_id & 0xffffffff; | |
166 } | |
167 | |
168 WebIDBCursorImpl* IndexedDBDispatcherHost::GetCursorFromId( | |
169 int32 ipc_cursor_id) { | |
170 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
171 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id); | |
172 } | |
173 | |
174 ::IndexedDBDatabaseMetadata IndexedDBDispatcherHost::ConvertMetadata( | |
175 const content::IndexedDBDatabaseMetadata& web_metadata) { | |
176 ::IndexedDBDatabaseMetadata metadata; | |
177 metadata.id = web_metadata.id; | |
178 metadata.name = web_metadata.name; | |
179 metadata.version = web_metadata.version; | |
180 metadata.int_version = web_metadata.int_version; | |
181 metadata.max_object_store_id = web_metadata.max_object_store_id; | |
182 | |
183 for (content::IndexedDBDatabaseMetadata::ObjectStoreMap::const_iterator iter = | |
184 web_metadata.object_stores.begin(); | |
185 iter != web_metadata.object_stores.end(); | |
186 ++iter) { | |
187 | |
188 const content::IndexedDBObjectStoreMetadata& web_store_metadata = | |
189 iter->second; | |
190 ::IndexedDBObjectStoreMetadata idb_store_metadata; | |
191 idb_store_metadata.id = web_store_metadata.id; | |
192 idb_store_metadata.name = web_store_metadata.name; | |
193 idb_store_metadata.keyPath = web_store_metadata.key_path; | |
194 idb_store_metadata.autoIncrement = web_store_metadata.auto_increment; | |
195 idb_store_metadata.max_index_id = web_store_metadata.max_index_id; | |
196 | |
197 for (content::IndexedDBObjectStoreMetadata::IndexMap::const_iterator | |
198 index_iter = web_store_metadata.indexes.begin(); | |
199 index_iter != web_store_metadata.indexes.end(); | |
200 ++index_iter) { | |
201 const content::IndexedDBIndexMetadata& web_index_metadata = | |
202 index_iter->second; | |
203 ::IndexedDBIndexMetadata idb_index_metadata; | |
204 idb_index_metadata.id = web_index_metadata.id; | |
205 idb_index_metadata.name = web_index_metadata.name; | |
206 idb_index_metadata.keyPath = web_index_metadata.key_path; | |
207 idb_index_metadata.unique = web_index_metadata.unique; | |
208 idb_index_metadata.multiEntry = web_index_metadata.multi_entry; | |
209 idb_store_metadata.indexes.push_back(idb_index_metadata); | |
210 } | |
211 metadata.object_stores.push_back(idb_store_metadata); | |
212 } | |
213 return metadata; | |
214 } | |
215 | |
216 void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames( | |
217 const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& params) { | |
218 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
219 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | |
220 | |
221 Context()->GetIDBFactory()->getDatabaseNames( | |
222 new IndexedDBCallbacks<std::vector<string16> >( | |
223 this, params.ipc_thread_id, params.ipc_callbacks_id), | |
224 WebKit::WebString::fromUTF8(params.database_identifier), | |
225 indexed_db_path.AsUTF16Unsafe()); | |
226 } | |
227 | |
228 void IndexedDBDispatcherHost::OnIDBFactoryOpen( | |
229 const IndexedDBHostMsg_FactoryOpen_Params& params) { | |
230 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
231 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | |
232 | |
233 GURL origin_url = | |
234 webkit_database::GetOriginFromIdentifier(params.database_identifier); | |
235 | |
236 int64 host_transaction_id = HostTransactionId(params.transaction_id); | |
237 | |
238 // TODO(dgrogan): Don't let a non-existing database be opened (and therefore | |
239 // created) if this origin is already over quota. | |
240 Context()->GetIDBFactory() | |
241 ->open(params.name, | |
242 params.version, | |
243 host_transaction_id, | |
244 new IndexedDBCallbacksDatabase(this, | |
245 params.ipc_thread_id, | |
246 params.ipc_callbacks_id, | |
247 params.ipc_database_callbacks_id, | |
248 host_transaction_id, | |
249 origin_url), | |
250 new IndexedDBDatabaseCallbacks( | |
251 this, params.ipc_thread_id, params.ipc_database_callbacks_id), | |
252 WebKit::WebString::fromUTF8(params.database_identifier), | |
253 indexed_db_path.AsUTF16Unsafe()); | |
254 } | |
255 | |
256 void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase( | |
257 const IndexedDBHostMsg_FactoryDeleteDatabase_Params& params) { | |
258 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
259 base::FilePath indexed_db_path = indexed_db_context_->data_path(); | |
260 | |
261 Context()->GetIDBFactory() | |
262 ->deleteDatabase(params.name, | |
263 new IndexedDBCallbacks<std::vector<char> >( | |
264 this, params.ipc_thread_id, params.ipc_callbacks_id), | |
265 WebKit::WebString::fromUTF8(params.database_identifier), | |
266 indexed_db_path.AsUTF16Unsafe()); | |
267 } | |
268 | |
269 void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id, | |
270 bool committed) { | |
271 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
272 TransactionIDToURLMap& transaction_url_map = | |
273 database_dispatcher_host_->transaction_url_map_; | |
274 TransactionIDToSizeMap& transaction_size_map = | |
275 database_dispatcher_host_->transaction_size_map_; | |
276 TransactionIDToDatabaseIDMap& transaction_database_map = | |
277 database_dispatcher_host_->transaction_database_map_; | |
278 if (committed) | |
279 Context()->TransactionComplete(transaction_url_map[host_transaction_id]); | |
280 // It's unclear if std::map::erase(key) has defined behavior if the | |
281 // key is not found. | |
282 // TODO(alecflett): Remove if it is proven that it is safe. | |
283 if (transaction_url_map.find(host_transaction_id) != | |
284 transaction_url_map.end()) | |
285 transaction_url_map.erase(host_transaction_id); | |
286 if (transaction_size_map.find(host_transaction_id) != | |
287 transaction_size_map.end()) | |
288 transaction_size_map.erase(host_transaction_id); | |
289 if (transaction_database_map.find(host_transaction_id) != | |
290 transaction_database_map.end()) | |
291 transaction_database_map.erase(host_transaction_id); | |
292 } | |
293 | |
294 ////////////////////////////////////////////////////////////////////// | |
295 // Helper templates. | |
296 // | |
297 | |
298 template <typename ObjectType> | |
299 ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess( | |
300 IDMap<ObjectType, IDMapOwnPointer>* map, | |
301 int32 ipc_return_object_id) { | |
302 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
303 ObjectType* return_object = map->Lookup(ipc_return_object_id); | |
304 if (!return_object) { | |
305 NOTREACHED() << "Uh oh, couldn't find object with id " | |
306 << ipc_return_object_id; | |
307 RecordAction(UserMetricsAction("BadMessageTerminate_IDBMF")); | |
308 BadMessageReceived(); | |
309 } | |
310 return return_object; | |
311 } | |
312 | |
313 template <typename ObjectType> | |
314 void IndexedDBDispatcherHost::DestroyObject( | |
315 IDMap<ObjectType, IDMapOwnPointer>* map, | |
316 int32 ipc_object_id) { | |
317 GetOrTerminateProcess(map, ipc_object_id); | |
318 map->Remove(ipc_object_id); | |
319 } | |
320 | |
321 ////////////////////////////////////////////////////////////////////// | |
322 // IndexedDBDispatcherHost::DatabaseDispatcherHost | |
323 // | |
324 | |
325 IndexedDBDispatcherHost::DatabaseDispatcherHost::DatabaseDispatcherHost( | |
326 IndexedDBDispatcherHost* parent) | |
327 : parent_(parent) { | |
328 map_.set_check_on_null_data(true); | |
329 } | |
330 | |
331 IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() { | |
332 // TODO(alecflett): uncomment these when we find the source of these leaks. | |
333 // DCHECK(transaction_size_map_.empty()); | |
334 // DCHECK(transaction_url_map_.empty()); | |
335 } | |
336 | |
337 void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() { | |
338 DCHECK( | |
339 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
340 // Abort outstanding transactions started by connections in the associated | |
341 // front-end to unblock later transactions. This should only occur on unclean | |
342 // (crash) or abrupt (process-kill) shutdowns. | |
343 for (TransactionIDToDatabaseIDMap::iterator iter = | |
344 transaction_database_map_.begin(); | |
345 iter != transaction_database_map_.end();) { | |
346 int64 transaction_id = iter->first; | |
347 int32 ipc_database_id = iter->second; | |
348 ++iter; | |
349 WebIDBDatabaseImpl* database = map_.Lookup(ipc_database_id); | |
350 if (database) { | |
351 database->abort( | |
352 transaction_id, | |
353 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError)); | |
354 } | |
355 } | |
356 DCHECK(transaction_database_map_.empty()); | |
357 | |
358 for (WebIDBObjectIDToURLMap::iterator iter = database_url_map_.begin(); | |
359 iter != database_url_map_.end(); | |
360 iter++) { | |
361 WebIDBDatabaseImpl* database = map_.Lookup(iter->first); | |
362 if (database) { | |
363 database->close(); | |
364 parent_->Context()->ConnectionClosed(iter->second, database); | |
365 } | |
366 } | |
367 } | |
368 | |
369 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived( | |
370 const IPC::Message& message, | |
371 bool* msg_is_ok) { | |
372 DCHECK( | |
373 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
374 bool handled = true; | |
375 IPC_BEGIN_MESSAGE_MAP_EX( | |
376 IndexedDBDispatcherHost::DatabaseDispatcherHost, message, *msg_is_ok) | |
377 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore, | |
378 OnCreateObjectStore) | |
379 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore, | |
380 OnDeleteObjectStore) | |
381 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction, | |
382 OnCreateTransaction) | |
383 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClose, OnClose) | |
384 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed) | |
385 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGet, OnGet) | |
386 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPut) | |
387 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexKeys, OnSetIndexKeys) | |
388 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexesReady, | |
389 OnSetIndexesReady) | |
390 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseOpenCursor, OnOpenCursor) | |
391 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCount, OnCount) | |
392 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteRange, OnDeleteRange) | |
393 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClear, OnClear) | |
394 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateIndex, OnCreateIndex) | |
395 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteIndex, OnDeleteIndex) | |
396 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseAbort, OnAbort) | |
397 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCommit, OnCommit) | |
398 IPC_MESSAGE_UNHANDLED(handled = false) | |
399 IPC_END_MESSAGE_MAP() | |
400 return handled; | |
401 } | |
402 | |
403 void IndexedDBDispatcherHost::DatabaseDispatcherHost::Send( | |
404 IPC::Message* message) { | |
405 parent_->Send(message); | |
406 } | |
407 | |
408 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore( | |
409 const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params) { | |
410 DCHECK( | |
411 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
412 WebIDBDatabaseImpl* database = | |
413 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
414 if (!database) | |
415 return; | |
416 | |
417 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
418 database->createObjectStore(host_transaction_id, | |
419 params.object_store_id, | |
420 params.name, | |
421 params.key_path, | |
422 params.auto_increment); | |
423 if (parent_->Context()->IsOverQuota( | |
424 database_url_map_[params.ipc_database_id])) { | |
425 database->abort( | |
426 host_transaction_id, | |
427 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError)); | |
428 } | |
429 } | |
430 | |
431 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteObjectStore( | |
432 int32 ipc_database_id, | |
433 int64 transaction_id, | |
434 int64 object_store_id) { | |
435 DCHECK( | |
436 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
437 WebIDBDatabaseImpl* database = | |
438 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
439 if (!database) | |
440 return; | |
441 | |
442 database->deleteObjectStore(parent_->HostTransactionId(transaction_id), | |
443 object_store_id); | |
444 } | |
445 | |
446 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction( | |
447 const IndexedDBHostMsg_DatabaseCreateTransaction_Params& params) { | |
448 DCHECK( | |
449 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
450 WebIDBDatabaseImpl* database = | |
451 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
452 if (!database) | |
453 return; | |
454 | |
455 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
456 | |
457 database->createTransaction( | |
458 host_transaction_id, | |
459 new IndexedDBDatabaseCallbacks( | |
460 parent_, params.ipc_thread_id, params.ipc_database_callbacks_id), | |
461 params.object_store_ids, | |
462 params.mode); | |
463 transaction_database_map_[host_transaction_id] = params.ipc_database_id; | |
464 parent_->RegisterTransactionId(host_transaction_id, | |
465 database_url_map_[params.ipc_database_id]); | |
466 } | |
467 | |
468 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose( | |
469 int32 ipc_database_id) { | |
470 DCHECK( | |
471 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
472 WebIDBDatabaseImpl* database = | |
473 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
474 if (!database) | |
475 return; | |
476 database->close(); | |
477 } | |
478 | |
479 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed( | |
480 int32 ipc_object_id) { | |
481 DCHECK( | |
482 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
483 WebIDBDatabaseImpl* database = map_.Lookup(ipc_object_id); | |
484 parent_->Context() | |
485 ->ConnectionClosed(database_url_map_[ipc_object_id], database); | |
486 database_url_map_.erase(ipc_object_id); | |
487 parent_->DestroyObject(&map_, ipc_object_id); | |
488 } | |
489 | |
490 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet( | |
491 const IndexedDBHostMsg_DatabaseGet_Params& params) { | |
492 DCHECK( | |
493 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
494 WebIDBDatabaseImpl* database = | |
495 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
496 if (!database) | |
497 return; | |
498 | |
499 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
500 new IndexedDBCallbacks<std::vector<char> >( | |
501 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
502 database->get(parent_->HostTransactionId(params.transaction_id), | |
503 params.object_store_id, | |
504 params.index_id, | |
505 params.key_range, | |
506 params.key_only, | |
507 callbacks.release()); | |
508 } | |
509 | |
510 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut( | |
511 const IndexedDBHostMsg_DatabasePut_Params& params) { | |
512 DCHECK( | |
513 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
514 | |
515 WebIDBDatabaseImpl* database = | |
516 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
517 if (!database) | |
518 return; | |
519 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
520 new IndexedDBCallbacks<IndexedDBKey>( | |
521 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
522 | |
523 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
524 // TODO(alecflett): Avoid a copy here. | |
525 std::vector<char> value_copy = params.value; | |
526 database->put(host_transaction_id, | |
527 params.object_store_id, | |
528 &value_copy, | |
529 params.key, | |
530 params.put_mode, | |
531 callbacks.release(), | |
532 params.index_ids, | |
533 params.index_keys); | |
534 TransactionIDToSizeMap* map = | |
535 &parent_->database_dispatcher_host_->transaction_size_map_; | |
536 // Size can't be big enough to overflow because it represents the | |
537 // actual bytes passed through IPC. | |
538 (*map)[host_transaction_id] += params.value.size(); | |
539 } | |
540 | |
541 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexKeys( | |
542 const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params) { | |
543 DCHECK( | |
544 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
545 WebIDBDatabaseImpl* database = | |
546 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
547 if (!database) | |
548 return; | |
549 | |
550 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
551 if (params.index_ids.size() != params.index_keys.size()) { | |
552 database->abort( | |
553 host_transaction_id, | |
554 WebIDBDatabaseError( | |
555 WebKit::WebIDBDatabaseExceptionUnknownError, | |
556 "Malformed IPC message: index_ids.size() != index_keys.size()")); | |
557 return; | |
558 } | |
559 | |
560 database->setIndexKeys(host_transaction_id, | |
561 params.object_store_id, | |
562 params.primary_key, | |
563 params.index_ids, | |
564 params.index_keys); | |
565 } | |
566 | |
567 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexesReady( | |
568 int32 ipc_database_id, | |
569 int64 transaction_id, | |
570 int64 object_store_id, | |
571 const std::vector<int64>& index_ids) { | |
572 DCHECK( | |
573 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
574 WebIDBDatabaseImpl* database = | |
575 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
576 if (!database) | |
577 return; | |
578 | |
579 database->setIndexesReady( | |
580 parent_->HostTransactionId(transaction_id), object_store_id, index_ids); | |
581 } | |
582 | |
583 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor( | |
584 const IndexedDBHostMsg_DatabaseOpenCursor_Params& params) { | |
585 DCHECK( | |
586 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
587 WebIDBDatabaseImpl* database = | |
588 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
589 if (!database) | |
590 return; | |
591 | |
592 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
593 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
594 parent_, params.ipc_thread_id, params.ipc_callbacks_id, -1)); | |
595 database->openCursor(parent_->HostTransactionId(params.transaction_id), | |
596 params.object_store_id, | |
597 params.index_id, | |
598 params.key_range, | |
599 params.direction, | |
600 params.key_only, | |
601 params.task_type, | |
602 callbacks.release()); | |
603 } | |
604 | |
605 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCount( | |
606 const IndexedDBHostMsg_DatabaseCount_Params& params) { | |
607 DCHECK( | |
608 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
609 WebIDBDatabaseImpl* database = | |
610 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
611 if (!database) | |
612 return; | |
613 | |
614 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
615 new IndexedDBCallbacks<std::vector<char> >( | |
616 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
617 database->count(parent_->HostTransactionId(params.transaction_id), | |
618 params.object_store_id, | |
619 params.index_id, | |
620 params.key_range, | |
621 callbacks.release()); | |
622 } | |
623 | |
624 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteRange( | |
625 const IndexedDBHostMsg_DatabaseDeleteRange_Params& params) { | |
626 DCHECK( | |
627 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
628 WebIDBDatabaseImpl* database = | |
629 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
630 if (!database) | |
631 return; | |
632 | |
633 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
634 new IndexedDBCallbacks<std::vector<char> >( | |
635 parent_, params.ipc_thread_id, params.ipc_callbacks_id)); | |
636 database->deleteRange(parent_->HostTransactionId(params.transaction_id), | |
637 params.object_store_id, | |
638 params.key_range, | |
639 callbacks.release()); | |
640 } | |
641 | |
642 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClear( | |
643 int32 ipc_thread_id, | |
644 int32 ipc_callbacks_id, | |
645 int32 ipc_database_id, | |
646 int64 transaction_id, | |
647 int64 object_store_id) { | |
648 DCHECK( | |
649 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
650 WebIDBDatabaseImpl* database = | |
651 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
652 if (!database) | |
653 return; | |
654 | |
655 scoped_ptr<IndexedDBCallbacksBase> callbacks( | |
656 new IndexedDBCallbacks<std::vector<char> >( | |
657 parent_, ipc_thread_id, ipc_callbacks_id)); | |
658 | |
659 database->clear(parent_->HostTransactionId(transaction_id), | |
660 object_store_id, | |
661 callbacks.release()); | |
662 } | |
663 | |
664 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnAbort( | |
665 int32 ipc_database_id, | |
666 int64 transaction_id) { | |
667 DCHECK( | |
668 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
669 WebIDBDatabaseImpl* database = | |
670 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
671 if (!database) | |
672 return; | |
673 | |
674 database->abort(parent_->HostTransactionId(transaction_id)); | |
675 } | |
676 | |
677 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCommit( | |
678 int32 ipc_database_id, | |
679 int64 transaction_id) { | |
680 DCHECK( | |
681 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
682 WebIDBDatabaseImpl* database = | |
683 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
684 if (!database) | |
685 return; | |
686 | |
687 int64 host_transaction_id = parent_->HostTransactionId(transaction_id); | |
688 int64 transaction_size = transaction_size_map_[host_transaction_id]; | |
689 if (transaction_size && | |
690 parent_->Context()->WouldBeOverQuota( | |
691 transaction_url_map_[host_transaction_id], transaction_size)) { | |
692 database->abort( | |
693 host_transaction_id, | |
694 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError)); | |
695 return; | |
696 } | |
697 | |
698 database->commit(host_transaction_id); | |
699 } | |
700 | |
701 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex( | |
702 const IndexedDBHostMsg_DatabaseCreateIndex_Params& params) { | |
703 DCHECK( | |
704 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
705 WebIDBDatabaseImpl* database = | |
706 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id); | |
707 if (!database) | |
708 return; | |
709 | |
710 int64 host_transaction_id = parent_->HostTransactionId(params.transaction_id); | |
711 database->createIndex(host_transaction_id, | |
712 params.object_store_id, | |
713 params.index_id, | |
714 params.name, | |
715 params.key_path, | |
716 params.unique, | |
717 params.multi_entry); | |
718 if (parent_->Context()->IsOverQuota( | |
719 database_url_map_[params.ipc_database_id])) { | |
720 database->abort( | |
721 host_transaction_id, | |
722 WebIDBDatabaseError(WebKit::WebIDBDatabaseExceptionQuotaError)); | |
723 } | |
724 } | |
725 | |
726 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteIndex( | |
727 int32 ipc_database_id, | |
728 int64 transaction_id, | |
729 int64 object_store_id, | |
730 int64 index_id) { | |
731 DCHECK( | |
732 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
733 WebIDBDatabaseImpl* database = | |
734 parent_->GetOrTerminateProcess(&map_, ipc_database_id); | |
735 if (!database) | |
736 return; | |
737 | |
738 database->deleteIndex( | |
739 parent_->HostTransactionId(transaction_id), object_store_id, index_id); | |
740 } | |
741 | |
742 ////////////////////////////////////////////////////////////////////// | |
743 // IndexedDBDispatcherHost::CursorDispatcherHost | |
744 // | |
745 | |
746 IndexedDBDispatcherHost::CursorDispatcherHost::CursorDispatcherHost( | |
747 IndexedDBDispatcherHost* parent) | |
748 : parent_(parent) { | |
749 map_.set_check_on_null_data(true); | |
750 } | |
751 | |
752 IndexedDBDispatcherHost::CursorDispatcherHost::~CursorDispatcherHost() {} | |
753 | |
754 bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived( | |
755 const IPC::Message& message, | |
756 bool* msg_is_ok) { | |
757 DCHECK( | |
758 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
759 | |
760 bool handled = true; | |
761 IPC_BEGIN_MESSAGE_MAP_EX( | |
762 IndexedDBDispatcherHost::CursorDispatcherHost, message, *msg_is_ok) | |
763 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorAdvance, OnAdvance) | |
764 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorContinue, OnContinue) | |
765 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetch, OnPrefetch) | |
766 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetchReset, OnPrefetchReset) | |
767 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDestroyed, OnDestroyed) | |
768 IPC_MESSAGE_UNHANDLED(handled = false) | |
769 IPC_END_MESSAGE_MAP() | |
770 return handled; | |
771 } | |
772 | |
773 void IndexedDBDispatcherHost::CursorDispatcherHost::Send( | |
774 IPC::Message* message) { | |
775 parent_->Send(message); | |
776 } | |
777 | |
778 void IndexedDBDispatcherHost::CursorDispatcherHost::OnAdvance( | |
779 int32 ipc_cursor_id, | |
780 int32 ipc_thread_id, | |
781 int32 ipc_callbacks_id, | |
782 unsigned long count) { | |
783 DCHECK( | |
784 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
785 WebIDBCursorImpl* idb_cursor = | |
786 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
787 if (!idb_cursor) | |
788 return; | |
789 | |
790 idb_cursor->advance( | |
791 count, | |
792 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
793 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
794 } | |
795 | |
796 void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue( | |
797 int32 ipc_cursor_id, | |
798 int32 ipc_thread_id, | |
799 int32 ipc_callbacks_id, | |
800 const IndexedDBKey& key) { | |
801 DCHECK( | |
802 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
803 WebIDBCursorImpl* idb_cursor = | |
804 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
805 if (!idb_cursor) | |
806 return; | |
807 | |
808 idb_cursor->continueFunction( | |
809 key, | |
810 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
811 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
812 } | |
813 | |
814 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch( | |
815 int32 ipc_cursor_id, | |
816 int32 ipc_thread_id, | |
817 int32 ipc_callbacks_id, | |
818 int n) { | |
819 DCHECK( | |
820 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
821 WebIDBCursorImpl* idb_cursor = | |
822 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
823 if (!idb_cursor) | |
824 return; | |
825 | |
826 idb_cursor->prefetchContinue( | |
827 n, | |
828 new IndexedDBCallbacks<WebIDBCursorImpl>( | |
829 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id)); | |
830 } | |
831 | |
832 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset( | |
833 int32 ipc_cursor_id, | |
834 int used_prefetches, | |
835 int unused_prefetches) { | |
836 DCHECK( | |
837 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
838 WebIDBCursorImpl* idb_cursor = | |
839 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id); | |
840 if (!idb_cursor) | |
841 return; | |
842 | |
843 idb_cursor->prefetchReset(used_prefetches, unused_prefetches); | |
844 } | |
845 | |
846 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed( | |
847 int32 ipc_object_id) { | |
848 DCHECK( | |
849 parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); | |
850 parent_->DestroyObject(&map_, ipc_object_id); | |
851 } | |
852 | |
853 } // namespace content | |
OLD | NEW |