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

Side by Side Diff: content/browser/indexed_db/indexed_db_dispatcher_host.cc

Issue 1963293002: Replacing Indexed DB Chromium IPC with Mojo Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactoring after Passing URLRequestContextGetter. Created 4 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/indexed_db/indexed_db_dispatcher_host.h"
6
7 #include <stddef.h>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/guid.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/process/process.h"
16 #include "base/stl_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "content/browser/bad_message.h"
19 #include "content/browser/child_process_security_policy_impl.h"
20 #include "content/browser/indexed_db/indexed_db_callbacks.h"
21 #include "content/browser/indexed_db/indexed_db_connection.h"
22 #include "content/browser/indexed_db/indexed_db_context_impl.h"
23 #include "content/browser/indexed_db/indexed_db_cursor.h"
24 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
25 #include "content/browser/indexed_db/indexed_db_metadata.h"
26 #include "content/browser/indexed_db/indexed_db_observation.h"
27 #include "content/browser/indexed_db/indexed_db_observer_changes.h"
28 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
29 #include "content/browser/indexed_db/indexed_db_value.h"
30 #include "content/browser/renderer_host/render_message_filter.h"
31 #include "content/common/indexed_db/indexed_db_messages.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/user_metrics.h"
34 #include "content/public/common/content_switches.h"
35 #include "content/public/common/result_codes.h"
36 #include "storage/browser/blob/blob_data_builder.h"
37 #include "storage/browser/blob/blob_storage_context.h"
38 #include "storage/browser/database/database_util.h"
39 #include "storage/browser/quota/quota_manager_proxy.h"
40 #include "storage/common/database/database_identifier.h"
41 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc eption.h"
42 #include "url/origin.h"
43
44 using storage::DatabaseUtil;
45 using blink::WebIDBKey;
46
47 namespace content {
48
49 namespace {
50
51 bool IsValidOrigin(const url::Origin& origin) {
52 return !origin.unique();
53 }
54
55 } // namespace
56
57 IndexedDBDispatcherHost::IndexedDBDispatcherHost(
58 int ipc_process_id,
59 net::URLRequestContextGetter* request_context_getter,
60 IndexedDBContextImpl* indexed_db_context,
61 ChromeBlobStorageContext* blob_storage_context)
62 : BrowserMessageFilter(IndexedDBMsgStart),
63 request_context_getter_(request_context_getter),
64 indexed_db_context_(indexed_db_context),
65 blob_storage_context_(blob_storage_context),
66 database_dispatcher_host_(base::MakeUnique<DatabaseDispatcherHost>(this)),
67 cursor_dispatcher_host_(base::MakeUnique<CursorDispatcherHost>(this)),
68 ipc_process_id_(ipc_process_id) {
69 DCHECK(indexed_db_context_.get());
70 }
71
72 IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {}
73
74 void IndexedDBDispatcherHost::OnChannelClosing() {
75 bool success = indexed_db_context_->TaskRunner()->PostTask(
76 FROM_HERE,
77 base::Bind(&IndexedDBDispatcherHost::ResetDispatcherHosts, this));
78
79 if (!success)
80 ResetDispatcherHosts();
81 }
82
83 void IndexedDBDispatcherHost::OnDestruct() const {
84 // The last reference to the dispatcher may be a posted task, which would
85 // be destructed on the IndexedDB thread. Without this override, that would
86 // take the dispatcher with it. Since the dispatcher may be keeping the
87 // IndexedDBContext alive, it might be destructed to on its own thread,
88 // which is not supported. Ensure destruction runs on the IO thread instead.
89 BrowserThread::DeleteOnIOThread::Destruct(this);
90 }
91
92 void IndexedDBDispatcherHost::ResetDispatcherHosts() {
93 // It is important that the various *_dispatcher_host_ members are reset
94 // on the IndexedDB thread, since there might be incoming messages on that
95 // thread, and we must not reset the dispatcher hosts until after those
96 // messages are processed.
97 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
98
99 // Note that we explicitly separate CloseAll() from destruction of the
100 // DatabaseDispatcherHost, since CloseAll() can invoke callbacks which need to
101 // be dispatched through database_dispatcher_host_.
102 database_dispatcher_host_->CloseAll();
103 database_dispatcher_host_.reset();
104 cursor_dispatcher_host_.reset();
105 }
106
107 base::TaskRunner* IndexedDBDispatcherHost::OverrideTaskRunnerForMessage(
108 const IPC::Message& message) {
109 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart)
110 return NULL;
111
112 switch (message.type()) {
113 case IndexedDBHostMsg_DatabasePut::ID:
114 case IndexedDBHostMsg_AckReceivedBlobs::ID:
115 return NULL;
116 default:
117 return indexed_db_context_->TaskRunner();
118 }
119 }
120
121 bool IndexedDBDispatcherHost::OnMessageReceived(const IPC::Message& message) {
122 if (IPC_MESSAGE_CLASS(message) != IndexedDBMsgStart)
123 return false;
124
125 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread() ||
126 (message.type() == IndexedDBHostMsg_DatabasePut::ID ||
127 message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID));
128
129 bool handled = database_dispatcher_host_->OnMessageReceived(message) ||
130 cursor_dispatcher_host_->OnMessageReceived(message);
131
132 if (!handled) {
133 handled = true;
134 IPC_BEGIN_MESSAGE_MAP(IndexedDBDispatcherHost, message)
135 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryGetDatabaseNames,
136 OnIDBFactoryGetDatabaseNames)
137 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryOpen, OnIDBFactoryOpen)
138 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_FactoryDeleteDatabase,
139 OnIDBFactoryDeleteDatabase)
140 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_AckReceivedBlobs, OnAckReceivedBlobs)
141 IPC_MESSAGE_UNHANDLED(handled = false)
142 IPC_END_MESSAGE_MAP()
143 }
144 return handled;
145 }
146
147 int32_t IndexedDBDispatcherHost::Add(IndexedDBCursor* cursor) {
148 if (!cursor_dispatcher_host_) {
149 return 0;
150 }
151 return cursor_dispatcher_host_->map_.Add(cursor);
152 }
153
154 int32_t IndexedDBDispatcherHost::Add(IndexedDBConnection* connection,
155 int32_t ipc_thread_id,
156 const url::Origin& origin) {
157 if (!database_dispatcher_host_) {
158 connection->Close();
159 delete connection;
160 return -1;
161 }
162 int32_t ipc_database_id = database_dispatcher_host_->map_.Add(connection);
163 connection->set_id(ipc_database_id);
164 context()->ConnectionOpened(origin, connection);
165 database_dispatcher_host_->database_origin_map_[ipc_database_id] = origin;
166 return ipc_database_id;
167 }
168
169 void IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id,
170 const url::Origin& origin) {
171 if (!database_dispatcher_host_)
172 return;
173 database_dispatcher_host_->transaction_size_map_[host_transaction_id] = 0;
174 database_dispatcher_host_->transaction_origin_map_[host_transaction_id] =
175 origin;
176 }
177
178 int64_t IndexedDBDispatcherHost::HostTransactionId(int64_t transaction_id) {
179 // Inject the renderer process id into the transaction id, to
180 // uniquely identify this transaction, and effectively bind it to
181 // the renderer that initiated it. The lower 32 bits of
182 // transaction_id are guaranteed to be unique within that renderer.
183 base::ProcessId pid = peer_pid();
184 DCHECK(!(transaction_id >> 32)) << "Transaction ids can only be 32 bits";
185 static_assert(sizeof(base::ProcessId) <= sizeof(int32_t),
186 "Process ID must fit in 32 bits");
187
188 return transaction_id | (static_cast<uint64_t>(pid) << 32);
189 }
190
191 int64_t IndexedDBDispatcherHost::RendererTransactionId(
192 int64_t host_transaction_id) {
193 DCHECK(host_transaction_id >> 32 == peer_pid())
194 << "Invalid renderer target for transaction id";
195 return host_transaction_id & 0xffffffff;
196 }
197
198 // static
199 uint32_t IndexedDBDispatcherHost::TransactionIdToRendererTransactionId(
200 int64_t host_transaction_id) {
201 return host_transaction_id & 0xffffffff;
202 }
203
204 // static
205 uint32_t IndexedDBDispatcherHost::TransactionIdToProcessId(
206 int64_t host_transaction_id) {
207 return (host_transaction_id >> 32) & 0xffffffff;
208 }
209
210 std::string IndexedDBDispatcherHost::HoldBlobData(
211 const IndexedDBBlobInfo& blob_info) {
212 DCHECK_CURRENTLY_ON(BrowserThread::IO);
213 std::string uuid = blob_info.uuid();
214 storage::BlobStorageContext* context = blob_storage_context_->context();
215 std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
216 if (uuid.empty()) {
217 uuid = base::GenerateGUID();
218 storage::BlobDataBuilder blob_data_builder(uuid);
219 blob_data_builder.set_content_type(base::UTF16ToUTF8(blob_info.type()));
220 blob_data_builder.AppendFile(blob_info.file_path(), 0, blob_info.size(),
221 blob_info.last_modified());
222 blob_data_handle = context->AddFinishedBlob(&blob_data_builder);
223 } else {
224 auto iter = blob_data_handle_map_.find(uuid);
225 if (iter != blob_data_handle_map_.end()) {
226 iter->second.second += 1;
227 return uuid;
228 }
229 blob_data_handle = context->GetBlobDataFromUUID(uuid);
230 }
231
232 DCHECK(!base::ContainsKey(blob_data_handle_map_, uuid));
233 blob_data_handle_map_[uuid] = std::make_pair(std::move(blob_data_handle), 1);
234 return uuid;
235 }
236
237 void IndexedDBDispatcherHost::DropBlobData(const std::string& uuid) {
238 DCHECK_CURRENTLY_ON(BrowserThread::IO);
239 const auto& iter = blob_data_handle_map_.find(uuid);
240 if (iter == blob_data_handle_map_.end()) {
241 DLOG(FATAL) << "Failed to find blob UUID in map:" << uuid;
242 return;
243 }
244
245 DCHECK_GE(iter->second.second, 1);
246 if (iter->second.second == 1)
247 blob_data_handle_map_.erase(iter);
248 else
249 --iter->second.second;
250 }
251
252 IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(
253 int32_t ipc_cursor_id) {
254 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
255 return cursor_dispatcher_host_->map_.Lookup(ipc_cursor_id);
256 }
257
258 ::IndexedDBDatabaseMetadata IndexedDBDispatcherHost::ConvertMetadata(
259 const content::IndexedDBDatabaseMetadata& web_metadata) {
260 ::IndexedDBDatabaseMetadata metadata;
261 metadata.id = web_metadata.id;
262 metadata.name = web_metadata.name;
263 metadata.version = web_metadata.version;
264 metadata.max_object_store_id = web_metadata.max_object_store_id;
265
266 for (const auto& iter : web_metadata.object_stores) {
267 const content::IndexedDBObjectStoreMetadata& web_store_metadata =
268 iter.second;
269 ::IndexedDBObjectStoreMetadata idb_store_metadata;
270 idb_store_metadata.id = web_store_metadata.id;
271 idb_store_metadata.name = web_store_metadata.name;
272 idb_store_metadata.key_path = web_store_metadata.key_path;
273 idb_store_metadata.auto_increment = web_store_metadata.auto_increment;
274 idb_store_metadata.max_index_id = web_store_metadata.max_index_id;
275
276 for (const auto& index_iter : web_store_metadata.indexes) {
277 const content::IndexedDBIndexMetadata& web_index_metadata =
278 index_iter.second;
279 ::IndexedDBIndexMetadata idb_index_metadata;
280 idb_index_metadata.id = web_index_metadata.id;
281 idb_index_metadata.name = web_index_metadata.name;
282 idb_index_metadata.key_path = web_index_metadata.key_path;
283 idb_index_metadata.unique = web_index_metadata.unique;
284 idb_index_metadata.multi_entry = web_index_metadata.multi_entry;
285 idb_store_metadata.indexes.push_back(idb_index_metadata);
286 }
287 metadata.object_stores.push_back(idb_store_metadata);
288 }
289 return metadata;
290 }
291
292 IndexedDBMsg_ObserverChanges IndexedDBDispatcherHost::ConvertObserverChanges(
293 std::unique_ptr<IndexedDBObserverChanges> changes) {
294 IndexedDBMsg_ObserverChanges idb_changes;
295 idb_changes.observation_index = changes->release_observation_indices_map();
296 for (const auto& observation : changes->release_observations())
297 idb_changes.observations.push_back(ConvertObservation(observation.get()));
298 return idb_changes;
299 }
300
301 IndexedDBMsg_Observation IndexedDBDispatcherHost::ConvertObservation(
302 const IndexedDBObservation* observation) {
303 // TODO(palakj): Modify function for indexed_db_value. Issue crbug.com/609934.
304 IndexedDBMsg_Observation idb_observation;
305 idb_observation.object_store_id = observation->object_store_id();
306 idb_observation.type = observation->type();
307 idb_observation.key_range = observation->key_range();
308 return idb_observation;
309 }
310
311 void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames(
312 const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& params) {
313 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
314
315 if (!IsValidOrigin(params.origin)) {
316 bad_message::ReceivedBadMessage(this, bad_message::IDBDH_INVALID_ORIGIN);
317 return;
318 }
319
320 base::FilePath indexed_db_path = indexed_db_context_->data_path();
321 context()->GetIDBFactory()->GetDatabaseNames(
322 new IndexedDBCallbacks(this, params.ipc_thread_id,
323 params.ipc_callbacks_id),
324 params.origin, indexed_db_path, request_context_getter_);
325 }
326
327 void IndexedDBDispatcherHost::OnIDBFactoryOpen(
328 const IndexedDBHostMsg_FactoryOpen_Params& params) {
329 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
330
331 if (!IsValidOrigin(params.origin)) {
332 bad_message::ReceivedBadMessage(this, bad_message::IDBDH_INVALID_ORIGIN);
333 return;
334 }
335
336 base::TimeTicks begin_time = base::TimeTicks::Now();
337 base::FilePath indexed_db_path = indexed_db_context_->data_path();
338
339 int64_t host_transaction_id = HostTransactionId(params.transaction_id);
340
341 // TODO(dgrogan): Don't let a non-existing database be opened (and therefore
342 // created) if this origin is already over quota.
343 scoped_refptr<IndexedDBCallbacks> callbacks = new IndexedDBCallbacks(
344 this, params.ipc_thread_id, params.ipc_callbacks_id,
345 params.ipc_database_callbacks_id, host_transaction_id, params.origin);
346 callbacks->SetConnectionOpenStartTime(begin_time);
347 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks =
348 new IndexedDBDatabaseCallbacks(
349 this, params.ipc_thread_id, params.ipc_database_callbacks_id);
350 std::unique_ptr<IndexedDBPendingConnection> connection =
351 base::MakeUnique<IndexedDBPendingConnection>(
352 callbacks, database_callbacks, ipc_process_id_, host_transaction_id,
353 params.version);
354 DCHECK(request_context_getter_);
355 context()->GetIDBFactory()->Open(params.name, std::move(connection),
356 request_context_getter_, params.origin,
357 indexed_db_path);
358 }
359
360 void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
361 const IndexedDBHostMsg_FactoryDeleteDatabase_Params& params) {
362 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
363
364 if (!IsValidOrigin(params.origin)) {
365 bad_message::ReceivedBadMessage(this, bad_message::IDBDH_INVALID_ORIGIN);
366 return;
367 }
368
369 base::FilePath indexed_db_path = indexed_db_context_->data_path();
370 DCHECK(request_context_getter_);
371 context()->GetIDBFactory()->DeleteDatabase(
372 params.name, request_context_getter_,
373 new IndexedDBCallbacks(this, params.ipc_thread_id,
374 params.ipc_callbacks_id),
375 params.origin, indexed_db_path);
376 }
377
378 // OnPutHelper exists only to allow us to hop threads while holding a reference
379 // to the IndexedDBDispatcherHost.
380 void IndexedDBDispatcherHost::OnPutHelper(
381 const IndexedDBHostMsg_DatabasePut_Params& params,
382 std::vector<storage::BlobDataHandle*> handles) {
383 database_dispatcher_host_->OnPut(params, handles);
384 }
385
386 void IndexedDBDispatcherHost::OnAckReceivedBlobs(
387 const std::vector<std::string>& uuids) {
388 DCHECK_CURRENTLY_ON(BrowserThread::IO);
389 for (const auto& uuid : uuids)
390 DropBlobData(uuid);
391 }
392
393 void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id,
394 bool committed) {
395 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
396 if (!database_dispatcher_host_)
397 return;
398 TransactionIDToOriginMap& transaction_origin_map =
399 database_dispatcher_host_->transaction_origin_map_;
400 TransactionIDToSizeMap& transaction_size_map =
401 database_dispatcher_host_->transaction_size_map_;
402 TransactionIDToDatabaseIDMap& transaction_database_map =
403 database_dispatcher_host_->transaction_database_map_;
404 if (committed)
405 context()->TransactionComplete(transaction_origin_map[host_transaction_id]);
406 transaction_origin_map.erase(host_transaction_id);
407 transaction_size_map.erase(host_transaction_id);
408 transaction_database_map.erase(host_transaction_id);
409 }
410
411 //////////////////////////////////////////////////////////////////////
412 // Helper templates.
413 //
414
415 template <typename ObjectType>
416 ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess(
417 IDMap<ObjectType, IDMapOwnPointer>* map,
418 int32_t ipc_return_object_id) {
419 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
420 ObjectType* return_object = map->Lookup(ipc_return_object_id);
421 if (!return_object) {
422 NOTREACHED() << "Uh oh, couldn't find object with id "
423 << ipc_return_object_id;
424 bad_message::ReceivedBadMessage(this, bad_message::IDBDH_GET_OR_TERMINATE);
425 }
426 return return_object;
427 }
428
429 template <typename ObjectType>
430 ObjectType* IndexedDBDispatcherHost::GetOrTerminateProcess(
431 RefIDMap<ObjectType>* map,
432 int32_t ipc_return_object_id) {
433 DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
434 ObjectType* return_object = map->Lookup(ipc_return_object_id);
435 if (!return_object) {
436 NOTREACHED() << "Uh oh, couldn't find object with id "
437 << ipc_return_object_id;
438 bad_message::ReceivedBadMessage(this, bad_message::IDBDH_GET_OR_TERMINATE);
439 }
440 return return_object;
441 }
442
443 template <typename MapType>
444 void IndexedDBDispatcherHost::DestroyObject(MapType* map,
445 int32_t ipc_object_id) {
446 GetOrTerminateProcess(map, ipc_object_id);
447 map->Remove(ipc_object_id);
448 }
449
450 //////////////////////////////////////////////////////////////////////
451 // IndexedDBDispatcherHost::DatabaseDispatcherHost
452 //
453
454 IndexedDBDispatcherHost::DatabaseDispatcherHost::DatabaseDispatcherHost(
455 IndexedDBDispatcherHost* parent)
456 : parent_(parent), weak_factory_(this) {
457 map_.set_check_on_null_data(true);
458 }
459
460 IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() {
461 // TODO(alecflett): uncomment these when we find the source of these leaks.
462 // DCHECK(transaction_size_map_.empty());
463 // DCHECK(transaction_origin_map_.empty());
464 }
465
466 void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
467 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
468 // Abort outstanding transactions started by connections in the associated
469 // front-end to unblock later transactions. This should only occur on unclean
470 // (crash) or abrupt (process-kill) shutdowns.
471 for (TransactionIDToDatabaseIDMap::iterator iter =
472 transaction_database_map_.begin();
473 iter != transaction_database_map_.end();) {
474 int64_t transaction_id = iter->first;
475 int32_t ipc_database_id = iter->second;
476 ++iter;
477 IndexedDBConnection* connection = map_.Lookup(ipc_database_id);
478 if (connection && connection->IsConnected()) {
479 connection->database()->Abort(
480 transaction_id,
481 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError));
482 }
483 }
484 DCHECK(transaction_database_map_.empty());
485
486 for (const auto& iter : database_origin_map_) {
487 IndexedDBConnection* connection = map_.Lookup(iter.first);
488 if (connection && connection->IsConnected()) {
489 connection->Close();
490 parent_->context()->ConnectionClosed(iter.second, connection);
491 }
492 }
493 }
494
495 bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
496 const IPC::Message& message) {
497 DCHECK((message.type() == IndexedDBHostMsg_DatabasePut::ID ||
498 message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID) ||
499 parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
500
501 bool handled = true;
502 IPC_BEGIN_MESSAGE_MAP(
503 IndexedDBDispatcherHost::DatabaseDispatcherHost, message)
504 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateObjectStore,
505 OnCreateObjectStore)
506 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteObjectStore,
507 OnDeleteObjectStore)
508 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction,
509 OnCreateTransaction)
510 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClose, OnClose)
511 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseVersionChangeIgnored,
512 OnVersionChangeIgnored)
513 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed)
514 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseObserve, OnObserve)
515 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseUnobserve, OnUnobserve)
516 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGet, OnGet)
517 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGetAll, OnGetAll)
518 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPutWrapper)
519 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexKeys, OnSetIndexKeys)
520 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseSetIndexesReady,
521 OnSetIndexesReady)
522 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseOpenCursor, OnOpenCursor)
523 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCount, OnCount)
524 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteRange, OnDeleteRange)
525 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClear, OnClear)
526 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateIndex, OnCreateIndex)
527 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDeleteIndex, OnDeleteIndex)
528 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseAbort, OnAbort)
529 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCommit, OnCommit)
530 IPC_MESSAGE_UNHANDLED(handled = false)
531 IPC_END_MESSAGE_MAP()
532
533 return handled;
534 }
535
536 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore(
537 const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params) {
538 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
539 IndexedDBConnection* connection =
540 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
541 if (!connection || !connection->IsConnected())
542 return;
543
544 int64_t host_transaction_id =
545 parent_->HostTransactionId(params.transaction_id);
546 connection->database()->CreateObjectStore(host_transaction_id,
547 params.object_store_id,
548 params.name,
549 params.key_path,
550 params.auto_increment);
551 }
552
553 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteObjectStore(
554 int32_t ipc_database_id,
555 int64_t transaction_id,
556 int64_t object_store_id) {
557 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
558 IndexedDBConnection* connection =
559 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
560 if (!connection || !connection->IsConnected())
561 return;
562
563 connection->database()->DeleteObjectStore(
564 parent_->HostTransactionId(transaction_id), object_store_id);
565 }
566
567 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction(
568 const IndexedDBHostMsg_DatabaseCreateTransaction_Params& params) {
569 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
570 IndexedDBConnection* connection =
571 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
572 if (!connection || !connection->IsConnected())
573 return;
574
575 int64_t host_transaction_id =
576 parent_->HostTransactionId(params.transaction_id);
577
578 if (base::ContainsKey(transaction_database_map_, host_transaction_id)) {
579 DLOG(ERROR) << "Duplicate host_transaction_id.";
580 return;
581 }
582
583 connection->database()->CreateTransaction(
584 host_transaction_id, connection, params.object_store_ids, params.mode);
585 transaction_database_map_[host_transaction_id] = params.ipc_database_id;
586 parent_->RegisterTransactionId(host_transaction_id,
587 database_origin_map_[params.ipc_database_id]);
588 }
589
590 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose(
591 int32_t ipc_database_id) {
592 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
593 IndexedDBConnection* connection =
594 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
595 if (!connection || !connection->IsConnected())
596 return;
597 connection->Close();
598 }
599
600 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnVersionChangeIgnored(
601 int32_t ipc_database_id) {
602 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
603 IndexedDBConnection* connection =
604 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
605 if (!connection || !connection->IsConnected())
606 return;
607 connection->VersionChangeIgnored();
608 }
609
610 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed(
611 int32_t ipc_object_id) {
612 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
613 IndexedDBConnection* connection =
614 parent_->GetOrTerminateProcess(&map_, ipc_object_id);
615 if (!connection)
616 return;
617 if (connection->IsConnected())
618 connection->Close();
619 parent_->context()->ConnectionClosed(database_origin_map_[ipc_object_id],
620 connection);
621 database_origin_map_.erase(ipc_object_id);
622 parent_->DestroyObject(&map_, ipc_object_id);
623 }
624
625 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnObserve(
626 const IndexedDBHostMsg_DatabaseObserve_Params& params) {
627 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
628 IndexedDBConnection* connection =
629 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
630 if (!connection || !connection->IsConnected())
631 return;
632 IndexedDBObserver::Options options(params.include_transaction,
633 params.no_records, params.values,
634 params.operation_types);
635 connection->database()->AddPendingObserver(
636 parent_->HostTransactionId(params.transaction_id), params.observer_id,
637 options);
638 }
639
640 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnUnobserve(
641 int32_t ipc_database_id,
642 const std::vector<int32_t>& observer_ids_to_remove) {
643 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
644 DCHECK(!observer_ids_to_remove.empty());
645 IndexedDBConnection* connection =
646 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
647 if (!connection || !connection->IsConnected())
648 return;
649 connection->RemoveObservers(observer_ids_to_remove);
650 }
651
652 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet(
653 const IndexedDBHostMsg_DatabaseGet_Params& params) {
654 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
655 IndexedDBConnection* connection =
656 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
657 if (!connection || !connection->IsConnected())
658 return;
659
660 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
661 parent_, params.ipc_thread_id, params.ipc_callbacks_id));
662 connection->database()->Get(
663 parent_->HostTransactionId(params.transaction_id), params.object_store_id,
664 params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
665 params.key_only, callbacks);
666 }
667
668 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGetAll(
669 const IndexedDBHostMsg_DatabaseGetAll_Params& params) {
670 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
671 IndexedDBConnection* connection =
672 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
673 if (!connection || !connection->IsConnected())
674 return;
675
676 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
677 parent_, params.ipc_thread_id, params.ipc_callbacks_id));
678 connection->database()->GetAll(
679 parent_->HostTransactionId(params.transaction_id), params.object_store_id,
680 params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
681 params.key_only, params.max_count, callbacks);
682 }
683
684 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPutWrapper(
685 const IndexedDBHostMsg_DatabasePut_Params& params) {
686 std::vector<storage::BlobDataHandle*> handles;
687 for (size_t i = 0; i < params.value.blob_or_file_info.size(); ++i) {
688 const IndexedDBMsg_BlobOrFileInfo& info = params.value.blob_or_file_info[i];
689 handles.push_back(parent_->blob_storage_context_->context()
690 ->GetBlobDataFromUUID(info.uuid)
691 .release());
692 }
693 parent_->context()->TaskRunner()->PostTask(
694 FROM_HERE, base::Bind(&IndexedDBDispatcherHost::OnPutHelper, parent_,
695 params, handles));
696 }
697
698 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
699 const IndexedDBHostMsg_DatabasePut_Params& params,
700 std::vector<storage::BlobDataHandle*> handles) {
701 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
702
703 ScopedVector<storage::BlobDataHandle> scoped_handles;
704 scoped_handles.swap(handles);
705
706 IndexedDBConnection* connection =
707 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
708 if (!connection || !connection->IsConnected())
709 return;
710 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
711 parent_, params.ipc_thread_id, params.ipc_callbacks_id));
712
713 int64_t host_transaction_id =
714 parent_->HostTransactionId(params.transaction_id);
715
716 std::vector<IndexedDBBlobInfo> blob_info(
717 params.value.blob_or_file_info.size());
718
719 ChildProcessSecurityPolicyImpl* policy =
720 ChildProcessSecurityPolicyImpl::GetInstance();
721
722 for (size_t i = 0; i < params.value.blob_or_file_info.size(); ++i) {
723 const IndexedDBMsg_BlobOrFileInfo& info = params.value.blob_or_file_info[i];
724 if (info.is_file) {
725 base::FilePath path;
726 if (!info.file_path.empty()) {
727 path = base::FilePath::FromUTF16Unsafe(info.file_path);
728 if (!policy->CanReadFile(parent_->ipc_process_id_, path)) {
729 bad_message::ReceivedBadMessage(parent_,
730 bad_message::IDBDH_CAN_READ_FILE);
731 return;
732 }
733 }
734 blob_info[i] =
735 IndexedDBBlobInfo(info.uuid, path, info.file_name, info.mime_type);
736 if (info.size != static_cast<uint64_t>(-1)) {
737 blob_info[i].set_last_modified(
738 base::Time::FromDoubleT(info.last_modified));
739 blob_info[i].set_size(info.size);
740 }
741 } else {
742 blob_info[i] = IndexedDBBlobInfo(info.uuid, info.mime_type, info.size);
743 }
744 }
745
746 // TODO(alecflett): Avoid a copy here.
747 IndexedDBValue value;
748 value.bits = params.value.bits;
749 value.blob_info.swap(blob_info);
750 connection->database()->Put(host_transaction_id, params.object_store_id,
751 &value, &scoped_handles,
752 base::MakeUnique<IndexedDBKey>(params.key),
753 params.put_mode, callbacks, params.index_keys);
754 // Size can't be big enough to overflow because it represents the
755 // actual bytes passed through IPC.
756 transaction_size_map_[host_transaction_id] += params.value.bits.size();
757 }
758
759 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexKeys(
760 const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params) {
761 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
762 IndexedDBConnection* connection =
763 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
764 if (!connection || !connection->IsConnected())
765 return;
766
767 int64_t host_transaction_id =
768 parent_->HostTransactionId(params.transaction_id);
769 connection->database()->SetIndexKeys(
770 host_transaction_id, params.object_store_id,
771 base::MakeUnique<IndexedDBKey>(params.primary_key), params.index_keys);
772 }
773
774 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexesReady(
775 int32_t ipc_database_id,
776 int64_t transaction_id,
777 int64_t object_store_id,
778 const std::vector<int64_t>& index_ids) {
779 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
780 IndexedDBConnection* connection =
781 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
782 if (!connection || !connection->IsConnected())
783 return;
784
785 connection->database()->SetIndexesReady(
786 parent_->HostTransactionId(transaction_id), object_store_id, index_ids);
787 }
788
789 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor(
790 const IndexedDBHostMsg_DatabaseOpenCursor_Params& params) {
791 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
792 IndexedDBConnection* connection =
793 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
794 if (!connection || !connection->IsConnected())
795 return;
796
797 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
798 parent_, params.ipc_thread_id, params.ipc_callbacks_id, -1));
799 connection->database()->OpenCursor(
800 parent_->HostTransactionId(params.transaction_id), params.object_store_id,
801 params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
802 params.direction, params.key_only, params.task_type, callbacks);
803 }
804
805 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCount(
806 const IndexedDBHostMsg_DatabaseCount_Params& params) {
807 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
808 IndexedDBConnection* connection =
809 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
810 if (!connection || !connection->IsConnected())
811 return;
812
813 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
814 parent_, params.ipc_thread_id, params.ipc_callbacks_id));
815 connection->database()->Count(
816 parent_->HostTransactionId(params.transaction_id), params.object_store_id,
817 params.index_id, base::MakeUnique<IndexedDBKeyRange>(params.key_range),
818 callbacks);
819 }
820
821 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteRange(
822 const IndexedDBHostMsg_DatabaseDeleteRange_Params& params) {
823 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
824 IndexedDBConnection* connection =
825 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
826 if (!connection || !connection->IsConnected())
827 return;
828
829 scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
830 parent_, params.ipc_thread_id, params.ipc_callbacks_id));
831 connection->database()->DeleteRange(
832 parent_->HostTransactionId(params.transaction_id), params.object_store_id,
833 base::MakeUnique<IndexedDBKeyRange>(params.key_range), callbacks);
834 }
835
836 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClear(
837 int32_t ipc_thread_id,
838 int32_t ipc_callbacks_id,
839 int32_t ipc_database_id,
840 int64_t transaction_id,
841 int64_t object_store_id) {
842 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
843 IndexedDBConnection* connection =
844 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
845 if (!connection || !connection->IsConnected())
846 return;
847
848 scoped_refptr<IndexedDBCallbacks> callbacks(
849 new IndexedDBCallbacks(parent_, ipc_thread_id, ipc_callbacks_id));
850
851 connection->database()->Clear(
852 parent_->HostTransactionId(transaction_id), object_store_id, callbacks);
853 }
854
855 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnAbort(
856 int32_t ipc_database_id,
857 int64_t transaction_id) {
858 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
859 IndexedDBConnection* connection =
860 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
861 if (!connection || !connection->IsConnected())
862 return;
863
864 connection->database()->Abort(parent_->HostTransactionId(transaction_id));
865 }
866
867 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCommit(
868 int32_t ipc_database_id,
869 int64_t transaction_id) {
870 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
871 IndexedDBConnection* connection =
872 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
873 if (!connection || !connection->IsConnected())
874 return;
875
876 int64_t host_transaction_id = parent_->HostTransactionId(transaction_id);
877 // May have been aborted by back end before front-end could request commit.
878 if (!base::ContainsKey(transaction_size_map_, host_transaction_id))
879 return;
880 int64_t transaction_size = transaction_size_map_[host_transaction_id];
881
882 // Always allow empty or delete-only transactions.
883 if (!transaction_size) {
884 connection->database()->Commit(host_transaction_id);
885 return;
886 }
887
888 parent_->context()->quota_manager_proxy()->GetUsageAndQuota(
889 parent_->context()->TaskRunner(),
890 GURL(transaction_origin_map_[host_transaction_id].Serialize()),
891 storage::kStorageTypeTemporary,
892 base::Bind(&IndexedDBDispatcherHost::DatabaseDispatcherHost::
893 OnGotUsageAndQuotaForCommit,
894 weak_factory_.GetWeakPtr(), ipc_database_id, transaction_id));
895 }
896
897 void IndexedDBDispatcherHost::DatabaseDispatcherHost::
898 OnGotUsageAndQuotaForCommit(int32_t ipc_database_id,
899 int64_t transaction_id,
900 storage::QuotaStatusCode status,
901 int64_t usage,
902 int64_t quota) {
903 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
904 IndexedDBConnection* connection = map_.Lookup(ipc_database_id);
905 // May have disconnected while quota check was pending.
906 if (!connection || !connection->IsConnected())
907 return;
908 int64_t host_transaction_id = parent_->HostTransactionId(transaction_id);
909 // May have aborted while quota check was pending.
910 if (!base::ContainsKey(transaction_size_map_, host_transaction_id))
911 return;
912 int64_t transaction_size = transaction_size_map_[host_transaction_id];
913
914 if (status == storage::kQuotaStatusOk &&
915 usage + transaction_size <= quota) {
916 connection->database()->Commit(host_transaction_id);
917 } else {
918 connection->database()->Abort(
919 host_transaction_id,
920 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
921 }
922 }
923
924 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex(
925 const IndexedDBHostMsg_DatabaseCreateIndex_Params& params) {
926 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
927 IndexedDBConnection* connection =
928 parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
929 if (!connection || !connection->IsConnected())
930 return;
931
932 int64_t host_transaction_id =
933 parent_->HostTransactionId(params.transaction_id);
934 connection->database()->CreateIndex(host_transaction_id,
935 params.object_store_id,
936 params.index_id,
937 params.name,
938 params.key_path,
939 params.unique,
940 params.multi_entry);
941 }
942
943 void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteIndex(
944 int32_t ipc_database_id,
945 int64_t transaction_id,
946 int64_t object_store_id,
947 int64_t index_id) {
948 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
949 IndexedDBConnection* connection =
950 parent_->GetOrTerminateProcess(&map_, ipc_database_id);
951 if (!connection || !connection->IsConnected())
952 return;
953
954 connection->database()->DeleteIndex(
955 parent_->HostTransactionId(transaction_id), object_store_id, index_id);
956 }
957
958 //////////////////////////////////////////////////////////////////////
959 // IndexedDBDispatcherHost::CursorDispatcherHost
960 //
961
962 IndexedDBDispatcherHost::CursorDispatcherHost::CursorDispatcherHost(
963 IndexedDBDispatcherHost* parent)
964 : parent_(parent) {
965 map_.set_check_on_null_data(true);
966 }
967
968 IndexedDBDispatcherHost::CursorDispatcherHost::~CursorDispatcherHost() {}
969
970 bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived(
971 const IPC::Message& message) {
972 bool handled = true;
973 IPC_BEGIN_MESSAGE_MAP(
974 IndexedDBDispatcherHost::CursorDispatcherHost, message)
975 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorAdvance, OnAdvance)
976 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorContinue, OnContinue)
977 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetch, OnPrefetch)
978 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetchReset, OnPrefetchReset)
979 IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDestroyed, OnDestroyed)
980 IPC_MESSAGE_UNHANDLED(handled = false)
981 IPC_END_MESSAGE_MAP()
982
983 DCHECK(!handled ||
984 parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
985
986 return handled;
987 }
988
989 void IndexedDBDispatcherHost::CursorDispatcherHost::OnAdvance(
990 int32_t ipc_cursor_id,
991 int32_t ipc_thread_id,
992 int32_t ipc_callbacks_id,
993 uint32_t count) {
994 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
995 IndexedDBCursor* idb_cursor =
996 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
997 if (!idb_cursor)
998 return;
999
1000 idb_cursor->Advance(
1001 count,
1002 new IndexedDBCallbacks(
1003 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id));
1004 }
1005
1006 void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue(
1007 int32_t ipc_cursor_id,
1008 int32_t ipc_thread_id,
1009 int32_t ipc_callbacks_id,
1010 const IndexedDBKey& key,
1011 const IndexedDBKey& primary_key) {
1012 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
1013 IndexedDBCursor* idb_cursor =
1014 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
1015 if (!idb_cursor)
1016 return;
1017
1018 idb_cursor->Continue(key.IsValid() ? base::MakeUnique<IndexedDBKey>(key)
1019 : std::unique_ptr<IndexedDBKey>(),
1020 primary_key.IsValid()
1021 ? base::MakeUnique<IndexedDBKey>(primary_key)
1022 : std::unique_ptr<IndexedDBKey>(),
1023 new IndexedDBCallbacks(parent_, ipc_thread_id,
1024 ipc_callbacks_id, ipc_cursor_id));
1025 }
1026
1027 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch(
1028 int32_t ipc_cursor_id,
1029 int32_t ipc_thread_id,
1030 int32_t ipc_callbacks_id,
1031 int n) {
1032 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
1033 IndexedDBCursor* idb_cursor =
1034 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
1035 if (!idb_cursor)
1036 return;
1037
1038 idb_cursor->PrefetchContinue(
1039 n,
1040 new IndexedDBCallbacks(
1041 parent_, ipc_thread_id, ipc_callbacks_id, ipc_cursor_id));
1042 }
1043
1044 void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset(
1045 int32_t ipc_cursor_id,
1046 int used_prefetches,
1047 int unused_prefetches) {
1048 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
1049 IndexedDBCursor* idb_cursor =
1050 parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
1051 if (!idb_cursor)
1052 return;
1053
1054 leveldb::Status s =
1055 idb_cursor->PrefetchReset(used_prefetches, unused_prefetches);
1056 // TODO(cmumford): Handle this error (crbug.com/363397)
1057 if (!s.ok())
1058 DLOG(ERROR) << "Unable to reset prefetch";
1059 }
1060
1061 void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed(
1062 int32_t ipc_object_id) {
1063 DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
1064 parent_->DestroyObject(&map_, ipc_object_id);
1065 }
1066
1067 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_dispatcher_host.h ('k') | content/browser/indexed_db/indexed_db_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698