1 // Copyright 2016 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/database_impl.h"
6 
7 #include <set>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/numerics/safe_math.h"
13 #include "base/sequence_checker.h"
14 #include "base/sequenced_task_runner.h"
15 #include "content/browser/indexed_db/indexed_db_callback_helpers.h"
16 #include "content/browser/indexed_db/indexed_db_connection.h"
17 #include "content/browser/indexed_db/indexed_db_context_impl.h"
18 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
19 #include "content/browser/indexed_db/indexed_db_factory_impl.h"
20 #include "content/browser/indexed_db/indexed_db_transaction.h"
21 #include "content/browser/indexed_db/transaction_impl.h"
22 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
23 
24 using blink::IndexedDBIndexKeys;
25 using blink::IndexedDBKey;
26 using blink::IndexedDBKeyPath;
27 using blink::IndexedDBKeyRange;
28 using std::swap;
29 
30 namespace blink {
31 class IndexedDBKeyRange;
32 }
33 
34 namespace content {
35 namespace {
36 
37 const char kBadTransactionMode[] = "Bad transaction mode";
38 const char kTransactionAlreadyExists[] = "Transaction already exists";
39 
40 }  // namespace
41 
DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection,const url::Origin & origin,IndexedDBDispatcherHost * dispatcher_host,scoped_refptr<base::SequencedTaskRunner> idb_runner)42 DatabaseImpl::DatabaseImpl(std::unique_ptr<IndexedDBConnection> connection,
43                            const url::Origin& origin,
44                            IndexedDBDispatcherHost* dispatcher_host,
45                            scoped_refptr<base::SequencedTaskRunner> idb_runner)
46     : dispatcher_host_(dispatcher_host),
47       indexed_db_context_(dispatcher_host->context()),
48       connection_(std::move(connection)),
49       origin_(origin),
50       idb_runner_(std::move(idb_runner)) {
51   DCHECK(idb_runner_->RunsTasksInCurrentSequence());
52   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
53   DCHECK(connection_);
54   indexed_db_context_->ConnectionOpened(origin_, connection_.get());
55 }
56 
~DatabaseImpl()57 DatabaseImpl::~DatabaseImpl() {
58   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
59   leveldb::Status status;
60   if (connection_->IsConnected()) {
61     status = connection_->AbortTransactionsAndClose(
62         IndexedDBConnection::CloseErrorHandling::kAbortAllReturnLastError);
63   }
64   indexed_db_context_->ConnectionClosed(origin_, connection_.get());
65   if (!status.ok()) {
66     indexed_db_context_->GetIDBFactory()->OnDatabaseError(
67         origin_, status, "Error during rollbacks.");
68   }
69 }
70 
RenameObjectStore(int64_t transaction_id,int64_t object_store_id,const base::string16 & new_name)71 void DatabaseImpl::RenameObjectStore(int64_t transaction_id,
72                                      int64_t object_store_id,
73                                      const base::string16& new_name) {
74   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
75   if (!connection_->IsConnected())
76     return;
77 
78   IndexedDBTransaction* transaction =
79       connection_->GetTransaction(transaction_id);
80   if (!transaction)
81     return;
82 
83   if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
84     mojo::ReportBadMessage(
85         "RenameObjectStore must be called from a version change transaction.");
86     return;
87   }
88 
89   transaction->ScheduleTask(
90       blink::mojom::IDBTaskType::Preemptive,
91       BindWeakOperation(&IndexedDBDatabase::RenameObjectStoreOperation,
92                         connection_->database()->AsWeakPtr(), object_store_id,
93                         new_name));
94 }
95 
CreateTransaction(mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction> transaction_receiver,int64_t transaction_id,const std::vector<int64_t> & object_store_ids,blink::mojom::IDBTransactionMode mode,blink::mojom::IDBTransactionDurability durability)96 void DatabaseImpl::CreateTransaction(
97     mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction>
98         transaction_receiver,
99     int64_t transaction_id,
100     const std::vector<int64_t>& object_store_ids,
101     blink::mojom::IDBTransactionMode mode,
102     blink::mojom::IDBTransactionDurability durability) {
103   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
104   if (!connection_->IsConnected())
105     return;
106 
107   if (mode != blink::mojom::IDBTransactionMode::ReadOnly &&
108       mode != blink::mojom::IDBTransactionMode::ReadWrite) {
109     mojo::ReportBadMessage(kBadTransactionMode);
110     return;
111   }
112 
113   if (connection_->GetTransaction(transaction_id)) {
114     mojo::ReportBadMessage(kTransactionAlreadyExists);
115     return;
116   }
117 
118   IndexedDBTransaction* transaction = connection_->CreateTransaction(
119       transaction_id,
120       std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode,
121       new IndexedDBBackingStore::Transaction(
122           connection_->database()->backing_store()->AsWeakPtr(), durability,
123           mode));
124   connection_->database()->RegisterAndScheduleTransaction(transaction);
125 
126   dispatcher_host_->CreateAndBindTransactionImpl(
127       std::move(transaction_receiver), origin_, transaction->AsWeakPtr());
128 }
129 
Close()130 void DatabaseImpl::Close() {
131   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
132   if (!connection_->IsConnected())
133     return;
134 
135   leveldb::Status status = connection_->AbortTransactionsAndClose(
136       IndexedDBConnection::CloseErrorHandling::kReturnOnFirstError);
137 
138   if (!status.ok()) {
139     indexed_db_context_->GetIDBFactory()->OnDatabaseError(
140         origin_, status, "Error during rollbacks.");
141   }
142 }
143 
VersionChangeIgnored()144 void DatabaseImpl::VersionChangeIgnored() {
145   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
146   if (!connection_->IsConnected())
147     return;
148 
149   connection_->VersionChangeIgnored();
150 }
151 
AddObserver(int64_t transaction_id,int32_t observer_id,bool include_transaction,bool no_records,bool values,uint32_t operation_types)152 void DatabaseImpl::AddObserver(int64_t transaction_id,
153                                int32_t observer_id,
154                                bool include_transaction,
155                                bool no_records,
156                                bool values,
157                                uint32_t operation_types) {
158   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
159   if (!connection_->IsConnected())
160     return;
161 
162   IndexedDBTransaction* transaction =
163       connection_->GetTransaction(transaction_id);
164   if (!transaction)
165     return;
166 
167   IndexedDBObserver::Options options(include_transaction, no_records, values,
168                                      operation_types);
169   connection_->database()->AddPendingObserver(transaction, observer_id,
170                                               options);
171 }
172 
RemoveObservers(const std::vector<int32_t> & observers)173 void DatabaseImpl::RemoveObservers(const std::vector<int32_t>& observers) {
174   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
175   if (!connection_->IsConnected())
176     return;
177 
178   connection_->RemoveObservers(observers);
179 }
180 
Get(int64_t transaction_id,int64_t object_store_id,int64_t index_id,const IndexedDBKeyRange & key_range,bool key_only,blink::mojom::IDBDatabase::GetCallback callback)181 void DatabaseImpl::Get(int64_t transaction_id,
182                        int64_t object_store_id,
183                        int64_t index_id,
184                        const IndexedDBKeyRange& key_range,
185                        bool key_only,
186                        blink::mojom::IDBDatabase::GetCallback callback) {
187   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
188   if (!connection_->IsConnected()) {
189     IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
190                                  "Not connected.");
191     std::move(callback).Run(blink::mojom::IDBDatabaseGetResult::NewErrorResult(
192         blink::mojom::IDBError::New(error.code(), error.message())));
193     return;
194   }
195 
196   IndexedDBTransaction* transaction =
197       connection_->GetTransaction(transaction_id);
198   if (!transaction) {
199     IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
200                                  "Unknown transaction.");
201     std::move(callback).Run(blink::mojom::IDBDatabaseGetResult::NewErrorResult(
202         blink::mojom::IDBError::New(error.code(), error.message())));
203     return;
204   }
205 
206   blink::mojom::IDBDatabase::GetCallback aborting_callback =
207       CreateCallbackAbortOnDestruct<blink::mojom::IDBDatabase::GetCallback,
208                                     blink::mojom::IDBDatabaseGetResultPtr>(
209           std::move(callback), transaction->AsWeakPtr());
210 
211   transaction->ScheduleTask(BindWeakOperation(
212       &IndexedDBDatabase::GetOperation, connection_->database()->AsWeakPtr(),
213       dispatcher_host_->AsWeakPtr(), object_store_id, index_id,
214       std::make_unique<IndexedDBKeyRange>(key_range),
215       key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
216       std::move(aborting_callback)));
217 }
218 
GetAll(int64_t transaction_id,int64_t object_store_id,int64_t index_id,const IndexedDBKeyRange & key_range,bool key_only,int64_t max_count,blink::mojom::IDBDatabase::GetAllCallback callback)219 void DatabaseImpl::GetAll(int64_t transaction_id,
220                           int64_t object_store_id,
221                           int64_t index_id,
222                           const IndexedDBKeyRange& key_range,
223                           bool key_only,
224                           int64_t max_count,
225                           blink::mojom::IDBDatabase::GetAllCallback callback) {
226   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
227   if (!connection_->IsConnected()) {
228     IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
229                                  "Not connected.");
230     std::move(callback).Run(
231         blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
232             blink::mojom::IDBError::New(error.code(), error.message())));
233     return;
234   }
235 
236   IndexedDBTransaction* transaction =
237       connection_->GetTransaction(transaction_id);
238   if (!transaction) {
239     IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
240                                  "Unknown transaction.");
241     std::move(callback).Run(
242         blink::mojom::IDBDatabaseGetAllResult::NewErrorResult(
243             blink::mojom::IDBError::New(error.code(), error.message())));
244     return;
245   }
246 
247   blink::mojom::IDBDatabase::GetAllCallback aborting_callback =
248       CreateCallbackAbortOnDestruct<blink::mojom::IDBDatabase::GetAllCallback,
249                                     blink::mojom::IDBDatabaseGetAllResultPtr>(
250           std::move(callback), transaction->AsWeakPtr());
251 
252   transaction->ScheduleTask(BindWeakOperation(
253       &IndexedDBDatabase::GetAllOperation, connection_->database()->AsWeakPtr(),
254       dispatcher_host_->AsWeakPtr(), object_store_id, index_id,
255       std::make_unique<IndexedDBKeyRange>(key_range),
256       key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE,
257       max_count, std::move(aborting_callback)));
258 }
259 
SetIndexKeys(int64_t transaction_id,int64_t object_store_id,const IndexedDBKey & primary_key,const std::vector<IndexedDBIndexKeys> & index_keys)260 void DatabaseImpl::SetIndexKeys(
261     int64_t transaction_id,
262     int64_t object_store_id,
263     const IndexedDBKey& primary_key,
264     const std::vector<IndexedDBIndexKeys>& index_keys) {
265   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
266   if (!connection_->IsConnected())
267     return;
268 
269   IndexedDBTransaction* transaction =
270       connection_->GetTransaction(transaction_id);
271   if (!transaction)
272     return;
273 
274   if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
275     mojo::ReportBadMessage(
276         "SetIndexKeys must be called from a version change transaction.");
277     return;
278   }
279 
280   transaction->ScheduleTask(
281       blink::mojom::IDBTaskType::Preemptive,
282       BindWeakOperation(&IndexedDBDatabase::SetIndexKeysOperation,
283                         connection_->database()->AsWeakPtr(), object_store_id,
284                         std::make_unique<IndexedDBKey>(primary_key),
285                         index_keys));
286 }
287 
SetIndexesReady(int64_t transaction_id,int64_t object_store_id,const std::vector<int64_t> & index_ids)288 void DatabaseImpl::SetIndexesReady(int64_t transaction_id,
289                                    int64_t object_store_id,
290                                    const std::vector<int64_t>& index_ids) {
291   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
292   if (!connection_->IsConnected())
293     return;
294 
295   IndexedDBTransaction* transaction =
296       connection_->GetTransaction(transaction_id);
297   if (!transaction)
298     return;
299 
300   if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
301     mojo::ReportBadMessage(
302         "SetIndexesReady must be called from a version change transaction.");
303     return;
304   }
305 
306   transaction->ScheduleTask(
307       blink::mojom::IDBTaskType::Preemptive,
308       BindWeakOperation(&IndexedDBDatabase::SetIndexesReadyOperation,
309                         connection_->database()->AsWeakPtr(),
310                         index_ids.size()));
311 }
312 
OpenCursor(int64_t transaction_id,int64_t object_store_id,int64_t index_id,const IndexedDBKeyRange & key_range,blink::mojom::IDBCursorDirection direction,bool key_only,blink::mojom::IDBTaskType task_type,blink::mojom::IDBDatabase::OpenCursorCallback callback)313 void DatabaseImpl::OpenCursor(
314     int64_t transaction_id,
315     int64_t object_store_id,
316     int64_t index_id,
317     const IndexedDBKeyRange& key_range,
318     blink::mojom::IDBCursorDirection direction,
319     bool key_only,
320     blink::mojom::IDBTaskType task_type,
321     blink::mojom::IDBDatabase::OpenCursorCallback callback) {
322   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
323   if (!connection_->IsConnected()) {
324     IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
325                                  "Not connected.");
326     std::move(callback).Run(
327         blink::mojom::IDBDatabaseOpenCursorResult::NewErrorResult(
328             blink::mojom::IDBError::New(error.code(), error.message())));
329     return;
330   }
331 
332   IndexedDBTransaction* transaction =
333       connection_->GetTransaction(transaction_id);
334   if (!transaction) {
335     IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
336                                  "Unknown transaction.");
337     std::move(callback).Run(
338         blink::mojom::IDBDatabaseOpenCursorResult::NewErrorResult(
339             blink::mojom::IDBError::New(error.code(), error.message())));
340     return;
341   }
342 
343   blink::mojom::IDBDatabase::OpenCursorCallback aborting_callback =
344       CreateCallbackAbortOnDestruct<
345           blink::mojom::IDBDatabase::OpenCursorCallback,
346           blink::mojom::IDBDatabaseOpenCursorResultPtr>(
347           std::move(callback), transaction->AsWeakPtr());
348 
349   if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange &&
350       task_type == blink::mojom::IDBTaskType::Preemptive) {
351     mojo::ReportBadMessage(
352         "OpenCursor with |Preemptive| task type must be called from a version "
353         "change transaction.");
354     return;
355   }
356 
357   std::unique_ptr<IndexedDBDatabase::OpenCursorOperationParams> params(
358       std::make_unique<IndexedDBDatabase::OpenCursorOperationParams>());
359   params->object_store_id = object_store_id;
360   params->index_id = index_id;
361   params->key_range = std::make_unique<IndexedDBKeyRange>(key_range);
362   params->direction = direction;
363   params->cursor_type =
364       key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE;
365   params->task_type = task_type;
366   params->callback = std::move(aborting_callback);
367   transaction->ScheduleTask(
368       BindWeakOperation(&IndexedDBDatabase::OpenCursorOperation,
369                         connection_->database()->AsWeakPtr(), std::move(params),
370                         origin_, dispatcher_host_->AsWeakPtr()));
371 }
372 
Count(int64_t transaction_id,int64_t object_store_id,int64_t index_id,const IndexedDBKeyRange & key_range,mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks> pending_callbacks)373 void DatabaseImpl::Count(
374     int64_t transaction_id,
375     int64_t object_store_id,
376     int64_t index_id,
377     const IndexedDBKeyRange& key_range,
378     mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks>
379         pending_callbacks) {
380   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
381   scoped_refptr<IndexedDBCallbacks> callbacks(
382       new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
383                              std::move(pending_callbacks), idb_runner_));
384   if (!connection_->IsConnected())
385     return;
386 
387   IndexedDBTransaction* transaction =
388       connection_->GetTransaction(transaction_id);
389   if (!transaction)
390     return;
391 
392   transaction->ScheduleTask(BindWeakOperation(
393       &IndexedDBDatabase::CountOperation, connection_->database()->AsWeakPtr(),
394       object_store_id, index_id,
395       std::make_unique<blink::IndexedDBKeyRange>(key_range),
396       std::move(callbacks)));
397 }
398 
DeleteRange(int64_t transaction_id,int64_t object_store_id,const IndexedDBKeyRange & key_range,mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks> pending_callbacks)399 void DatabaseImpl::DeleteRange(
400     int64_t transaction_id,
401     int64_t object_store_id,
402     const IndexedDBKeyRange& key_range,
403     mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks>
404         pending_callbacks) {
405   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
406   scoped_refptr<IndexedDBCallbacks> callbacks(
407       new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
408                              std::move(pending_callbacks), idb_runner_));
409   if (!connection_->IsConnected())
410     return;
411 
412   IndexedDBTransaction* transaction =
413       connection_->GetTransaction(transaction_id);
414   if (!transaction)
415     return;
416 
417   transaction->ScheduleTask(BindWeakOperation(
418       &IndexedDBDatabase::DeleteRangeOperation,
419       connection_->database()->AsWeakPtr(), object_store_id,
420       std::make_unique<IndexedDBKeyRange>(key_range), std::move(callbacks)));
421 }
422 
GetKeyGeneratorCurrentNumber(int64_t transaction_id,int64_t object_store_id,mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks> pending_callbacks)423 void DatabaseImpl::GetKeyGeneratorCurrentNumber(
424     int64_t transaction_id,
425     int64_t object_store_id,
426     mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks>
427         pending_callbacks) {
428   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
429   scoped_refptr<IndexedDBCallbacks> callbacks(
430       new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
431                              std::move(pending_callbacks), idb_runner_));
432   if (!connection_->IsConnected())
433     return;
434 
435   IndexedDBTransaction* transaction =
436       connection_->GetTransaction(transaction_id);
437   if (!transaction)
438     return;
439 
440   transaction->ScheduleTask(BindWeakOperation(
441       &IndexedDBDatabase::GetKeyGeneratorCurrentNumberOperation,
442       connection_->database()->AsWeakPtr(), object_store_id,
443       std::move(callbacks)));
444 }
445 
Clear(int64_t transaction_id,int64_t object_store_id,mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks> pending_callbacks)446 void DatabaseImpl::Clear(
447     int64_t transaction_id,
448     int64_t object_store_id,
449     mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks>
450         pending_callbacks) {
451   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
452   scoped_refptr<IndexedDBCallbacks> callbacks(
453       new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_,
454                              std::move(pending_callbacks), idb_runner_));
455   if (!connection_->IsConnected())
456     return;
457 
458   IndexedDBTransaction* transaction =
459       connection_->GetTransaction(transaction_id);
460   if (!transaction)
461     return;
462 
463   transaction->ScheduleTask(BindWeakOperation(
464       &IndexedDBDatabase::ClearOperation, connection_->database()->AsWeakPtr(),
465       object_store_id, std::move(callbacks)));
466 }
467 
CreateIndex(int64_t transaction_id,int64_t object_store_id,int64_t index_id,const base::string16 & name,const IndexedDBKeyPath & key_path,bool unique,bool multi_entry)468 void DatabaseImpl::CreateIndex(int64_t transaction_id,
469                                int64_t object_store_id,
470                                int64_t index_id,
471                                const base::string16& name,
472                                const IndexedDBKeyPath& key_path,
473                                bool unique,
474                                bool multi_entry) {
475   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
476   if (!connection_->IsConnected())
477     return;
478 
479   IndexedDBTransaction* transaction =
480       connection_->GetTransaction(transaction_id);
481   if (!transaction)
482     return;
483 
484   if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
485     mojo::ReportBadMessage(
486         "CreateIndex must be called from a version change transaction.");
487     return;
488   }
489 
490   transaction->ScheduleTask(
491       blink::mojom::IDBTaskType::Preemptive,
492       BindWeakOperation(&IndexedDBDatabase::CreateIndexOperation,
493                         connection_->database()->AsWeakPtr(), object_store_id,
494                         index_id, name, key_path, unique, multi_entry));
495 }
496 
DeleteIndex(int64_t transaction_id,int64_t object_store_id,int64_t index_id)497 void DatabaseImpl::DeleteIndex(int64_t transaction_id,
498                                int64_t object_store_id,
499                                int64_t index_id) {
500   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
501   if (!connection_->IsConnected())
502     return;
503 
504   IndexedDBTransaction* transaction =
505       connection_->GetTransaction(transaction_id);
506   if (!transaction)
507     return;
508 
509   if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
510     mojo::ReportBadMessage(
511         "DeleteIndex must be called from a version change transaction.");
512     return;
513   }
514 
515   transaction->ScheduleTask(BindWeakOperation(
516       &IndexedDBDatabase::DeleteIndexOperation,
517       connection_->database()->AsWeakPtr(), object_store_id, index_id));
518 }
519 
RenameIndex(int64_t transaction_id,int64_t object_store_id,int64_t index_id,const base::string16 & new_name)520 void DatabaseImpl::RenameIndex(int64_t transaction_id,
521                                int64_t object_store_id,
522                                int64_t index_id,
523                                const base::string16& new_name) {
524   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
525   if (!connection_->IsConnected())
526     return;
527 
528   IndexedDBTransaction* transaction =
529       connection_->GetTransaction(transaction_id);
530   if (!transaction)
531     return;
532 
533   if (transaction->mode() != blink::mojom::IDBTransactionMode::VersionChange) {
534     mojo::ReportBadMessage(
535         "RenameIndex must be called from a version change transaction.");
536     return;
537   }
538 
539   transaction->ScheduleTask(
540       BindWeakOperation(&IndexedDBDatabase::RenameIndexOperation,
541                         connection_->database()->AsWeakPtr(), object_store_id,
542                         index_id, new_name));
543 }
544 
Abort(int64_t transaction_id)545 void DatabaseImpl::Abort(int64_t transaction_id) {
546   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
547   if (!connection_->IsConnected())
548     return;
549 
550   IndexedDBTransaction* transaction =
551       connection_->GetTransaction(transaction_id);
552   if (!transaction)
553     return;
554 
555   connection_->AbortTransactionAndTearDownOnError(
556       transaction,
557       IndexedDBDatabaseError(blink::mojom::IDBException::kAbortError,
558                              "Transaction aborted by user."));
559 }
560 
561 }  // namespace content
562